[open-ils-commits] r18371 - in branches/serials-integration: . Open-ILS Open-ILS/examples Open-ILS/examples/apache Open-ILS/src Open-ILS/src/edi_translator Open-ILS/src/edi_translator/data Open-ILS/src/extras Open-ILS/src/extras/import Open-ILS/src/perlmods/OpenILS Open-ILS/src/perlmods/OpenILS/Application Open-ILS/src/perlmods/OpenILS/Application/Acq Open-ILS/src/perlmods/OpenILS/Application/Actor Open-ILS/src/perlmods/OpenILS/Application/Cat Open-ILS/src/perlmods/OpenILS/Application/Circ Open-ILS/src/perlmods/OpenILS/Application/Search Open-ILS/src/perlmods/OpenILS/Application/Storage/CDBI Open-ILS/src/perlmods/OpenILS/Application/Storage/Driver/Pg Open-ILS/src/perlmods/OpenILS/Application/Storage/Publisher Open-ILS/src/perlmods/OpenILS/Application/Trigger Open-ILS/src/perlmods/OpenILS/Application/Trigger/Validator/Acq Open-ILS/src/perlmods/OpenILS/SIP Open-ILS/src/perlmods/OpenILS/SIP/Transaction Open-ILS/src/perlmods/OpenILS/Utils Open-ILS/src/perlmods/OpenILS/WWW Open-ILS/src/perlmods/OpenILS/WWW/AddedContent Open-ILS/src/reporter Open-ILS/src/sql/Pg Open-ILS/src/sql/Pg/upgrade Open-ILS/src/support-scripts Open-ILS/src/support-scripts/test-scripts Open-ILS/tests/datasets Open-ILS/tests/datasets/edi_scratch Open-ILS/web Open-ILS/web/css/skin Open-ILS/web/css/skin/default Open-ILS/web/images Open-ILS/web/js/dojo/MARC Open-ILS/web/js/dojo/fieldmapper Open-ILS/web/js/dojo/openils Open-ILS/web/js/dojo/openils/acq Open-ILS/web/js/dojo/openils/acq/nls Open-ILS/web/js/dojo/openils/actor/nls Open-ILS/web/js/dojo/openils/conify/nls Open-ILS/web/js/dojo/openils/opac/nls Open-ILS/web/js/dojo/openils/widget Open-ILS/web/js/dojo/openils/widget/nls Open-ILS/web/js/ui/default Open-ILS/web/js/ui/default/acq/common Open-ILS/web/js/ui/default/acq/financial Open-ILS/web/js/ui/default/acq/invoice Open-ILS/web/js/ui/default/acq/po Open-ILS/web/js/ui/default/acq/search Open-ILS/web/js/ui/default/actor/user Open-ILS/web/js/ui/default/booking Open-ILS/web/js/ui/default/circ/selfcheck Open-ILS/web/js/ui/default/conify/global/acq Open-ILS/web/js/ui/default/conify/global/asset Open-ILS/web/js/ui/default/vandelay Open-ILS/web/opac/common/js Open-ILS/web/opac/locale/en-US Open-ILS/web/opac/skin/craftsman/js Open-ILS/web/opac/skin/craftsman/xml/rdetail Open-ILS/web/opac/skin/craftsman/xml/result Open-ILS/web/opac/skin/default/js Open-ILS/web/opac/skin/default/xml/common Open-ILS/web/opac/skin/default/xml/rdetail Open-ILS/web/templates Open-ILS/web/templates/default Open-ILS/web/templates/default/acq/common Open-ILS/web/templates/default/acq/financial Open-ILS/web/templates/default/acq/invoice Open-ILS/web/templates/default/acq/lineitem Open-ILS/web/templates/default/acq/picklist Open-ILS/web/templates/default/acq/po Open-ILS/web/templates/default/acq/receiving Open-ILS/web/templates/default/acq/search Open-ILS/web/templates/default/acq/settings Open-ILS/web/templates/default/actor/user Open-ILS/web/templates/default/booking Open-ILS/web/templates/default/circ/selfcheck Open-ILS/web/templates/default/conify/global/acq Open-ILS/web/templates/default/conify/global/asset Open-ILS/web/templates/default/conify/global/booking Open-ILS/web/templates/default/conify/global/config Open-ILS/web/templates/default/vandelay/inc Open-ILS/xsl Open-ILS/xul/staff_client Open-ILS/xul/staff_client/chrome/content/OpenILS Open-ILS/xul/staff_client/chrome/content/auth Open-ILS/xul/staff_client/chrome/content/cat Open-ILS/xul/staff_client/chrome/content/circ Open-ILS/xul/staff_client/chrome/content/main Open-ILS/xul/staff_client/chrome/content/util Open-ILS/xul/staff_client/chrome/locale/en-US Open-ILS/xul/staff_client/chrome/skin Open-ILS/xul/staff_client/defaults/preferences Open-ILS/xul/staff_client/external Open-ILS/xul/staff_client/server/OpenILS Open-ILS/xul/staff_client/server/admin Open-ILS/xul/staff_client/server/cat Open-ILS/xul/staff_client/server/circ Open-ILS/xul/staff_client/server/locale/en-US Open-ILS/xul/staff_client/server/patron Open-ILS/xul/staff_client/server/serial Open-ILS/xul/staff_client/server/skin build/i18n/po/opac.js build/tools (dbwells)

svn at svn.open-ils.org svn at svn.open-ils.org
Mon Oct 18 09:47:00 EDT 2010


Author: dbwells
Date: 2010-10-18 09:46:56 -0400 (Mon, 18 Oct 2010)
New Revision: 18371

Added:
   branches/serials-integration/Open-ILS/examples/list_perms.pl
   branches/serials-integration/Open-ILS/src/edi_translator/data/BakerAndTaylor/
   branches/serials-integration/Open-ILS/src/edi_translator/data/bergware/
   branches/serials-integration/Open-ILS/src/edi_translator/data/brodart/
   branches/serials-integration/Open-ILS/src/edi_translator/data/edidev.net/
   branches/serials-integration/Open-ILS/src/edi_translator/data/ingram/
   branches/serials-integration/Open-ILS/src/edi_translator/data/misc/
   branches/serials-integration/Open-ILS/src/edi_translator/data/sources.txt
   branches/serials-integration/Open-ILS/src/edi_translator/data/stylus/
   branches/serials-integration/Open-ILS/src/edi_translator/data/test_output/
   branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Utils/ISBN.pm
   branches/serials-integration/Open-ILS/src/sql/Pg/1.6.1-2.0-upgrade-db.sql
   branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0376.data.merge_auth_perms.sql
   branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0377.schema.actor.card.barcode-lower-index.sql
   branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0378.data.fix_org_unit_setting_types.sql
   branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0379.data.org-setting-circ.missing_pieces.copy_status.sql
   branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0380.data.spine_label.sql
   branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0381.data.spine_label_font_weight.sql
   branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0382.schema.asset_copy_location_callnums.sql
   branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0383.data.org-setting-circ.do_not_tally_claims_returned.sql
   branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0384.data.hold_pull_list_template.sql
   branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0385.schema.perm_list_fkeys.sql
   branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0386.data.org-setting-patron-clone-copy-addr.sql
   branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0387.schema.perm_list_fkeys_restrict_delete.sql
   branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0388.data.org-setting-ui.patron.editor_defaults.sql
   branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0389.data.issuance-holds.sql
   branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0390.schema.usrgroup-index.sql
   branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0391.schema.copy_note_owner_index.sql
   branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0392.data.org-setting-ui.patron.editor_address_requirement.sql
   branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0393.schema.perm-id-change-i18n-protection.sql
   branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0394.data.org-setting-cat.default_classification_scheme.sql
   branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0395.schema.fix-i18n-fixer.sql
   branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0396.data.org-setting-payflowpro.sql
   branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0397.data.coust.opac_fully_compresssed.sql
   branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0398.schema.serials-indexes.sql
   branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0399.schema.strict-renewal-test.sql
   branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0400.schema.unique_authority_index.sql
   branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0401.schema.authority_record_entry_drop_arn.sql
   branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0402.schema.unique_authority_index_revisited.sql
   branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0403.schema.serials-tweaks.sql
   branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0404.schema.acq-provider-contact-null-null.sql
   branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0405.schema.acq-hold-copy-map-drop-fkey.sql
   branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0406.schema.hold-matrix.user-not-requestor.sql
   branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0407.data.serial-perm.sql
   branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0408.schema.update_maintain_901.sql
   branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0409.data.receive-serial-perm.sql
   branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0410.schema.allow_parallel_reingest.sql
   branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0411.schema.assume_inserts_only_flag.sql
   branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0412.data.trigger.validator.HoldIsCancelled.sql
   branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0413.schema.upgrade-auditor-tables.sql
   branches/serials-integration/Open-ILS/tests/datasets/edi_scratch/
   branches/serials-integration/Open-ILS/updates/
   branches/serials-integration/Open-ILS/web/css/skin/default/register.css
   branches/serials-integration/Open-ILS/web/css/skin/default/serial.css
   branches/serials-integration/Open-ILS/web/images/dimple.png
   branches/serials-integration/Open-ILS/web/images/licenses.txt
   branches/serials-integration/Open-ILS/web/js/dojo/openils/widget/HoldingCode.js
   branches/serials-integration/Open-ILS/web/js/ui/default/cat/
   branches/serials-integration/Open-ILS/web/js/ui/default/conify/global/asset/copy_template.js
   branches/serials-integration/Open-ILS/web/js/ui/default/serial/
   branches/serials-integration/Open-ILS/web/templates/default/cat/
   branches/serials-integration/Open-ILS/web/templates/default/conify/global/asset/copy_template.tt2
   branches/serials-integration/Open-ILS/web/templates/default/conify/global/config/rule_age_hold_protect.tt2
   branches/serials-integration/Open-ILS/web/templates/default/conify/global/config/rule_circ_duration.tt2
   branches/serials-integration/Open-ILS/web/templates/default/conify/global/config/rule_max_fine.tt2
   branches/serials-integration/Open-ILS/web/templates/default/conify/global/config/rule_recurring_fine.tt2
   branches/serials-integration/Open-ILS/web/templates/default/serial/
   branches/serials-integration/Open-ILS/xul/staff_client/defaults/preferences/autoupdate.js
   branches/serials-integration/Open-ILS/xul/staff_client/external/make_updates.sh
   branches/serials-integration/Open-ILS/xul/staff_client/server/locale/en-US/marcedit-tooltips-authority.xml
   branches/serials-integration/Open-ILS/xul/staff_client/server/locale/en-US/marcedit-tooltips-mfhd.xml
   branches/serials-integration/Open-ILS/xul/staff_client/server/serial/batch_receive.js
   branches/serials-integration/Open-ILS/xul/staff_client/server/serial/batch_receive.xul
   branches/serials-integration/Open-ILS/xul/staff_client/server/serial/batch_receive_overlay.xul
   branches/serials-integration/Open-ILS/xul/staff_client/server/serial/common.js
   branches/serials-integration/Open-ILS/xul/staff_client/server/serial/pattern_wizard.js
   branches/serials-integration/Open-ILS/xul/staff_client/server/serial/pattern_wizard.xul
   branches/serials-integration/Open-ILS/xul/staff_client/server/serial/pattern_wizard_overlay.xul
   branches/serials-integration/Open-ILS/xul/staff_client/server/skin/serial.css
   branches/serials-integration/Open-ILS/xul/staff_client/update.rdf
   branches/serials-integration/Open-ILS/xul/staff_client/windowssetup.nsi
   branches/serials-integration/build/i18n/po/opac.js/opac.js.pot
Removed:
   branches/serials-integration/Open-ILS/src/cgi-bin/
   branches/serials-integration/Open-ILS/src/support-scripts/test-scripts/edi_object.pl
   branches/serials-integration/Open-ILS/src/support-scripts/test-scripts/ordrsp_parse.pl
Modified:
   branches/serials-integration/
   branches/serials-integration/Makefile.am
   branches/serials-integration/Open-ILS/examples/apache/eg.conf
   branches/serials-integration/Open-ILS/examples/apache/eg_vhost.conf
   branches/serials-integration/Open-ILS/examples/fm_IDL.xml
   branches/serials-integration/Open-ILS/examples/oils_ctl.sh
   branches/serials-integration/Open-ILS/examples/oils_sip.xml.example
   branches/serials-integration/Open-ILS/examples/openils.profile.js
   branches/serials-integration/Open-ILS/examples/opensrf.xml.example
   branches/serials-integration/Open-ILS/src/Makefile.am
   branches/serials-integration/Open-ILS/src/edi_translator/README
   branches/serials-integration/Open-ILS/src/edi_translator/test_client.pl
   branches/serials-integration/Open-ILS/src/extras/Makefile.install
   branches/serials-integration/Open-ILS/src/extras/ils_events.xml
   branches/serials-integration/Open-ILS/src/extras/import/marc2are.pl
   branches/serials-integration/Open-ILS/src/extras/import/marc_add_ids
   branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application.pm
   branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Acq/EDI.pm
   branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Acq/Invoice.pm
   branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Acq/Lineitem.pm
   branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Acq/Order.pm
   branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Actor.pm
   branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Actor/UserGroups.pm
   branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Booking.pm
   branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Cat.pm
   branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Cat/AuthCommon.pm
   branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Cat/Authority.pm
   branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Cat/BibCommon.pm
   branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Circ/Circulate.pm
   branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Circ/CopyLocations.pm
   branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Circ/CreditCard.pm
   branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Circ/Holds.pm
   branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Fielder.pm
   branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Search/Biblio.pm
   branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Search/Serial.pm
   branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Serial.pm
   branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Storage/CDBI/authority.pm
   branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Storage/Driver/Pg/QueryParser.pm
   branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Storage/Publisher/action.pm
   branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Storage/Publisher/actor.pm
   branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Storage/Publisher/asset.pm
   branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Storage/Publisher/biblio.pm
   branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Storage/Publisher/metabib.pm
   branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/SuperCat.pm
   branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Trigger/Reactor.pm
   branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Trigger/Validator.pm
   branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Trigger/Validator/Acq/PurchaseOrderEDIRequired.pm
   branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Vandelay.pm
   branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Const.pm
   branches/serials-integration/Open-ILS/src/perlmods/OpenILS/SIP.pm
   branches/serials-integration/Open-ILS/src/perlmods/OpenILS/SIP/Item.pm
   branches/serials-integration/Open-ILS/src/perlmods/OpenILS/SIP/Patron.pm
   branches/serials-integration/Open-ILS/src/perlmods/OpenILS/SIP/Transaction/Checkin.pm
   branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Utils/Cronscript.pm
   branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Utils/MFHD.pm
   branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Utils/OfflineStore.pm
   branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Utils/RemoteAccount.pm
   branches/serials-integration/Open-ILS/src/perlmods/OpenILS/WWW/AddedContent/ContentCafe.pm
   branches/serials-integration/Open-ILS/src/perlmods/OpenILS/WWW/Exporter.pm
   branches/serials-integration/Open-ILS/src/perlmods/OpenILS/WWW/Method.pm
   branches/serials-integration/Open-ILS/src/perlmods/OpenILS/WWW/Redirect.pm
   branches/serials-integration/Open-ILS/src/perlmods/OpenILS/WWW/SuperCat.pm
   branches/serials-integration/Open-ILS/src/perlmods/OpenILS/WWW/Web.pm
   branches/serials-integration/Open-ILS/src/reporter/clark-kent.pl
   branches/serials-integration/Open-ILS/src/sql/Pg/002.functions.config.sql
   branches/serials-integration/Open-ILS/src/sql/Pg/002.schema.config.sql
   branches/serials-integration/Open-ILS/src/sql/Pg/005.schema.actors.sql
   branches/serials-integration/Open-ILS/src/sql/Pg/006.schema.permissions.sql
   branches/serials-integration/Open-ILS/src/sql/Pg/011.schema.authority.sql
   branches/serials-integration/Open-ILS/src/sql/Pg/020.schema.functions.sql
   branches/serials-integration/Open-ILS/src/sql/Pg/030.schema.metabib.sql
   branches/serials-integration/Open-ILS/src/sql/Pg/040.schema.asset.sql
   branches/serials-integration/Open-ILS/src/sql/Pg/100.circ_matrix.sql
   branches/serials-integration/Open-ILS/src/sql/Pg/110.hold_matrix.sql
   branches/serials-integration/Open-ILS/src/sql/Pg/200.schema.acq.sql
   branches/serials-integration/Open-ILS/src/sql/Pg/210.schema.serials.sql
   branches/serials-integration/Open-ILS/src/sql/Pg/800.fkeys.sql
   branches/serials-integration/Open-ILS/src/sql/Pg/950.data.seed-values.sql
   branches/serials-integration/Open-ILS/src/support-scripts/clear_expired_circ_history.srfsh
   branches/serials-integration/Open-ILS/src/support-scripts/edi_fetcher.pl
   branches/serials-integration/Open-ILS/src/support-scripts/edi_pusher.pl
   branches/serials-integration/Open-ILS/src/support-scripts/eg_db_config.pl
   branches/serials-integration/Open-ILS/src/support-scripts/settings-tester.pl
   branches/serials-integration/Open-ILS/src/support-scripts/test-scripts/ftp_ls.pl
   branches/serials-integration/Open-ILS/web/Makefile.am
   branches/serials-integration/Open-ILS/web/css/skin/default.css
   branches/serials-integration/Open-ILS/web/js/dojo/MARC/Field.js
   branches/serials-integration/Open-ILS/web/js/dojo/MARC/Record.js
   branches/serials-integration/Open-ILS/web/js/dojo/fieldmapper/Fieldmapper.js
   branches/serials-integration/Open-ILS/web/js/dojo/fieldmapper/IDL.js
   branches/serials-integration/Open-ILS/web/js/dojo/fieldmapper/dojoData.js
   branches/serials-integration/Open-ILS/web/js/dojo/openils/BibTemplate.js
   branches/serials-integration/Open-ILS/web/js/dojo/openils/I18N.js
   branches/serials-integration/Open-ILS/web/js/dojo/openils/PermaCrud.js
   branches/serials-integration/Open-ILS/web/js/dojo/openils/User.js
   branches/serials-integration/Open-ILS/web/js/dojo/openils/Util.js
   branches/serials-integration/Open-ILS/web/js/dojo/openils/XUL.js
   branches/serials-integration/Open-ILS/web/js/dojo/openils/acq/Lineitem.js
   branches/serials-integration/Open-ILS/web/js/dojo/openils/acq/nls/acq.js
   branches/serials-integration/Open-ILS/web/js/dojo/openils/actor/nls/register.js
   branches/serials-integration/Open-ILS/web/js/dojo/openils/conify/nls/conify.js
   branches/serials-integration/Open-ILS/web/js/dojo/openils/opac/nls/opac.js
   branches/serials-integration/Open-ILS/web/js/dojo/openils/widget/AutoFieldWidget.js
   branches/serials-integration/Open-ILS/web/js/dojo/openils/widget/AutoGrid.js
   branches/serials-integration/Open-ILS/web/js/dojo/openils/widget/AutoWidget.js
   branches/serials-integration/Open-ILS/web/js/dojo/openils/widget/EditPane.js
   branches/serials-integration/Open-ILS/web/js/dojo/openils/widget/FacetSidebar.js
   branches/serials-integration/Open-ILS/web/js/dojo/openils/widget/FilteringTreeSelect.js
   branches/serials-integration/Open-ILS/web/js/dojo/openils/widget/Searcher.js
   branches/serials-integration/Open-ILS/web/js/dojo/openils/widget/nls/Searcher.js
   branches/serials-integration/Open-ILS/web/js/ui/default/acq/common/li_table.js
   branches/serials-integration/Open-ILS/web/js/ui/default/acq/financial/view_fund.js
   branches/serials-integration/Open-ILS/web/js/ui/default/acq/invoice/view.js
   branches/serials-integration/Open-ILS/web/js/ui/default/acq/po/view_po.js
   branches/serials-integration/Open-ILS/web/js/ui/default/acq/search/invoice.js
   branches/serials-integration/Open-ILS/web/js/ui/default/acq/search/unified.js
   branches/serials-integration/Open-ILS/web/js/ui/default/actor/user/register.js
   branches/serials-integration/Open-ILS/web/js/ui/default/booking/reservation.js
   branches/serials-integration/Open-ILS/web/js/ui/default/circ/selfcheck/selfcheck.js
   branches/serials-integration/Open-ILS/web/js/ui/default/conify/global/acq/distribution_formula.js
   branches/serials-integration/Open-ILS/web/js/ui/default/vandelay/vandelay.js
   branches/serials-integration/Open-ILS/web/opac/common/js/config.js
   branches/serials-integration/Open-ILS/web/opac/locale/en-US/lang.dtd
   branches/serials-integration/Open-ILS/web/opac/locale/en-US/opac.dtd
   branches/serials-integration/Open-ILS/web/opac/skin/craftsman/js/rdetail.js
   branches/serials-integration/Open-ILS/web/opac/skin/craftsman/xml/rdetail/rdetail_extras.xml
   branches/serials-integration/Open-ILS/web/opac/skin/craftsman/xml/result/result_table.xml
   branches/serials-integration/Open-ILS/web/opac/skin/default/js/container.js
   branches/serials-integration/Open-ILS/web/opac/skin/default/js/holds.js
   branches/serials-integration/Open-ILS/web/opac/skin/default/js/rdetail.js
   branches/serials-integration/Open-ILS/web/opac/skin/default/js/result_common.js
   branches/serials-integration/Open-ILS/web/opac/skin/default/xml/common/holds.xml
   branches/serials-integration/Open-ILS/web/opac/skin/default/xml/common/js_common.xml
   branches/serials-integration/Open-ILS/web/opac/skin/default/xml/rdetail/rdetail_summary.xml
   branches/serials-integration/Open-ILS/web/templates/base.tt2
   branches/serials-integration/Open-ILS/web/templates/default/acq/common/inv_dialog.tt2
   branches/serials-integration/Open-ILS/web/templates/default/acq/common/jubgrid.tt2
   branches/serials-integration/Open-ILS/web/templates/default/acq/common/li_table.tt2
   branches/serials-integration/Open-ILS/web/templates/default/acq/common/li_table_pager.tt2
   branches/serials-integration/Open-ILS/web/templates/default/acq/financial/list_funds.tt2
   branches/serials-integration/Open-ILS/web/templates/default/acq/financial/view_fund.tt2
   branches/serials-integration/Open-ILS/web/templates/default/acq/financial/view_funding_source.tt2
   branches/serials-integration/Open-ILS/web/templates/default/acq/invoice/view.tt2
   branches/serials-integration/Open-ILS/web/templates/default/acq/lineitem/findbib.tt2
   branches/serials-integration/Open-ILS/web/templates/default/acq/lineitem/related.tt2
   branches/serials-integration/Open-ILS/web/templates/default/acq/lineitem/search.tt2
   branches/serials-integration/Open-ILS/web/templates/default/acq/lineitem/worksheet.tt2
   branches/serials-integration/Open-ILS/web/templates/default/acq/picklist/bib_search.tt2
   branches/serials-integration/Open-ILS/web/templates/default/acq/picklist/brief_record.tt2
   branches/serials-integration/Open-ILS/web/templates/default/acq/picklist/from_bib.tt2
   branches/serials-integration/Open-ILS/web/templates/default/acq/picklist/list.tt2
   branches/serials-integration/Open-ILS/web/templates/default/acq/picklist/upload.tt2
   branches/serials-integration/Open-ILS/web/templates/default/acq/picklist/user_request.tt2
   branches/serials-integration/Open-ILS/web/templates/default/acq/picklist/view.tt2
   branches/serials-integration/Open-ILS/web/templates/default/acq/po/events.tt2
   branches/serials-integration/Open-ILS/web/templates/default/acq/po/search.tt2
   branches/serials-integration/Open-ILS/web/templates/default/acq/po/view.tt2
   branches/serials-integration/Open-ILS/web/templates/default/acq/receiving/process.tt2
   branches/serials-integration/Open-ILS/web/templates/default/acq/search/unified.tt2
   branches/serials-integration/Open-ILS/web/templates/default/acq/settings/li_attr.tt2
   branches/serials-integration/Open-ILS/web/templates/default/actor/user/register.tt2
   branches/serials-integration/Open-ILS/web/templates/default/actor/user/register_table.tt2
   branches/serials-integration/Open-ILS/web/templates/default/booking/capture.tt2
   branches/serials-integration/Open-ILS/web/templates/default/booking/pickup.tt2
   branches/serials-integration/Open-ILS/web/templates/default/booking/pull_list.tt2
   branches/serials-integration/Open-ILS/web/templates/default/booking/reservation.tt2
   branches/serials-integration/Open-ILS/web/templates/default/booking/return.tt2
   branches/serials-integration/Open-ILS/web/templates/default/circ/selfcheck/main.tt2
   branches/serials-integration/Open-ILS/web/templates/default/conify/global/acq/distribution_formula.tt2
   branches/serials-integration/Open-ILS/web/templates/default/conify/global/acq/edi_account.tt2
   branches/serials-integration/Open-ILS/web/templates/default/conify/global/booking/resource_type.tt2
   branches/serials-integration/Open-ILS/web/templates/default/vandelay/inc/item_attrs.tt2
   branches/serials-integration/Open-ILS/xsl/ATOM2XHTML.xsl
   branches/serials-integration/Open-ILS/xsl/MARC21slim2HTMLCard-holdings.xsl
   branches/serials-integration/Open-ILS/xul/staff_client/Makefile.am
   branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/OpenILS/data.js
   branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/auth/controller.js
   branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/auth/session.js
   branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/cat/opac.js
   branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/cat/opac.xul
   branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/circ/offline.js
   branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/circ/offline_checkin.js
   branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/circ/offline_checkout.js
   branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/circ/offline_in_house_use.js
   branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/circ/offline_renew.js
   branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/main/bindings.xml
   branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/main/constants.js
   branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/main/main.js
   branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/main/main.xul
   branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/main/menu.js
   branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/main/menu_frame_menus.xul
   branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/main/menu_frame_overlay.xul
   branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/util/browser.js
   branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/util/browser.xul
   branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/util/list.js
   branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/util/print.js
   branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/util/rbrowser.xul
   branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/util/widgets.js
   branches/serials-integration/Open-ILS/xul/staff_client/chrome/locale/en-US/offline.properties
   branches/serials-integration/Open-ILS/xul/staff_client/chrome/skin/global.css
   branches/serials-integration/Open-ILS/xul/staff_client/defaults/preferences/prefs.js
   branches/serials-integration/Open-ILS/xul/staff_client/install.rdf
   branches/serials-integration/Open-ILS/xul/staff_client/server/OpenILS/util_overlay.xul
   branches/serials-integration/Open-ILS/xul/staff_client/server/admin/copy_locations.js
   branches/serials-integration/Open-ILS/xul/staff_client/server/admin/copy_locations.xhtml
   branches/serials-integration/Open-ILS/xul/staff_client/server/admin/printer_settings.html
   branches/serials-integration/Open-ILS/xul/staff_client/server/admin/printer_settings.js
   branches/serials-integration/Open-ILS/xul/staff_client/server/cat/bib_brief_overlay.js
   branches/serials-integration/Open-ILS/xul/staff_client/server/cat/bib_brief_overlay.xul
   branches/serials-integration/Open-ILS/xul/staff_client/server/cat/copy_browser.js
   branches/serials-integration/Open-ILS/xul/staff_client/server/cat/copy_browser.xul
   branches/serials-integration/Open-ILS/xul/staff_client/server/cat/copy_editor.js
   branches/serials-integration/Open-ILS/xul/staff_client/server/cat/marcedit.js
   branches/serials-integration/Open-ILS/xul/staff_client/server/cat/marcedit.xul
   branches/serials-integration/Open-ILS/xul/staff_client/server/cat/spine_labels.js
   branches/serials-integration/Open-ILS/xul/staff_client/server/cat/spine_labels.xul
   branches/serials-integration/Open-ILS/xul/staff_client/server/cat/volume_copy_creator.js
   branches/serials-integration/Open-ILS/xul/staff_client/server/cat/z3950.js
   branches/serials-integration/Open-ILS/xul/staff_client/server/circ/alternate_copy_summary.js
   branches/serials-integration/Open-ILS/xul/staff_client/server/circ/alternate_copy_summary.xul
   branches/serials-integration/Open-ILS/xul/staff_client/server/circ/checkin.js
   branches/serials-integration/Open-ILS/xul/staff_client/server/circ/checkout.js
   branches/serials-integration/Open-ILS/xul/staff_client/server/circ/pre_cat_fields.xul
   branches/serials-integration/Open-ILS/xul/staff_client/server/circ/util.js
   branches/serials-integration/Open-ILS/xul/staff_client/server/locale/en-US/cat.properties
   branches/serials-integration/Open-ILS/xul/staff_client/server/locale/en-US/circ.properties
   branches/serials-integration/Open-ILS/xul/staff_client/server/locale/en-US/common.properties
   branches/serials-integration/Open-ILS/xul/staff_client/server/locale/en-US/marcedit-tooltips.xml
   branches/serials-integration/Open-ILS/xul/staff_client/server/locale/en-US/patron.properties
   branches/serials-integration/Open-ILS/xul/staff_client/server/locale/en-US/serial.properties
   branches/serials-integration/Open-ILS/xul/staff_client/server/patron/bill2.js
   branches/serials-integration/Open-ILS/xul/staff_client/server/patron/bill2.xul
   branches/serials-integration/Open-ILS/xul/staff_client/server/patron/bill_details.js
   branches/serials-integration/Open-ILS/xul/staff_client/server/patron/bill_history.js
   branches/serials-integration/Open-ILS/xul/staff_client/server/patron/bills.js
   branches/serials-integration/Open-ILS/xul/staff_client/server/patron/display.js
   branches/serials-integration/Open-ILS/xul/staff_client/server/patron/display_horiz_overlay.xul
   branches/serials-integration/Open-ILS/xul/staff_client/server/patron/display_overlay.xul
   branches/serials-integration/Open-ILS/xul/staff_client/server/patron/hold_details.js
   branches/serials-integration/Open-ILS/xul/staff_client/server/patron/holds.js
   branches/serials-integration/Open-ILS/xul/staff_client/server/patron/holds_overlay.xul
   branches/serials-integration/Open-ILS/xul/staff_client/server/patron/info_group.js
   branches/serials-integration/Open-ILS/xul/staff_client/server/patron/items.js
   branches/serials-integration/Open-ILS/xul/staff_client/server/patron/search_result.js
   branches/serials-integration/Open-ILS/xul/staff_client/server/patron/standing_penalties.js
   branches/serials-integration/Open-ILS/xul/staff_client/server/patron/summary.js
   branches/serials-integration/Open-ILS/xul/staff_client/server/patron/summary.xul
   branches/serials-integration/Open-ILS/xul/staff_client/server/patron/summary_overlay_horiz.xul
   branches/serials-integration/Open-ILS/xul/staff_client/server/patron/ue.js
   branches/serials-integration/Open-ILS/xul/staff_client/server/patron/util.js
   branches/serials-integration/Open-ILS/xul/staff_client/server/serial/scap_editor.js
   branches/serials-integration/Open-ILS/xul/staff_client/server/serial/scap_editor.xul
   branches/serials-integration/Open-ILS/xul/staff_client/server/skin/cat.css
   branches/serials-integration/Open-ILS/xul/staff_client/server/skin/global.css
   branches/serials-integration/README
   branches/serials-integration/build/tools/update.sh
   branches/serials-integration/configure.ac
Log:
Catch up to trunk phase 1 -- Merged revisions 17255-17299,17303,17307,17309,17311-17314,17316-17318,17322-17323,17328,17330-17339,17341-17346,17350-17351,17353-17356,17358-17361,17363-17367,17369,17371-17373,17375-17379,17383,17385,17387,17389-17391,17393-17401,17404-17405,17413-17414,17416-17419,17428,17431,17433-17434,17436,17441-17442,17444-17447,17449-17450,17463-17464,17467,17469-17470,17472,17474,17476-17478,17480,17482,17484,17486,17488,17490-17491,17495-17496,17498,17501-17503,17505-17509,17511,17514,17516-17518,17520,17522-17523,17525,17527-17530,17533,17535,17537,17540-17541,17543,17545,17547,17549-17550,17553-17555,17557,17560,17563,17566,17571-17580,17582,17584-17593,17595,17597,17599,17601-17603,17605-17607,17609,17612,17614-17615,17617,17620,17622,17624-17625,17628-17630,17632-17640,17643-17648,17652-17653,17655,17657-17658,17661,17663,17665-17690,17692,17694,17696-17699,17701-17702,17704,17706-17708,17710,17713-17715,17717-17719,17723,17732-17733,17735-17736,17738,17744,17748,17750,17752,17754-17755,17757,17759,17762-17763,17765,17767,17769-17770,17772,17775-17776,17778,17780,17782,17784,17786,17788,17790,17792,17794,17796,17798,17800,17802-17804,17808-17810,17812-17813,17815,17817,17819,17821,17823,17825,17827,17829,17831,17833,17836,17838,17840,17843-17844,17848,17850,17853,17855,17857-17858,17860,17862-17863,17866-17867,17869,17872-17873,17875,17877,17879,17881,17883,17886 via svnmerge from 
svn://svn.open-ils.org/ILS/trunk

........
  r17255 | dbs | 2010-08-18 21:24:03 -0400 (Wed, 18 Aug 2010) | 18 lines
  
  Add basic authority browse/edit/delete interface
  
  http://localhost/eg/cat/authority/list should get you where you need to be
  
  The paging is comical, the JS should probably be split out from the
  declarative markup, the interface needs i18n, the UI needs to become
  usable - but at least we have exposed some functionality for working
  with authority records now.
  
  Ideally this becomes a widget that we can just embed into other
  interfaces to maintain context (which suggests using openils.cgi
  to seed the initial values of the widget).
  
  Note that the delete function works - it sets the deleted flag for
  an are to "true" - but the underlying authorities browse interface
  currently doesn't care about such niceties and always returns deleted
  records along with undeleted records. So that might be the next stop.
........
  r17256 | dbs | 2010-08-18 21:26:33 -0400 (Wed, 18 Aug 2010) | 4 lines
  
  Forgot to set the open-ils.pcrud controller for are in r17255
  
  And making the new perm section tab-consistent while I'm at it
........
  r17257 | dbs | 2010-08-18 23:35:53 -0400 (Wed, 18 Aug 2010) | 2 lines
  
  Don't return deleted authority records in a browse list
........
  r17258 | dbs | 2010-08-18 23:47:35 -0400 (Wed, 18 Aug 2010) | 4 lines
  
  Don't show deleted authority records in startwith browse, either
  
  Also restore the >= operator that was stomped in r17257
........
  r17259 | dbs | 2010-08-19 00:47:53 -0400 (Thu, 19 Aug 2010) | 5 lines
  
  Fix some defects in the first iteration of the authority edit/delete interface
  
    * Ensure that the correct ID is assigned to the edit/delete request
    * Prevent caching of results so that when a record is deleted, we don't continue to see it
........
  r17260 | dbs | 2010-08-19 09:57:07 -0400 (Thu, 19 Aug 2010) | 6 lines
  
  Give the authority list interface a place on the staff client Cataloging menu
  
  The interface itself still needs usability love, but exposing basic edit/delete
  functionality for authority records should give authoritarians some level of
  happiness.
........
  r17261 | erickson | 2010-08-19 10:22:26 -0400 (Thu, 19 Aug 2010) | 1 line
  
  downgraded a debug log message from error() to debug()
........
  r17262 | erickson | 2010-08-19 10:22:27 -0400 (Thu, 19 Aug 2010) | 1 line
  
  added clear_marc to po li retrieval to cut down network; mild code cleanup
........
  r17263 | erickson | 2010-08-19 10:22:28 -0400 (Thu, 19 Aug 2010) | 1 line
  
  automatically create lineitem assets (i.e. load bibs and items) during po activation when necessary since activation requires it;  only do this during non-dry-run calls
........
  r17264 | erickson | 2010-08-19 11:01:53 -0400 (Thu, 19 Aug 2010) | 1 line
  
  for consistency, use same 'icons' to indicate PO and PL.  don't show PO/PL links when no such object is linked to the lineitem
........
  r17265 | erickson | 2010-08-19 11:01:54 -0400 (Thu, 19 Aug 2010) | 1 line
  
  added missing closing td
........
  r17266 | miker | 2010-08-19 11:51:06 -0400 (Thu, 19 Aug 2010) | 12 lines
  
  Add support to BibTemplate for arbitrary XML chunks (DOM node) via the "xml" constructure param, which disables automatic format-specific fetching.
  
  Add a new module, openils.FeedTemplate which, given:
  
   * an xml feed (URI or pre-collected DOM node)
   * a dojo.query to pull out items from the feed
   * the DOM node of a template to clone for each item
   * the target DOM node into which it should shove the item-filled template instances
  
  will render a feed of arbitrary xml for you.
........
  r17267 | dbs | 2010-08-19 12:51:00 -0400 (Thu, 19 Aug 2010) | 7 lines
  
  Further enhancements to the authority list interface
  
    * Offer Next / Previous buttons instead of forcing the number spinner
    * Submit searches onBlur of the search box instead of having to click Submit
    * Accept CGI params so we can kick off a search from other interfaces
    * Factor out the displayRecords() code so we can attach other events to it
........
  r17268 | senator | 2010-08-19 13:35:03 -0400 (Thu, 19 Aug 2010) | 3 lines
  
  Acq: make view/place orders open a new tab w/ xul browser wrapped therearound
........
  r17269 | senator | 2010-08-19 14:18:21 -0400 (Thu, 19 Aug 2010) | 9 lines
  
  Serials: an alternative batch receiving interface, to support certain
  heavy-barcoding workflows.
  
  Still needs some things hooked up in the middle layer to create serial.units.
  Still needs some configurability.  Access from "Actions for this Record" in
  the staff-client-wrapped OPAC for a record with subscriptions and items
  attached.
........
  r17270 | erickson | 2010-08-19 16:00:14 -0400 (Thu, 19 Aug 2010) | 1 line
  
  added util function for printing an html string;  use new func for PO printing;  TODO, use new func in selfcheck code to reduce duplication
........
  r17271 | erickson | 2010-08-19 17:00:30 -0400 (Thu, 19 Aug 2010) | 1 line
  
  circ_modifier codes could be defined, but non-true (i.e. '0').  test for defined instead of truthiness when analyzing LID circ modifiers.  repaired (invisible) bug that unnecessarily lead to using circ mod objects instead of codes, depending on context
........
  r17272 | dbs | 2010-08-19 18:11:30 -0400 (Thu, 19 Aug 2010) | 2 lines
  
  Class::DBI::Frozen::301 needs to be forcefully installed on Debian Squeeze
........
  r17273 | erickson | 2010-08-19 18:16:01 -0400 (Thu, 19 Aug 2010) | 1 line
  
  move PO status to top of page for clarity
........
  r17274 | erickson | 2010-08-19 18:16:01 -0400 (Thu, 19 Aug 2010) | 1 line
  
  submit unified search query on Enter when focused on value widget
........
  r17275 | dbs | 2010-08-19 23:27:04 -0400 (Thu, 19 Aug 2010) | 10 lines
  
  Give the Authority List interface the ability to merge records... almost
  
  Separate the interface into separate JavaScript vs markup files
  
  To-do: 
    * Provide a middle layer method that accepts the array of records to merge and merges them
    * Teach the mergeRecords() to call that method when it exists
    * Provide a way of reordering the records or otherwise flagging which record should be the lead
    * Prevent the same record from being added to the merge slushbox twice
........
  r17276 | dbs | 2010-08-19 23:35:59 -0400 (Thu, 19 Aug 2010) | 2 lines
  
  Add a speedbump (confirmation dialog) when deleting authority records
........
  r17277 | dbs | 2010-08-19 23:47:46 -0400 (Thu, 19 Aug 2010) | 2 lines
  
  Add a speedbump to the MFHD delete workflow
........
  r17278 | dbs | 2010-08-20 00:02:44 -0400 (Fri, 20 Aug 2010) | 2 lines
  
  When initiating a new authority search, reset the pager to zero to avoid surprises
........
  r17279 | dbs | 2010-08-20 00:10:07 -0400 (Fri, 20 Aug 2010) | 2 lines
  
  Hitting ENTER in the term search box fires off a search now, as you would expect
........
  r17280 | gmc | 2010-08-20 07:25:40 -0400 (Fri, 20 Aug 2010) | 6 lines
  
  bug 620899: fix broken test for oils_web.xml
  
  Patch from Rick Scott <rick at shadowspar.dyndns.org>
  
  Signed-off-by: Galen Charlton <gmc at esilibrary.com>
........
  r17281 | dbs | 2010-08-20 09:22:30 -0400 (Fri, 20 Aug 2010) | 4 lines
  
  Add the authority record merge middle-layer API (open-ils.cat.authority.records.merge)
  
  Also add a pertinent permission (MERGE_AUTH_RECORDS)
........
  r17282 | dbs | 2010-08-20 10:01:26 -0400 (Fri, 20 Aug 2010) | 6 lines
  
  Hook up the authority management interface to the middle layer
  
  For now, uses the first record in the list as the master; we either
  need to give users the ability to select the master record at merge
  time, or to select it prior to clicking "Merge"
........
  r17283 | erickson | 2010-08-20 10:11:27 -0400 (Fri, 20 Aug 2010) | 1 line
  
  repair faulty lineitem detachment from invoices
........
  r17284 | erickson | 2010-08-20 10:11:27 -0400 (Fri, 20 Aug 2010) | 1 line
  
  propagate estimated price to created copy as copy price (aka list price or replacement price); propagate invoiced amount to created copy as copy cost (aka library cost);  caveats and consderations noted in the code.
........
  r17285 | erickson | 2010-08-20 11:22:03 -0400 (Fri, 20 Aug 2010) | 1 line
  
  until distrib formula skip_count is used (and possibly even then), let's hide it from the setup UI
........
  r17286 | erickson | 2010-08-20 11:35:53 -0400 (Fri, 20 Aug 2010) | 1 line
  
  during LI creation, adopt the provider of the PO if linked to a PO (and no provider was selected). repair event description copy/paste error
........
  r17287 | dbs | 2010-08-20 11:41:43 -0400 (Fri, 20 Aug 2010) | 2 lines
  
  Apply a little bit of style to group form elements together in confined spaces
........
  r17288 | phasefx | 2010-08-20 13:18:28 -0400 (Fri, 20 Aug 2010) | 1 line
  
  eliminate false positives for ContentCafe features for a given bib
........
  r17289 | erickson | 2010-08-20 14:33:25 -0400 (Fri, 20 Aug 2010) | 1 line
  
  added support for a SIP config option that forces the server to return the no_i18n version of the patron profile group name from the 'ptype' sub (aka PC field in patron-info requests); added config options getter sub; cleaned up some string concats to prevent warnings
........
  r17290 | dbs | 2010-08-20 14:38:35 -0400 (Fri, 20 Aug 2010) | 19 lines
  
  Add an API for counting the number of bibs linked to each authority record in the input list
  
  srfsh# request open-ils.cat open-ils.cat.authority.records.count_linked_bibs [1,2,3,4,5,6]
  
  Received Data: [
    {
      "bibs":1,
      "authority":1
    },
    {
      "bibs":1,
      "authority":2
    },
    {
      "bibs":2,
      "authority":3
    }
  ]
........
  r17291 | senator | 2010-08-20 14:53:12 -0400 (Fri, 20 Aug 2010) | 7 lines
  
  Booking: more progress on the forward-port from rel_1_6
  
  This completes the merging of changes from r15878 except for those to
  Circulate.pm, which are more involved and call for more untangling.
  
  More to come soon.
........
  r17292 | erickson | 2010-08-20 14:59:52 -0400 (Fri, 20 Aug 2010) | 3 lines
  
  added internal_id handler
  
  in anticipation of possible sip extension for returning patron ID
........
  r17293 | erickson | 2010-08-20 15:03:54 -0400 (Fri, 20 Aug 2010) | 1 line
  
  added sample SIP config for patron_type_uses_code option
........
  r17294 | erickson | 2010-08-20 15:19:41 -0400 (Fri, 20 Aug 2010) | 1 line
  
  re-tab to use tabs for consistency with rest of file;  for now, add embedded vim command to settle the issue
........
  r17295 | atz | 2010-08-20 16:13:35 -0400 (Fri, 20 Aug 2010) | 3 lines
  
  Add type="text/javascript" to <script> tags where needed.
  
  Probably just a formality.
........
  r17296 | atz | 2010-08-20 16:13:36 -0400 (Fri, 20 Aug 2010) | 5 lines
  
  Allow STAFF_CLIENT_BUILD_ID to be passed in or set in ENV
  
  Deconflict actions for STAFF_CLIENT_BUILD_ID='current'.  Build will
  always end up in datestamped directory, but a symlink will be added
  to it w/ the build ID string.  That should keep everybody happy.
........
  r17297 | senator | 2010-08-20 17:51:03 -0400 (Fri, 20 Aug 2010) | 14 lines
  
  Booking: finish the forward-port from rel_1_6
  
  This /should/ complete the forward port of booking from the rel_1_6 branch,
  which means that booking in trunk should work just how it does in the latest
  1.6.1.* releases.
  
  Most of the changes in this commit were to Circ/Circulate.pm, and cursory
  tests don't indicate any problems in the circulation logic overall, but the
  lay of the land there is quite different now in trunk than it was when Booking
  was initially developed, so I'd be somewhat wary for a little while.
  
  Going forward, trunk can accept improvements/bug fixes/etc for booking, and
  those changes can be *back*ported to branches in the usual way.  Yay!
........
  r17298 | gmc | 2010-08-20 19:32:32 -0400 (Fri, 20 Aug 2010) | 4 lines
  
  fix seed for item_barcode Vandelay bib attribute definition
  
  Signed-off-by: Galen Charlton <gmc at esilibrary.com>
........
  r17299 | miker | 2010-08-21 14:02:36 -0400 (Sat, 21 Aug 2010) | 1 line
  
  we need an index on LOWER(barcode) with r17018
........
  r17303 | dbs | 2010-08-22 09:28:14 -0400 (Sun, 22 Aug 2010) | 5 lines
  
  Show the number of bibs linked to each authority record
  
  This information is important to cataloguers when deciding which records
  to merge or delete.
........
  r17307 | erickson | 2010-08-23 10:50:39 -0400 (Mon, 23 Aug 2010) | 1 line
  
  perl 5.8 requires quotes around the version #
........
  r17309 | gmc | 2010-08-23 11:09:13 -0400 (Mon, 23 Aug 2010) | 8 lines
  
  display copy counts correctly in staff search results
  
  Also fixes following warning:
  
  Useless use of a constant in void context at .../OpenILS/Application/Search/Biblio.pm line 263.
  
  Signed-off-by: Galen Charlton <gmc at esilibrary.com>
........
  r17311 | atz | 2010-08-23 13:54:35 -0400 (Mon, 23 Aug 2010) | 7 lines
  
  Failure to open a file(handle) should be a fatal error.
  
  Otherwise we aren't getting any output anyway.
  
  Also a few formatting touchups for readability.
  
  TODO: use warnings!  use Cronscript for standardized lockfile and options.
........
  r17312 | atz | 2010-08-23 13:56:31 -0400 (Mon, 23 Aug 2010) | 3 lines
  
  Perltidy
  
  death to tabs
........
  r17313 | atz | 2010-08-23 14:23:04 -0400 (Mon, 23 Aug 2010) | 1 line
  
  Paste error
........
  r17314 | phasefx | 2010-08-23 14:36:26 -0400 (Mon, 23 Aug 2010) | 2 lines
  
  Allow true deletion of existing addresses in patron editor.  Let summary sidebar anticipate dissappearing addresses on refresh.
........
  r17316 | erickson | 2010-08-23 15:19:51 -0400 (Mon, 23 Aug 2010) | 3 lines
  
  conify UIs for config.rule_ stuff;
  
  Includes duration, recurring fine, max fine, and age hold protect
........
  r17317 | erickson | 2010-08-23 15:27:11 -0400 (Mon, 23 Aug 2010) | 1 line
  
  typos in path name for new circ conify UIs
........
  r17318 | erickson | 2010-08-23 15:32:45 -0400 (Mon, 23 Aug 2010) | 1 line
  
  more typos, arg, let's try this again
........
  r17322 | scottmk | 2010-08-24 09:29:02 -0400 (Tue, 24 Aug 2010) | 6 lines
  
  Correcting some miscellaneous anomalies in the org unit setting types.
  
  M    Open-ILS/src/sql/Pg/002.schema.config.sql
  A    Open-ILS/src/sql/Pg/upgrade/0378.data.fix_org_unit_setting_types.sql
  M    Open-ILS/src/sql/Pg/950.data.seed-values.sql
........
  r17323 | atz | 2010-08-24 11:22:03 -0400 (Tue, 24 Aug 2010) | 3 lines
  
  1-line fix for false 404 from sylvar
  
  solves "The requested URL /xul/rel_1_6_0_7/server/patron/ue.xhtml&clone=112879 was not found on this server."
........
  r17328 | phasefx | 2010-08-24 14:05:16 -0400 (Tue, 24 Aug 2010) | 1 line
  
  a suggestion from tsbere, this raises the existing login window if the staff client is invoked when it is already running
........
  r17330 | phasefx | 2010-08-24 15:04:20 -0400 (Tue, 24 Aug 2010) | 5 lines
  
  Staff Client Build/Update Enhancements patch from Thomas Berezansky
  
  Among other things, allows cross-compilation of Windows installers from Unix environments via NSIS, and enables Mozilla's upgrade mechanism for performing upgrades without needing to download and execute external files.
  
  See https://bugs.launchpad.net/evergreen/+bug/616452/ for more details.
........
  r17331 | phasefx | 2010-08-24 15:04:25 -0400 (Tue, 24 Aug 2010) | 1 line
  
  change Evergreen Staff Client folder and link names to Evergreen Staff Client Trunk for now, to sidestep an issue with installing over old-style installations
........
  r17332 | phasefx | 2010-08-24 15:25:39 -0400 (Tue, 24 Aug 2010) | 1 line
  
  one more label change for the trunk client
........
  r17333 | dbs | 2010-08-24 23:12:00 -0400 (Tue, 24 Aug 2010) | 5 lines
  
  Teach the spine label editor some manners: insert/delete rows, cursor up + down
  
  Tested with single and multiple spine labels at a time. Lots of DOM
  manipulation going on here, but seems to work nicely.
........
  r17334 | dbs | 2010-08-25 10:33:47 -0400 (Wed, 25 Aug 2010) | 2 lines
  
  Provide i18n support for some coust labels and descriptions
........
  r17335 | phasefx | 2010-08-25 11:57:33 -0400 (Wed, 25 Aug 2010) | 1 line
  
  circ.missing_pieces.copy_status org unit setting to support the Mark/Scan as Missing Pieces workflow.
........
  r17336 | phasefx | 2010-08-25 12:38:04 -0400 (Wed, 25 Aug 2010) | 1 line
  
  tsbere to the rescue for the server-xul make target if in the staff client directory
........
  r17337 | erickson | 2010-08-25 12:58:09 -0400 (Wed, 25 Aug 2010) | 1 line
  
  added support for configuring redirect depth, skin, and locale during IP-based org unit redirection
........
  r17338 | erickson | 2010-08-25 12:58:10 -0400 (Wed, 25 Aug 2010) | 1 line
  
  added sample apache config for the IP-based redirector
........
  r17339 | miker | 2010-08-25 17:51:55 -0400 (Wed, 25 Aug 2010) | 1 line
  
  update standing penalty query for blocked barcode list, trunk style!
........
  r17341 | dbs | 2010-08-25 20:16:11 -0400 (Wed, 25 Aug 2010) | 11 lines
  
  Make spine label settings configurable as org unit settings
  
  Note that due to the persist attribute on these XUL elements, a user
  who has manually changed their spine label settings may not see the
  org unit setting defaults for those particular settings if those
  org unit settings are created or changed. 
  
  Now that the infrastructure is in place, We could make the org unit
  settings take precedence over the persisted attributes if we think
  that's the right way to go.
........
  r17342 | dbs | 2010-08-25 21:38:54 -0400 (Wed, 25 Aug 2010) | 7 lines
  
  Add font-weight to label settings to support boldness
  
    * font-weight gets its own user-editable setting on the label generator UI,
  along with a library setting, so now you too can have bold spine labels applied
  uniformly at your library (but overridden for individual labels)
    * Convert a few hardcoded labels to entities in passing
........
  r17343 | dbs | 2010-08-25 23:07:39 -0400 (Wed, 25 Aug 2010) | 10 lines
  
  Add explicit identification of the master authority record when merging
  
  We now generate a table with the first cell containing either "Master"
  (indicating the record into which the other records will be merged) and
  or "Target" (indicating that the record will be merged into the master.
  
  This also adds a horizontal rule to delineate between the form buttons
  at the top, and adds borders to provide more clarity between the mergebox
  contents.
........
  r17344 | dbs | 2010-08-25 23:49:20 -0400 (Wed, 25 Aug 2010) | 6 lines
  
  Provide a visual delimiter for the spine/pocket label groupbox
  
  This just wraps a black border around the area where users edit
  the spine/pocket label, to give an idea of the area that can
  be edited according to the line width / length settings.
........
  r17345 | dbs | 2010-08-26 08:49:16 -0400 (Thu, 26 Aug 2010) | 2 lines
  
  Spine label editor: make ENTER at the end of a line move to next line
........
  r17346 | senator | 2010-08-26 10:39:59 -0400 (Thu, 26 Aug 2010) | 2 lines
  
  Fix OPAC renewals, broken by an imperfect booking test.
........
  r17350 | dbs | 2010-08-26 11:16:19 -0400 (Thu, 26 Aug 2010) | 6 lines
  
  Fix mismatches between cat.spine.font.* and cat.label.font.* that phasefx caught
  
  The font settings apply to both spine and pocket labels, and I committed
  the original upgrade and SQL scripts half-way through adjusting for that
  realization.
........
  r17351 | miker | 2010-08-26 12:53:51 -0400 (Thu, 26 Aug 2010) | 1 line
  
  examples of how to specify default preferred language and weight values
........
  r17353 | erickson | 2010-08-26 13:03:05 -0400 (Thu, 26 Aug 2010) | 1 line
  
  depth could be 0, don't undef on false; repaired url param addition of depth
........
  r17354 | erickson | 2010-08-26 13:03:06 -0400 (Thu, 26 Aug 2010) | 1 line
  
  added support for returning hold shelf expire time (CM field) in item info response when an item has been captured for a hold.  value is populated if item is on holds shelf or in transit to holds shelf
........
  r17355 | erickson | 2010-08-26 14:14:12 -0400 (Thu, 26 Aug 2010) | 1 line
  
  use openils.Util.printHtmlString for invoice printing; added progress dialog while wiating for invoices to arrive
........
  r17356 | phasefx | 2010-08-26 15:19:29 -0400 (Thu, 26 Aug 2010) | 1 line
  
  missing COMMIT;
........
  r17358 | dbs | 2010-08-26 21:19:26 -0400 (Thu, 26 Aug 2010) | 7 lines
  
  Restrict authority record fields to 1xx and 5xx when offering a match
  
  When you right-click on a subfield eligible for authority control and display
  the list of authority records that match the left-truncated subfield, we should
  not display every field in the matching authority records; the 1xx and 5xx seem
  like the obvious options to which the selection should be limited.
........
  r17359 | dbs | 2010-08-27 10:10:27 -0400 (Fri, 27 Aug 2010) | 18 lines
  
  Split spine labels between the alpha and numeric part of the LC subclass
  
  Some sites jam the alpha and numberic parts of the LC subclass together;
  for example "QA76.76" instead of "QA 76.76". Without the space, Evergreen
  was not inserting a line break. This commit will insert a line break
  automatically if the first element of a call number contains 1 to 3 alpha
  characters followed immediately by 1 or more numbers.
  
  This should not affect Dewey or most other classification systems, but will
  have the effect of making call numbers split as follows:
  
  Given "QA76.76 S93 1998", generate:
  
  QA
  76.76
  S93
  1998
........
  r17360 | dbs | 2010-08-27 12:08:22 -0400 (Fri, 27 Aug 2010) | 7 lines
  
  Cleaner implementation of LC subclass / Cutter spine label splitting
  
  TODO: detect whether this library is configured as an LC library and
  only invoke these call number machinations if that is the case. That
  leaves the door open for implementations of preferred Dewey splitting
  mechanisms, etc.
........
  r17361 | phasefx | 2010-08-27 14:13:26 -0400 (Fri, 27 Aug 2010) | 1 line
  
  support hiding of patron credit functionality.  To do this, create a server/skin/global_custom.css file containing  .hide_patron_credit { display: none }
........
  r17363 | dbs | 2010-08-27 17:11:05 -0400 (Fri, 27 Aug 2010) | 10 lines
  
  Add label_prefix and label_suffix columns to asset.copy_location
  
  These columns will be used to (optionally) set label prefixes and suffixes
  when printing spine labels for copies at a given copy location.
  
  The copy location editor has been taught to be aware of these new columns,
  but right now a NULL prefix or suffix will be turned into an empty string
  once the copy location has been edited. That might not be a big deal, but
  I'm a foolish hobgoblin and like consistency.
........
  r17364 | senator | 2010-08-27 17:50:28 -0400 (Fri, 27 Aug 2010) | 6 lines
  
  Serials: closer to full working receiving in the batch receive interface
  
  Units are actually created now, one per item. Plus misc bug fixes.
  For more flexible binding of items into units, see the serial control view.
........
  r17365 | dbs | 2010-08-27 17:58:24 -0400 (Fri, 27 Aug 2010) | 6 lines
  
  Teach the spine label editor to use the label prefixes and suffixes
  
  If label_prefix or label_suffix are defined in asset.copy_location, the
  spine label editor will now prefix or suffix them to the call number
  label respectively.
........
  r17366 | dbs | 2010-08-30 08:26:04 -0400 (Mon, 30 Aug 2010) | 4 lines
  
  Refine the backspace operation in spine label editor
  
  Make backspace at the start of a line also move up to the previous row.
........
  r17367 | dbs | 2010-08-30 10:13:00 -0400 (Mon, 30 Aug 2010) | 7 lines
  
  Use different label printing strategies for XUL 1.9.2 vs. 1.9.0
  
  r16421 contained a fix for printing in XUL 1.9.2 that appears to have
  broken printing in XUL 1.9.0. This change should switch back to the old
  style of printing if XUL 1.9.0 is detected, and otherwise uses the 1.9.2
  strategy for any other version of XUL.
........
  r17369 | dbs | 2010-08-30 10:23:17 -0400 (Mon, 30 Aug 2010) | 5 lines
  
  Display blank instead of 'undefined' for undefined label prefixes and suffixes
  
  When you saved an "undefined" prefix or suffix, that string would actually be stuffed
  into the database, which is not optimal.
........
  r17371 | dbs | 2010-08-30 10:47:37 -0400 (Mon, 30 Aug 2010) | 2 lines
  
  Add upgrade script to go along with r13763 (thanks for the reminder, senator)
........
  r17372 | dbs | 2010-08-30 10:56:55 -0400 (Mon, 30 Aug 2010) | 2 lines
  
  Complete the label font settings namespace change and replace some debug values for spine margin
........
  r17373 | senator | 2010-08-30 10:57:56 -0400 (Mon, 30 Aug 2010) | 2 lines
  
  Make "show item details" consistent for top AND bottom of patron items out
........
  r17375 | phasefx | 2010-08-30 11:36:16 -0400 (Mon, 30 Aug 2010) | 1 line
  
  infrastructure for context sensitive print setting
........
  r17376 | phasefx | 2010-08-30 11:36:18 -0400 (Mon, 30 Aug 2010) | 1 line
  
  label printer context
........
  r17377 | phasefx | 2010-08-30 11:36:20 -0400 (Mon, 30 Aug 2010) | 1 line
  
  mail printer context
........
  r17378 | phasefx | 2010-08-30 11:36:23 -0400 (Mon, 30 Aug 2010) | 1 line
  
  allows us to set printer context for list-based print actions
........
  r17379 | phasefx | 2010-08-30 11:36:24 -0400 (Mon, 30 Aug 2010) | 1 line
  
  receipt printer context
........
  r17383 | phasefx | 2010-08-30 12:15:40 -0400 (Mon, 30 Aug 2010) | 1 line
  
  show penalty/message notes on "Stop Sign Page"
........
  r17385 | phasefx | 2010-08-30 12:49:00 -0400 (Mon, 30 Aug 2010) | 2 lines
  
  option to not include claims returned circs in summary sidebar and under-button tallies
........
  r17387 | senator | 2010-08-30 13:02:22 -0400 (Mon, 30 Aug 2010) | 2 lines
  
  Basic auto-grid based editor for copy templates.  Useful esp. for serials.
........
  r17389 | erickson | 2010-08-30 13:27:37 -0400 (Mon, 30 Aug 2010) | 1 line
  
  show lineitem ID for each lineitem in lineitem table (po/pl) and general lineitem summary blob (invoicing)
........
  r17390 | erickson | 2010-08-30 13:27:38 -0400 (Mon, 30 Aug 2010) | 1 line
  
  disallow self-check login w/ inactive barcode
........
  r17391 | erickson | 2010-08-30 13:39:27 -0400 (Mon, 30 Aug 2010) | 1 line
  
  added option (suppressEditFields) to suppress fields from an autogrid's EditPane
........
  r17393 | dbs | 2010-08-30 18:01:10 -0400 (Mon, 30 Aug 2010) | 9 lines
  
  Add a bib_source editor widget to the MARC editor
  
  This widget should only be exposed when editing bibliographic MARC records.
  The existing restriction of not being able to set the bib source when importing
  via Z39.50 sadly remains in place; I believe the best place to tackle that will
  be in the Z39.50 import interface itself.
  
  Also TODO: i18n
........
  r17394 | dbs | 2010-08-30 23:17:35 -0400 (Mon, 30 Aug 2010) | 5 lines
  
  Add explicit rtype options to more invokers of the MARC Editor
  
  Neither are particularly applicable to the current bib_source editor
  implementation, but may be useful for other purposes inside the editor.
........
  r17395 | dbs | 2010-08-30 23:20:28 -0400 (Mon, 30 Aug 2010) | 7 lines
  
  Make the bib source selector in Vandelay MARC batch importer/exporter work
  
  The bib source selector in Vandelay offered a drop down of the available
  bib source selections, but never actually affected the source attribute
  of the bib records in biblio.record_entry when they were imported. This
  commit finishes off the logic that was almost there.
........
  r17396 | miker | 2010-08-30 23:31:09 -0400 (Mon, 30 Aug 2010) | 1 line
  
  Allow the OPAC to autoload IDL classes instead of either pulling in a long class list and evaluating them all, or loading a .5MB+ xml file and parsing the whole thing. 40% speedup in simple tests where cache is bypassed.
........
  r17397 | erickson | 2010-08-30 23:52:51 -0400 (Mon, 30 Aug 2010) | 4 lines
  
  pcrud.apply repairs.
  
  Skip objects that require no action instead of throwing an exception
  In last oncomplete handler, call final-complete as necessary and disconnect instead of starting over at object list position 0; no longer any need for final-complete/disconnect outside of closing request handler
........
  r17398 | erickson | 2010-08-30 23:52:52 -0400 (Mon, 30 Aug 2010) | 1 line
  
  istanceOf is not of this world; use dojo.isArray instead
........
  r17399 | erickson | 2010-08-30 23:52:53 -0400 (Mon, 30 Aug 2010) | 4 lines
  
  distrib formula streamlined drag-n-drop UI.
  
  Goal is to make distrib formulas faster/easier to create and manage
  TODO: add a clone option for formulas; style tweaks
........
  r17400 | erickson | 2010-08-31 08:48:31 -0400 (Tue, 31 Aug 2010) | 10 lines
  
  use circ_lib param instead of direct ws_ou acccess
  
  circulator->circ_lib, which defaults to requestor->ws_ou (but is
  overrideable) should be used in in lieu of direct ws_ou accesss;
  
  This is useful when the caller is not physically logged in to a
  workstation (e.g. centralized SIP client) and need to specify the
  physical location through other means.
  
  This change has no effect unless circ_lib is overridden by the caller
........
  r17401 | erickson | 2010-08-31 08:48:32 -0400 (Tue, 31 Aug 2010) | 1 line
  
  use current_loc as the circ_lib for checkin if provided and formatted as a valid org shortname
........
  r17404 | phasefx | 2010-08-31 13:01:30 -0400 (Tue, 31 Aug 2010) | 1 line
  
  fixes a bug when purging offline transactions after an Export
........
  r17405 | senator | 2010-08-31 13:05:20 -0400 (Tue, 31 Aug 2010) | 5 lines
  
  Booking: fix a bug in selecting the start/end date of a reservation
  
  This bug would generally only manifest on certain days of the year
  (1/29-31, 3/31, 5/31, 8/31, and 10/31).
........
  r17413 | erickson | 2010-08-31 15:49:03 -0400 (Tue, 31 Aug 2010) | 7 lines
  
  distribution formula config UI repairs/enhancements
  
  added distribution formula cloning
  added ability to change distrib formula name from formula detail page
  plugged some i18n holes
  using local copy of dimple grippy icons in distrib formula UI
  added local copy of dimple.png w/ new license file indicating image origin/license.
........
  r17414 | phasefx | 2010-08-31 16:08:09 -0400 (Tue, 31 Aug 2010) | 1 line
  
  printable_output() support in util.browser had stopped working, and this fixes that.  If an interface embedded in util.browser has a printable_output() function, the text output from that function should be printed, instead of a direct print attempt against the content window
........
  r17416 | erickson | 2010-08-31 17:22:43 -0400 (Tue, 31 Aug 2010) | 1 line
  
  added support for specifying a dojo.data-style query to select options in the filtering select to 'disable'.  disabling greys the background and prevents selection of the items in question
........
  r17417 | erickson | 2010-08-31 17:22:44 -0400 (Tue, 31 Aug 2010) | 1 line
  
  allow pass-thru of filteringtreeselect disableQuery as constructor param
........
  r17418 | erickson | 2010-08-31 17:22:45 -0400 (Tue, 31 Aug 2010) | 1 line
  
  disable non-usergroup profiles in user registration profile group selector
........
  r17419 | erickson | 2010-09-01 09:55:16 -0400 (Wed, 01 Sep 2010) | 1 line
  
  added explicit IDL class loading for cbreb, cbrebi, mvr, and ahr
........
  r17428 | senator | 2010-09-01 16:10:04 -0400 (Wed, 01 Sep 2010) | 7 lines
  
  Serials: improve the alternative batch receive interface for the
  barcode-heavy, one unit per item workflow. Support setting call numbers
  at receive time, effectively making it possible to associate call numbers
  with issuances instead of associating them with distributions.
  
  Other bugfixes/tweaks to the same interface.
........
  r17431 | senator | 2010-09-01 18:57:49 -0400 (Wed, 01 Sep 2010) | 2 lines
  
  Serials: checkbox for batch receive interface to en/disable receiving w units
........
  r17433 | dbs | 2010-09-01 22:11:21 -0400 (Wed, 01 Sep 2010) | 2 lines
  
  Experiment with putting a .pot under version control to see if Launchpad picks it up for translations
........
  r17434 | dbs | 2010-09-01 22:35:37 -0400 (Wed, 01 Sep 2010) | 5 lines
  
  i18n for biblio source editor and label prefix/suffix fields in copy location editor
  
  There were a few outstanding strings in the biblio source editor and copy location
  editor that needed attention. They are now un-hardcoded.
........
  r17436 | dbs | 2010-09-01 23:18:53 -0400 (Wed, 01 Sep 2010) | 5 lines
  
  Forward-port org unit setting types from r17392
  
  The upgrade script was committed in r17322 but the 950.data.seed-values.sql
  script still had the incorrect values in oils_i18n_gettext().
........
  r17441 | phasefx | 2010-09-02 01:08:19 -0400 (Thu, 02 Sep 2010) | 1 line
  
  stop the chilifresh undefined errors in craftsman
........
  r17442 | phasefx | 2010-09-02 01:08:58 -0400 (Thu, 02 Sep 2010) | 2 lines
  
  let's use xulrunner 1.9.0.17 for a while; it feels like it has fewer problems than 1.9.2.8
........
  r17444 | phasefx | 2010-09-02 02:25:36 -0400 (Thu, 02 Sep 2010) | 2 lines
  
  xulrunner 1.9.1.11 seems to be behaving, and is one of the only 3 releases currently showing up in releases.mozilla.org
........
  r17445 | erickson | 2010-09-02 12:21:45 -0400 (Thu, 02 Sep 2010) | 1 line
  
  added holds pull list action/trigger template w/ API call for fetching the formatted HTML.  This allows for an alternate print approach, particularly useful for large pull lists
........
  r17446 | erickson | 2010-09-02 13:35:46 -0400 (Thu, 02 Sep 2010) | 1 line
  
  display PO order (activation) date in PO page
........
  r17447 | senator | 2010-09-02 14:45:28 -0400 (Thu, 02 Sep 2010) | 7 lines
  
  Circ/Booking: replace checks for the CAPTURE_RESERVATION permission with
  checks for COPY_CHECKIN
  
  There's no such permission as CAPTURE_HOLD, so why should reservations be
  different?  Also, testing for reservations to capture during normal checkin
  was making trouble for users if they didn't have CAPTURE_RESERVATION.
........
  r17449 | atz | 2010-09-02 14:47:35 -0400 (Thu, 02 Sep 2010) | 1 line
  
  Utility for ISBN10->ISBN13 upconversion
........
  r17450 | phasefx | 2010-09-02 16:10:36 -0400 (Thu, 02 Sep 2010) | 2 lines
  
  fix the problem where login does not work immediately after registering a workstation
........
  r17463 | phasefx | 2010-09-02 19:57:47 -0400 (Thu, 02 Sep 2010) | 1 line
  
  up the default pull list limit from 50 to 100
........
  r17464 | phasefx | 2010-09-02 19:57:51 -0400 (Thu, 02 Sep 2010) | 1 line
  
  wire up the alternate print approach for full pull lists
........
  r17467 | erickson | 2010-09-03 09:36:11 -0400 (Fri, 03 Sep 2010) | 1 line
  
  users with no transaction history will have no xact summary; protect
........
  r17469 | miker | 2010-09-03 11:36:21 -0400 (Fri, 03 Sep 2010) | 1 line
  
  add opac_visible to asset.copy_location and org units
........
  r17470 | miker | 2010-09-03 11:38:03 -0400 (Fri, 03 Sep 2010) | 1 line
  
  typo in supercat fixup
........
  r17472 | senator | 2010-09-03 12:30:47 -0400 (Fri, 03 Sep 2010) | 24 lines
  
  Serials: a wizard for the pattern code field of the caption_and_pattern object
  
  This field holds the same data you'd find in the contents of an 853, 854, or
  855 tag.  This wizard aims to make it a little easier for mere mortals to
  compose this information, since the correctness of this field is fairly
  central to reasonably accurate serials issuance prediction.
  
  Find a button to launch this wizard from the Caption/Pattern interface of the
  Serial Control View.
  
  Big thanks to Galen Charlton, Dan Wells and Mike Rylander for all the help in
  getting this started and understanding the MARC.
  
  The wizard does still have a way to go before it's everything it can be. It
  still needs (in no particular order):
      - scrollbars on that dialog window
      - support for subfield $y and probably $z, possibly others
      - i18n fixes, accessibility improvements
      - more control over subfield $8
      - more input validation and user guidance; sane defaults for some fields?
      - reconsideration of the order of the parts of the wizard
      - finding out if it makes sense to allow $m without $j,$k and $l present
........
  r17474 | gmc | 2010-09-03 12:37:15 -0400 (Fri, 03 Sep 2010) | 7 lines
  
  allow updates of permission.perm_list.id to cascade
  
  Doing this to make it possible to reshuffle permission IDs
  for upgrades to 2.0.x
  
  Signed-off-by: Galen Charlton <gmc at esilibrary.com>
........
  r17476 | miker | 2010-09-03 13:30:36 -0400 (Fri, 03 Sep 2010) | 1 line
  
  we should really just use for(;;) for arguments
........
  r17477 | miker | 2010-09-03 13:35:00 -0400 (Fri, 03 Sep 2010) | 1 line
  
  use slice to clone arguments as an array, because arguments does not support splice
........
  r17478 | erickson | 2010-09-03 15:00:05 -0400 (Fri, 03 Sep 2010) | 1 line
  
  repaired thinko in hold targeting org-unit max-loops check
........
  r17480 | erickson | 2010-09-03 15:13:08 -0400 (Fri, 03 Sep 2010) | 6 lines
  
  Patron address copy on clone
  
  In patron reg, copy address instead of linking to original address on
  clone.  Controlled by new org unit setting
  
  circ.patron_edit.clone.copy_address
........
  r17482 | gmc | 2010-09-03 15:16:59 -0400 (Fri, 03 Sep 2010) | 10 lines
  
  restrict deletion of perm_lists in use
  
  Per suggestion by Mike Rylander; prevents overzealous
  administrator from removing necessary permisions that
  are in use.
  
  TODO: UI to make it clear when that happens
  
  Signed-off-by: Galen Charlton <gmc at esilibrary.com>
........
  r17484 | gmc | 2010-09-03 15:28:01 -0400 (Fri, 03 Sep 2010) | 8 lines
  
  give default OUs separate addresses
  
  Per suggestion from Anoop Atre to avoid a new user
  changing one OU address in a new database and wondering
  why all of the OU addresses were changed.
  
  Signed-off-by: Galen Charlton <gmc at esilibrary.com>
........
  r17486 | miker | 2010-09-03 15:55:06 -0400 (Fri, 03 Sep 2010) | 1 line
  
  make insertOrderedFields insert in /ascending/ order instead of descending. doh
........
  r17488 | erickson | 2010-09-03 16:00:22 -0400 (Fri, 03 Sep 2010) | 1 line
  
  event code may be 0 (SUCCESS) == false in SIP checkin, check defined instead
........
  r17490 | miker | 2010-09-03 17:08:07 -0400 (Fri, 03 Sep 2010) | 1 line
  
  make the authcookie param (and openils.User.authcookie) useful
........
  r17491 | senator | 2010-09-03 17:47:13 -0400 (Fri, 03 Sep 2010) | 5 lines
  
  AutoFieldWidget now shows timestamps correctly.
  
  Timestamps used to be a little bit off because of Dojo's limited parsing
  of ISO6801 stamps.
........
  r17495 | scottmk | 2010-09-07 10:18:50 -0400 (Tue, 07 Sep 2010) | 14 lines
  
  Consolidated upgrade script for 1.6 -> 2.0. 
  
  Things still missing: 
  
  1. Inserts and other changes to permission.perm_list and 
  permission.grp_perm_map. These can't be derived in a simple way from 
  the individual upgrade scripts, and will have to be hand-crafted to 
  fit what's already in the seed data. 
  
  2. Operations on optional schemas need to be moved out of the 
  transaction so that the script will work in a database that 
  doesn't have them. 
........
  r17496 | erickson | 2010-09-07 10:51:21 -0400 (Tue, 07 Sep 2010) | 1 line
  
  make lineitem price updates synchronous to prevent race condition between onChange of price set completion and PO activation
........
  r17498 | phasefx | 2010-09-07 11:24:55 -0400 (Tue, 07 Sep 2010) | 1 line
  
  Only modify msg when needed or we'll get spurious 'stop sign' pages
........
  r17501 | scottmk | 2010-09-07 12:12:15 -0400 (Tue, 07 Sep 2010) | 7 lines
  
  Move some operations out of the transaction so that they can
  fail without killing the script.  The affected objects do
  not necessarily exist -- i.e. the reporter schema, the
  extend_reporter schema, and the auditor.action_hold_request_history
  table.
........
  r17502 | erickson | 2010-09-07 12:41:53 -0400 (Tue, 07 Sep 2010) | 1 line
  
  cache the SIP login session to determine 'where' a transaction is occuring in case the caller does not indicate the location; compare hold pickup lib to physical location to determine alert type; small logging and format tweaks
........
  r17503 | erickson | 2010-09-07 12:54:44 -0400 (Tue, 07 Sep 2010) | 1 line
  
  a little more SIP checkin logging
........
  r17505 | scottmk | 2010-09-07 15:56:48 -0400 (Tue, 07 Sep 2010) | 8 lines
  
  The reporter and extend_reporter schemas are no longer optional.
  So changes to them go back into the transaction.
  
  ALTERs to auditor.action_hold_request_history stay outside of the
  transaction, at least for now, until the status of that table
  is clarified.
........
  r17506 | phasefx | 2010-09-07 16:50:58 -0400 (Tue, 07 Sep 2010) | 8 lines
  
  Tweaked Holdings Maintenance so that it only shows the selected library, its ancestors, and its descendents, subject to a Limit menu for org depth (so for example, in the stock example hierarchy where you have Consortium -> System -> Branch -> Sub-Library/Bookmobile, if you Limit to Branch, you will not see any Bookmobile or Sub-Library orgs).  It no longer renders sibling libs when clicking through the list.
  
  Also...
  
  * some refactoring and comment removal
  * less obtrusive but hopefully still useful menu entry styling for library entries that have volumes
  * some defensive coding for util.make_menulist
........
  r17507 | phasefx | 2010-09-08 00:07:32 -0400 (Wed, 08 Sep 2010) | 2 lines
  
  disabled lib menu entries in Holdings Maintenance was an artifact of that menu data being generated and used in other contexts.  This enables all the libs for the menu in Holdings Maintenance
........
  r17508 | phasefx | 2010-09-08 02:49:34 -0400 (Wed, 08 Sep 2010) | 1 line
  
  give OpenILS.data.lookup the ability to handle actor stat cats
........
  r17509 | phasefx | 2010-09-08 02:50:02 -0400 (Wed, 08 Sep 2010) | 13 lines
  
  We were shoving a fieldmapper actor.usr object into hold slip templates as params.data.user, but that environment doesn't have fieldmapper, dojo, etc.  To sidestep some difficulties adding such libraries, this takes user stat cat entries and shoves them in as normal Javascript objects (params.data.user_stat_cat_entries)
  
  So you can add something like this to the hold slip template:
  
  <script>
      var x = params.data.user_stat_cat_entries;
      for (var i = 0; i < x.length; i++) {
          document.write(x[i].stat_cat.name + ' : ' + x[i].stat_cat_entry + '<br/>');
      }
  </script>
  
  However, such pig-trickery with inline Javascript only works with the Mozilla Print strategy (where we render HTML and execute Javascript).
........
  r17511 | miker | 2010-09-08 09:36:09 -0400 (Wed, 08 Sep 2010) | 1 line
  
  Cleanup of reporter:selector values instigated by a report from Sally Fortin of the missing selector for the cbt class.
........
  r17514 | miker | 2010-09-08 10:37:22 -0400 (Wed, 08 Sep 2010) | 1 line
  
  A simple "vital stats" collector method returning information about a user for display in the OPAC or Staff Client.
........
  r17516 | phasefx | 2010-09-08 12:17:48 -0400 (Wed, 08 Sep 2010) | 13 lines
  
  * move inline CSS in patron editor to a file
  * hook for custom CSS file to override patron editor styling
  
  So for example, you can create /openils/var/web/css/skin/default/register_custom.css and have it contain CSS like this:
  
  TR[fmfield=ident_type] { display: none; } /* dangerous if the widget is required and doesn't have a default */
  TR[fmfield=ident_value2] > TD { font-size: x-large; }
  TR[fmfield=barred] { display: none; }
  TR[fmfield=country] { display: none; } /* dangerous if the widget is required and doesn't have a default */
  TR[fmfield=master_account] { display: none; }
  TR[fmfield=alert_message] { display: none; }
........
  r17517 | phasefx | 2010-09-08 14:10:15 -0400 (Wed, 08 Sep 2010) | 2 lines
  
  org unit settings for default ident type and default country for new users and new addresses in patron editor
........
  r17518 | dbs | 2010-09-08 14:10:47 -0400 (Wed, 08 Sep 2010) | 10 lines
  
  Library::CallNumber::LC is now in CPAN
  
  We briefly had to grab Library::CallNumber::LC from the SVN repo, but
  that broke on systems without subversion installed (argh). Thankfully
  the maintainer moved Library::CallNumber::LC to CPAN so our job becomes
  routine.
  
  Thanks to Chris Sharp and Benjamin Shum for running the gauntlet of a
  2.0 alpha install and finding this problem.
........
  r17520 | dbs | 2010-09-08 14:57:43 -0400 (Wed, 08 Sep 2010) | 2 lines
  
  Make Class::DBI::Frozen::301 a common forced module for all distros; genericize RHEL/CentOS
........
  r17522 | phasefx | 2010-09-08 15:32:42 -0400 (Wed, 08 Sep 2010) | 4 lines
  
  let's us set the z-index to -1 for rows in register_custom.css to make certain patron editor fields read-only.  miker_++
  
  For example: TR[fmfield=ident_value] { z-index: -1; }
........
  r17523 | phasefx | 2010-09-08 15:57:33 -0400 (Wed, 08 Sep 2010) | 2 lines
  
  make the table rows containing stat cats in the patron editor more easily selectable by CSS.  So, for example, we could put something like this in register_custom.css: TR[stat_cat_id='1'] { border: solid thick red; font-size: x-large; }
........
  r17525 | senator | 2010-09-08 16:16:20 -0400 (Wed, 08 Sep 2010) | 8 lines
  
  Serials: Improve open-ils.serial.receive_items.one_unit_per; remove dead code
  
  ..receive_items.one_unit_per will now generate/update summaries as
  ..receive_items already does.
  
  ..items.receive_by_id was unneeded, dead code.
........
  r17527 | miker | 2010-09-08 16:46:27 -0400 (Wed, 08 Sep 2010) | 1 line
  
  Middle Layer work to enable Issuance (type I) holds; also cleaned up support for F(orce) and R(ecall) copy-type holds, UI pending
........
  r17528 | miker | 2010-09-08 16:53:32 -0400 (Wed, 08 Sep 2010) | 1 line
  
  thinko in seed data permission
........
  r17529 | miker | 2010-09-08 18:34:16 -0400 (Wed, 08 Sep 2010) | 1 line
  
  Check for empty-ok after testing issuance copies in addition to when there are no copies to test
........
  r17530 | dbs | 2010-09-08 21:50:10 -0400 (Wed, 08 Sep 2010) | 14 lines
  
  Make OpenLibrary the default added content provider
  
  OpenLibrary is a better choice than Amazon for added content out of the box
  because:
  
  1) The OpenLibrary added content handler provides cover images +
  tables of content, whereas the Amazon added content handler only
  provides cover images.
  
  2) The terms of use for OpenLibrary content are much friendlier than
  the Amazon "Product Advertising API".
  
  We discussed this back in mid-2009: http://markmail.org/message/csx2hl6aleznapga
........
  r17533 | dbs | 2010-09-08 22:51:55 -0400 (Wed, 08 Sep 2010) | 4 lines
  
  Address typos and grammar in seed data
  
  TODO: Consistently wrap translatable content in oils_i18n_gettext() calls
........
  r17535 | erickson | 2010-09-09 09:35:18 -0400 (Thu, 09 Sep 2010) | 1 line
  
  for consistency, use 'issuanceid' as the issuance ID param for holds possibility testing; removed some crusty, old hold creation code
........
  r17537 | senator | 2010-09-09 09:44:18 -0400 (Thu, 09 Sep 2010) | 6 lines
  
  Serials: pattern wizard bugfix
  
  Previously, you couldn't always compile the pattern at the end of the wizard
  if you elected not to use certain parts of the wizard, such as enumeration
  captions, even though to do so should be perfectly valid.
........
  r17540 | erickson | 2010-09-09 10:22:22 -0400 (Thu, 09 Sep 2010) | 1 line
  
  ported ils-version comment updates to trunk, change ils-version to HEAD for trunk installs
........
  r17541 | miker | 2010-09-09 11:31:23 -0400 (Thu, 09 Sep 2010) | 1 line
  
  With group billing calls we need a new index
........
  r17543 | miker | 2010-09-09 11:55:50 -0400 (Thu, 09 Sep 2010) | 1 line
  
  should have had this index all along, but was less important until now where copy nnotes are used up front
........
  r17545 | miker | 2010-09-09 12:30:01 -0400 (Thu, 09 Sep 2010) | 1 line
  
  loop over users in a group, as the plan for usrgroup+mous is terrible
........
  r17547 | senator | 2010-09-09 14:53:14 -0400 (Thu, 09 Sep 2010) | 3 lines
  
  Make overrideEditWidgets to an AutoGrid able to accept shoved in values from
  the fields of the object they're editing.
........
  r17549 | phasefx | 2010-09-09 16:35:44 -0400 (Thu, 09 Sep 2010) | 1 line
  
  Styling tweaks to brief bib summary bar.  More tooltips, and expose record id and bib call number (from the first available defined in the appropriate asset.call_number_class entry)
........
  r17550 | phasefx | 2010-09-09 16:35:47 -0400 (Thu, 09 Sep 2010) | 1 line
  
  Change the field order in asset.call_number_class if you want to sort these
........
  r17553 | erickson | 2010-09-09 17:09:25 -0400 (Thu, 09 Sep 2010) | 1 line
  
  added alternate issuance flesh call that only fleshes the subscription;  used for public/opac display
........
  r17554 | erickson | 2010-09-09 17:09:26 -0400 (Thu, 09 Sep 2010) | 1 line
  
  added support for viewing and editing existing issuance-level holds to the default opac skin
........
  r17555 | senator | 2010-09-09 17:28:20 -0400 (Thu, 09 Sep 2010) | 4 lines
  
  Improve on 17547 to support a default value for /creating/ new objects while
  letting the current value of an object pass through to the overriding widget
  when /editing/.
........
  r17557 | phasefx | 2010-09-09 17:45:10 -0400 (Thu, 09 Sep 2010) | 1 line
  
  put these buttons under the sway of Dojo so that they don't get triggered when pressing enter in random fields in the patron editor form.  I have no idea why this works :)
........
  r17560 | phasefx | 2010-09-09 18:15:53 -0400 (Thu, 09 Sep 2010) | 1 line
  
  better synchronization between holds interface and hold details interface, and provide more data to list columns in hold details
........
  r17563 | senator | 2010-09-09 22:15:06 -0400 (Thu, 09 Sep 2010) | 8 lines
  
  Booking: stop the "new resource type" dialog from executing a naughty query
  
  The dialog will no longer offer a field for selecting a bibliographic record,
  but then again you wouldn't need it.  Bibliographically-based resource types
  can be set up through a context menu option in the staff OPAC browser, whereas
  this interface is only suited to non-bib-based resource types, like meeting
  rooms, laptops, etc.
........
  r17566 | erickson | 2010-09-10 10:17:02 -0400 (Fri, 10 Sep 2010) | 1 line
  
  added command line option for defining a stderr output log file for the SIP server
........
  r17571 | atz | 2010-09-10 11:54:52 -0400 (Fri, 10 Sep 2010) | 3 lines
  
  Adapt update.sh to make process changes
  
  Some warnings still appear, but script works like it used to.
........
  r17572 | atz | 2010-09-10 11:56:28 -0400 (Fri, 10 Sep 2010) | 1 line
  
  Script is executable
........
  r17573 | atz | 2010-09-10 11:57:21 -0400 (Fri, 10 Sep 2010) | 1 line
  
  Two files that should probably be deleted.
........
  r17574 | dbs | 2010-09-10 12:04:51 -0400 (Fri, 10 Sep 2010) | 13 lines
  
  Remove the previously deprecated CGI interfaces for configuring the Evergreen system
  
  The CGI interfaces have not been maintained; the interfaces available through
  the Admin -> Server Administration menu in the staff client are the recommended
  method for setting up new libraries in the organizational hierarchy,
  permissions, copy statuses, and circulation rules.
  
  Note that an adjustment to eg_vhost.conf is recommended to point to the
  offline.pl script, which is the only remaining CGI script in use; this
  should avoid conflicting Apache definitions for the /cgi-bin/ alias.
  
  Addresses https://bugs.launchpad.net/evergreen/+bug/634984
........
  r17575 | dbs | 2010-09-10 12:08:30 -0400 (Fri, 10 Sep 2010) | 10 lines
  
  Enable Class::DBI::Frozen::301 use for offline transaction management
  
  Most modern systems will install Class::DBI::Frozen::301 to avoid
  conflicts with incompatible Class::DBI packages. We need to teach
  offline.pl how to use Class::DBI::Frozen::301 if it is available.
  
  Note that we're using "use parent" instead of "use base" per the
  recommendation of "perldoc base"; accordingly, we're adding the
  system prerequisite for the parent pragma.
........
  r17576 | phasefx | 2010-09-10 12:35:37 -0400 (Fri, 10 Sep 2010) | 1 line
  
  the method behind patron.util.retrieve_fleshed_au_via_id can take a fields parameter for which fields to flesh, so let's expose that, and flesh some patron data being sent to receipt templates while we're here.  End-goal is to expose address information in patron searches without sending too much data over the wire
........
  r17577 | phasefx | 2010-09-10 12:35:40 -0400 (Fri, 10 Sep 2010) | 1 line
  
  move Patron Search over to fm_columns instead of patron.util.columns (the former makes use of fm_IDL.xml and can automagically make use of new fields, etc.).  Also give fm_columns the ability to hide virtual fields from the column picker
........
  r17578 | phasefx | 2010-09-10 12:35:45 -0400 (Fri, 10 Sep 2010) | 1 line
  
  Give the ability to duplicate column definitions by prefixing their id's.  Allow the specification of alternate row objects and datafields to render from.  The idea is to let us do such things as list address columns for a patron twice, once for the billing address and again for the mailing address.
........
  r17579 | phasefx | 2010-09-10 12:35:48 -0400 (Fri, 10 Sep 2010) | 1 line
  
  render patron barcode in patron search results
........
  r17580 | phasefx | 2010-09-10 12:35:51 -0400 (Fri, 10 Sep 2010) | 1 line
  
  In list.fm_columns, allow us to dictate the data object used for rendering (the row.my object fed into list.append) for all columns via the '*' column definition.  Also, wire up mailing and billing address columns into Patron Search
........
  r17582 | phasefx | 2010-09-10 14:17:20 -0400 (Fri, 10 Sep 2010) | 1 line
  
  ui.patron.registration.require_address org unit setting and associated behavior for requiring at least one postal address during patron registration
........
  r17584 | dbs | 2010-09-10 14:41:16 -0400 (Fri, 10 Sep 2010) | 4 lines
  
  Why yes, there _is_ a missing backslash at the end of that line!
  
  Thanks to Thomas Berezansky for reporting the broken Makefile.install.
........
  r17585 | dbs | 2010-09-10 15:07:45 -0400 (Fri, 10 Sep 2010) | 6 lines
  
  'use parent' consistently throughout OfflineStore.pm
  
  If we're going to use "use parent" instead of "use base" when creating
  the child instance of Class::DBI 3.01 that is OpenILS::Utils::OfflineStore,
  we might as well be consistent when declaring its own children.
........
  r17586 | miker | 2010-09-10 16:11:15 -0400 (Fri, 10 Sep 2010) | 1 line
  
  Allow the caller to specify a max number of facet values per facet
........
  r17587 | miker | 2010-09-10 16:12:19 -0400 (Fri, 10 Sep 2010) | 1 line
  
  more, different layers
........
  r17588 | phasefx | 2010-09-10 16:12:42 -0400 (Fri, 10 Sep 2010) | 1 line
  
  indentation
........
  r17589 | phasefx | 2010-09-10 16:12:44 -0400 (Fri, 10 Sep 2010) | 1 line
  
  some defense in patron.util.set_penalty_css against unfleshed or partially fleshed users
........
  r17590 | phasefx | 2010-09-10 16:12:45 -0400 (Fri, 10 Sep 2010) | 1 line
  
  fixes a bug where where the Staff column in a Payments list was styling CSS for a patron's billing Full Details dialog
........
  r17591 | phasefx | 2010-09-10 16:12:47 -0400 (Fri, 10 Sep 2010) | 1 line
  
  minor tweaks to patron retrieval within the billing interface
........
  r17592 | phasefx | 2010-09-10 16:12:49 -0400 (Fri, 10 Sep 2010) | 1 line
  
  enable the Refund action in the new billing interface
........
  r17593 | miker | 2010-09-10 16:13:05 -0400 (Fri, 10 Sep 2010) | 1 line
  
  use mod_deflate when and where we can (opac, and not in IE, basically)
........
  r17595 | senator | 2010-09-10 16:21:21 -0400 (Fri, 10 Sep 2010) | 2 lines
  
  Acq: no reason to deprive the user of back/forward here
........
  r17597 | senator | 2010-09-10 18:02:18 -0400 (Fri, 10 Sep 2010) | 3 lines
  
  Make it a little more straightfoward to refresh an autogrid from without. Can
  be useful in making glitchy, half-rendered grids behave.
........
  r17599 | senator | 2010-09-10 18:24:44 -0400 (Fri, 10 Sep 2010) | 8 lines
  
  Add "refresh grid" buttons to some consistently glitchy autogrids.
  
  This is obviously not an ideal solution, but if the user sees these grids
  and it's clear that not all the rows that should appear are rendering, they
  at least have a button to click to deal with it.  There are probably other
  places where this could be applied.
........
  r17601 | miker | 2010-09-10 22:12:41 -0400 (Fri, 10 Sep 2010) | 1 line
  
  In IE, tell Evergreen to return just the initially visible facets, and do it async-y (thanks berick)
........
  r17602 | dbs | 2010-09-10 23:31:26 -0400 (Fri, 10 Sep 2010) | 2 lines
  
  Typo fix in Vandelay item attribute definition editor
........
  r17603 | miker | 2010-09-11 10:18:24 -0400 (Sat, 11 Sep 2010) | 1 line
  
  thinko in schwarzian transform, and provide a tiebreaker sort on string
........
  r17605 | miker | 2010-09-11 14:35:46 -0400 (Sat, 11 Sep 2010) | 1 line
  
  Method for retrieving received issuances attached to a bib, optionally scoped by location, with paging and ordering support
........
  r17606 | miker | 2010-09-11 15:39:24 -0400 (Sat, 11 Sep 2010) | 1 line
  
  add "type" (siss.holding_type) and "status" (sitem.status) filters; renaming the method to be explicit about the fact that it is for issuances with received (sitem.date_received IS NOT NULL) items /only/
........
  r17607 | senator | 2010-09-11 20:12:26 -0400 (Sat, 11 Sep 2010) | 6 lines
  
  Serials: support predicting issuances until a specified end date
  
  Previously you could specify a number of issues, or possibly a final holding,
  but if you haven't created the final holding yet, but you know when the
  subscription ends, this can be useful.
........
  r17609 | miker | 2010-09-12 11:23:46 -0400 (Sun, 12 Sep 2010) | 1 line
  
  add maxValuesPerFacet attr/param
........
  r17612 | senator | 2010-09-12 14:32:33 -0400 (Sun, 12 Sep 2010) | 5 lines
  
  Serials: make it possible to predict issues for all dists at once, not just one
  
  Also return events on failure in a few more places to gives users better clues
  when things go wrong. More work is still ahead on this.
........
  r17614 | phasefx | 2010-09-12 14:43:38 -0400 (Sun, 12 Sep 2010) | 1 line
  
  staff.circ_modifier.display localization for rendering circ modifiers
........
  r17615 | senator | 2010-09-12 15:03:01 -0400 (Sun, 12 Sep 2010) | 24 lines
  
  Serials: dojo/autogrid-based scaffolding for building serials objects
  
  Accessible from the staff client OPAC browser's "Actions for this Record" menu
  as "Alternate Serial Control", these minimalist interfaces should support a
  workflow by which the user can create a subscription and its related parts
  (distributions, streams, etc), and get things going in a quick and dirty way
  while the existing Serial Control View continues to develop.
  
  Some notable differences in orientation between this and the existing
  interface work include:
      - The disuse of call numbers on distributions, instead favoring call number
      application to items by issuance at receive time (i.e., all copies of
      the Sep 2010 issue of Popular Mechanics share a call number rather than
      all copies of Popular Mechanics, any issue, at a given library sharing a
      call number).
      - Lack of attention to binding (although the batch receive interface will
      treat each item as a single bound unit, for barcoding, or will avoid
      creating units altogether if you don't want to barcode your serials).
  
  If this doesn't sound like the way you would do serials, I'd definitely
  recommend sticking with Serials Control View and ignoring these interfaces.
  Dan Wells' interface work promises broader functionality in the long run.
........
  r17617 | phasefx | 2010-09-12 15:29:40 -0400 (Sun, 12 Sep 2010) | 15 lines
  
  Allows you to create *_custom.properties files for overlaying stock strings with <messagecatalog>.
  
  So for example, a recent commit changed how circ modifiers are displayed in the staff client, with
  
  common.properties:
  staff.circ_modifier.display=%1$s : %2$s : %3$s
  
  You could do this for the original rendering:
  
  common_custom.properties:
  staff.circ_modifier.display=%1$s
  
  The custom file need only contain the properties that you wish to change.
  
  The xul <messagecatalog id="commonStrings" src="/xul/server/locale/<!--#echo var='locale'-->/common.properties" /> will attempt to parse both common.properties and common_custom.properties
........
  r17620 | senator | 2010-09-12 16:19:18 -0400 (Sun, 12 Sep 2010) | 2 lines
  
  Serials: little bugfixin on this OPAC-oriented method
........
  r17622 | erickson | 2010-09-12 22:04:24 -0400 (Sun, 12 Sep 2010) | 1 line
  
  wrap custom props file reader in try/catch to prevent xhr complaining about missing file
........
  r17624 | gmc | 2010-09-13 08:35:22 -0400 (Mon, 13 Sep 2010) | 4 lines
  
  make the other two k_* MARC templates usable by default
  
  Signed-off-by: Galen Charlton <gmc at esilibrary.com>
........
  r17625 | scottmk | 2010-09-13 08:35:59 -0400 (Mon, 13 Sep 2010) | 5 lines
  
  Add a Perl script for extracting permission names from the output
  of the dump_idl utility (and hence from an IDL file).
  
  AM   Open-ILS/examples/list_perms.pl
........
  r17628 | dbs | 2010-09-13 10:49:32 -0400 (Mon, 13 Sep 2010) | 4 lines
  
  README tweaks: Remove --create-bootstrap from eg_db_config.pl; s/STAFF_CLIENT_BUILD_ID/STAFF_CLIENT_STAMP_ID/
  
  Thanks to tsbere for flagging these changes
........
  r17629 | miker | 2010-09-13 11:17:44 -0400 (Mon, 13 Sep 2010) | 1 line
  
  teach fielder to cache (off by default), with a default timeout of 5min
........
  r17630 | miker | 2010-09-13 11:48:41 -0400 (Mon, 13 Sep 2010) | 1 line
  
  have fielder cache some frequently used data
........
  r17632 | atz | 2010-09-13 12:34:32 -0400 (Mon, 13 Sep 2010) | 1 line
  
  Prevent failure of update scripts.
........
  r17633 | atz | 2010-09-13 12:37:05 -0400 (Mon, 13 Sep 2010) | 1 line
  
  Typo
........
  r17634 | miker | 2010-09-13 13:26:03 -0400 (Mon, 13 Sep 2010) | 1 line
  
  we need to move permissions around for a Great Renumbering, but i18n is not protected by fkeys.  this provides infratructure for maintaining i18n values that already exist in a db, and an example usage on permission.perm_list
........
  r17635 | miker | 2010-09-13 13:34:11 -0400 (Mon, 13 Sep 2010) | 1 line
  
  arg...typo
........
  r17636 | miker | 2010-09-13 13:35:15 -0400 (Mon, 13 Sep 2010) | 1 line
  
  arg...typo ... again (but not really a problem)
........
  r17637 | miker | 2010-09-13 14:14:19 -0400 (Mon, 13 Sep 2010) | 1 line
  
  method for generating a set of compressed holdings statements for a bib with optional location and depth scoping, type filtering and item status filtering
........
  r17638 | miker | 2010-09-13 15:03:32 -0400 (Mon, 13 Sep 2010) | 1 line
  
  a little defensive programming
........
  r17639 | dbs | 2010-09-13 17:02:28 -0400 (Mon, 13 Sep 2010) | 4 lines
  
  Update README: create the database from template0 to avoid SQL_ASCII / UNICODE conflicts
  
  Of course, perhaps this just obscures a real problem. Hrm.
........
  r17640 | gmc | 2010-09-13 17:07:35 -0400 (Mon, 13 Sep 2010) | 9 lines
  
  fix retrieval of cat.default_classification_scheme
  
  Fixes bug where the cat.default_classification_scheme OU
  setting was effectively ignored in bib call # display
  in bib overlay and list of default call numbers during volume
  creation.
  
  Signed-off-by: Galen Charlton <gmc at esilibrary.com>
........
  r17643 | gmc | 2010-09-13 17:30:26 -0400 (Mon, 13 Sep 2010) | 6 lines
  
  add cat.default_classification_scheme OU setting type to DB
  
  For benefit of those tracking trunk.
  
  Signed-off-by: Galen Charlton <gmc at esilibrary.com>
........
  r17644 | dbs | 2010-09-14 00:13:42 -0400 (Tue, 14 Sep 2010) | 25 lines
  
  Integrate authority browse and creation support into the MARC editor
  
  This commit changes the contextual authority menu to be based on
  the authority browse interface; this should result in better
  matching behavior. The browse axis (author, subject, title, topic)
  is based on the context tag.
  
  The browse interface has enabled the contextual menu to grow
  "Next page" / "Previous page" menu items to enable cataloguers
  to wade through long lists of similar authority entries.
  
  The browse interface has also grown a "Create new authority record"
  menu with two submenu items. 
  
    * "Create immediately" takes the field in context and creates a new authority
       record based on that field, with matching indicators and subfields.
    * "Create and edit..." displays the MARCXML for the authority record in
       a MARC editor window before saving the record to the database.
  
  TODO: Make the "Create..." contextual options add the $0 linking subfield
  to the newly controlled field.
  
  TODO: Address some of the flaky UI behaviour, such as having to right-click
  three times on an authority-controllable field to display the authority menu.
........
  r17645 | scottmk | 2010-09-14 09:27:09 -0400 (Tue, 14 Sep 2010) | 4 lines
  
  Fix a function that moves translations in config.i18n_core,
  so that it will handle both text-based keys and numeric keys.
........
  r17646 | miker | 2010-09-14 11:04:41 -0400 (Tue, 14 Sep 2010) | 1 line
  
  some fleshing logic detangling
........
  r17647 | miker | 2010-09-14 11:06:57 -0400 (Tue, 14 Sep 2010) | 1 line
  
  and, of course, the attendant typo
........
  r17648 | miker | 2010-09-14 11:25:38 -0400 (Tue, 14 Sep 2010) | 1 line
  
  show holdings in the stock slimpac -- holdings format changed slightly
........
  r17652 | phasefx | 2010-09-14 11:39:58 -0400 (Tue, 14 Sep 2010) | 2 lines
  
  For some reason I already had cat.default_classification_scheme (my db started at upgrade version 0366), so adding some defense here
........
  r17653 | miker | 2010-09-14 11:44:44 -0400 (Tue, 14 Sep 2010) | 1 line
  
  unbreak item count in result list of slimpac
........
  r17655 | phasefx | 2010-09-14 11:49:26 -0400 (Tue, 14 Sep 2010) | 2 lines
  
  regexp for robust filename mangling
........
  r17657 | senator | 2010-09-14 15:01:28 -0400 (Tue, 14 Sep 2010) | 8 lines
  
  Add PayfloPro support to credit card processing
  
  Additionally, add some default view/update permissions to
  credit-card-processing-related org settings.
  
  This should bring the list of supported payment card processing APIs to:
  AuthorizeNet, PayPal (Website Payments Pro), and PayflowPro
........
  r17658 | erickson | 2010-09-14 15:04:24 -0400 (Tue, 14 Sep 2010) | 1 line
  
  additional issuance holds supporting code; in this case, hold_to_mvr func which is used by the uber hold details method;  commit also includes a small speed tweak for fetching details for copy holds (1 less cstore call)
........
  r17661 | senator | 2010-09-14 17:44:39 -0400 (Tue, 14 Sep 2010) | 3 lines
  
  OPAC display of fully compressed serials holding. Mostly miker's work except
  the OU setting part
........
  r17663 | senator | 2010-09-14 17:53:32 -0400 (Tue, 14 Sep 2010) | 3 lines
  
  Work by miker to add IDL chunking where it affects acq interfaces.
  And all things under web/templates. Makes things faster!
........
  r17665 | senator | 2010-09-14 18:20:24 -0400 (Tue, 14 Sep 2010) | 4 lines
  
  Add in more classes for IDL chunking, needed in serials interfaces
  
  Also will need to add more in for booking interfaces and misc other ones; gah.
........
  r17666 | erickson | 2010-09-14 22:30:31 -0400 (Tue, 14 Sep 2010) | 1 line
  
  added some additional auto-idl classes to load for acq UIs
........
  r17667 | erickson | 2010-09-14 22:30:32 -0400 (Tue, 14 Sep 2010) | 1 line
  
  added useful exception that is typical w/ autofieldwidget when an IDL class is not defined
........
  r17668 | gmc | 2010-09-15 00:26:52 -0400 (Wed, 15 Sep 2010) | 15 lines
  
  MARC tooltip updates
  
  * updated bibliographic tooltips; now current as of LC MARC21 Bibliographic
    Update 11, including the RDA tags.  Along the way, enhanced the bib tooltips to:
    * include definitions for embedded holdings tags (84X, 853-855, 863-868, 876-878)
    * expand dropdown for nonfiling indicator values
  * added tooltip files for authority records and MFHDs
  * taught MARC editor how to choose the correct tooltip file
  
  Caveat: if you localize the authority and MFHD tooltips for a locale other than
  en-US, you must edit marcedit.js, either to take your translation into account
  or to make it smarter about checking for available translations of the tooltips.
  
  Signed-off-by: Galen Charlton <gmc at esilibrary.com>
........
  r17669 | atz | 2010-09-15 01:24:48 -0400 (Wed, 15 Sep 2010) | 5 lines
  
  edi_translator sample EDI/JEDI docs
  
  EDI test and sample data
  
  Ingram ORDRSP that fails translation
........
  r17670 | atz | 2010-09-15 01:24:49 -0400 (Wed, 15 Sep 2010) | 1 line
  
  Extra test_client functionality.
........
  r17671 | atz | 2010-09-15 01:24:49 -0400 (Wed, 15 Sep 2010) | 12 lines
  
  Overhaul ORDRSP processing based on new Business::EDI capabilities
  
  Lots of error checking
  
  Fetch updates for xpath_value and a B&T data hack
  
  ORDRSP is forced only b/c the DB requires it.  We can't accurately
  know the message type until the translator deals with it (or we
  build our own fault-prone sniffer).  But for now all we expect from
  vendors in ORDRSP, so we can force temporarily.
  
  Also EDI example data and debugging tweaks
........
  r17672 | atz | 2010-09-15 01:24:50 -0400 (Wed, 15 Sep 2010) | 1 line
  
  Scripts obsolete
........
  r17673 | atz | 2010-09-15 01:24:52 -0400 (Wed, 15 Sep 2010) | 1 line
  
  Allow state='retry'
........
  r17674 | atz | 2010-09-15 01:24:53 -0400 (Wed, 15 Sep 2010) | 3 lines
  
  Trivial clarification
  
  Also a comment about targeting
........
  r17675 | atz | 2010-09-15 01:24:53 -0400 (Wed, 15 Sep 2010) | 1 line
  
  Minor cleanup
........
  r17676 | atz | 2010-09-15 01:24:54 -0400 (Wed, 15 Sep 2010) | 1 line
  
  Expanding handling (unfinished) for LI/LID QTY codes
........
  r17677 | atz | 2010-09-15 01:24:55 -0400 (Wed, 15 Sep 2010) | 1 line
  
  perltidy and cleanup
........
  r17678 | atz | 2010-09-15 01:24:56 -0400 (Wed, 15 Sep 2010) | 1 line
  
  Filling in another missing page_title
........
  r17679 | atz | 2010-09-15 01:24:57 -0400 (Wed, 15 Sep 2010) | 1 line
  
  Tons of EDI test files
........
  r17680 | atz | 2010-09-15 01:24:58 -0400 (Wed, 15 Sep 2010) | 4 lines
  
  More ORDRSP processing
  
  LID status updates, LI inheritance of status if all LIDs get the same status.
  Various cross-checks and safeguards.
........
  r17681 | atz | 2010-09-15 01:24:59 -0400 (Wed, 15 Sep 2010) | 1 line
  
  Beginning of modperl EDI message viewer
........
  r17682 | atz | 2010-09-15 01:25:00 -0400 (Wed, 15 Sep 2010) | 1 line
  
  Update README
........
  r17683 | atz | 2010-09-15 01:25:01 -0400 (Wed, 15 Sep 2010) | 1 line
  
  comment out debugging entry
........
  r17684 | atz | 2010-09-15 01:25:02 -0400 (Wed, 15 Sep 2010) | 12 lines
  
  edi_fetcher overhaul, test_client improvement
  
  New options: --test --provider --account
  
  Lots of crosschecking.  Accept files from command line or STDIN.
  
  Had to break out the logic in EDI to accommodate non-retrieved input.
  Remote retrieval now avoids pulling a file if the same file was
  previously retrieved and successfully processed.  If it bombed out,
  then we get it again (on the hopes it might have been fixed).
  
  Also better test_client behavior on edi2json failure.
........
  r17685 | atz | 2010-09-15 01:25:03 -0400 (Wed, 15 Sep 2010) | 1 line
  
  Update comment (trivial)
........
  r17686 | atz | 2010-09-15 01:25:03 -0400 (Wed, 15 Sep 2010) | 12 lines
  
  Handle ls w/ fileglobs
  
  This avoids returning non-useful paths like:
      /home/jatzberger/out/*Q*/uVQgpAoMT4
  when the file is:
      /home/jatzberger/out/uVQgpAoMT4
  
  Also finally resolve the discrepancy between FTP and SFTP ls behavior.
  
  force full(er) paths to be returned from ls_uftp
  
  Note, we cut out ./ if present.
........
  r17687 | atz | 2010-09-15 01:25:04 -0400 (Wed, 15 Sep 2010) | 1 line
  
  less hardcoding, more good
........
  r17688 | atz | 2010-09-15 01:25:05 -0400 (Wed, 15 Sep 2010) | 1 line
  
  Deepen test mode feedback (into top level EDI function)
........
  r17689 | atz | 2010-09-15 01:25:06 -0400 (Wed, 15 Sep 2010) | 3 lines
  
  Allow noauth option for retrieval method to support EDI
  
  EDI scripts run from crontab, w/o an associated user to auth
........
  r17690 | atz | 2010-09-15 01:25:07 -0400 (Wed, 15 Sep 2010) | 13 lines
  
  ORDRSP processing - PO linkage and object refresh
  
  Several objects get updated potentially several times during processing,
  and it is important to retrieve the item after earlier updates because
  some columns are being populated by DB default values or 'NOW', for example.
  The first 'NOW' for create_time would be correct, the subsequent ones incorrect,
  so the value(s) must be fetched.
  
  In order that an edi_message shows up in the list associated with a PO, we take the
  first valid PO number, if present.  Note that this mapping theoretically may vary:
  multliple PO lineitems *could* appear in one response, but in practice, we
  expect only one, so this should suffice.  This is also a good reason to prevent
  splitting a PO after it has been sent.
........
  r17692 | gmc | 2010-09-15 09:13:32 -0400 (Wed, 15 Sep 2010) | 4 lines
  
  move edi_scratch to join other test datasets
  
  Signed-off-by: Galen Charlton <gmc at esilibrary.com>
........
  r17694 | miker | 2010-09-15 10:49:04 -0400 (Wed, 15 Sep 2010) | 1 line
  
  A big pile of useful serial-schema indexes
........
  r17696 | erickson | 2010-09-15 12:26:53 -0400 (Wed, 15 Sep 2010) | 1 line
  
  2 debugging tools for identifying undefined IDL classes
........
  r17697 | phasefx | 2010-09-15 12:34:56 -0400 (Wed, 15 Sep 2010) | 2 lines
  
  add 'atevdef', 'ath', 'atreact', 'atval' to the list of classes to pull in so that Admin -> Local Administration -> Notifications / Action Triggers works
........
  r17698 | erickson | 2010-09-15 13:02:16 -0400 (Wed, 15 Sep 2010) | 1 line
  
  when IDL class is not defined, load it inline instead of throwing exceptions.  *tips hat to miker*
........
  r17699 | erickson | 2010-09-15 13:10:30 -0400 (Wed, 15 Sep 2010) | 1 line
  
  in the view fund UI, filter debits and allocations by the specific fund in question
........
  r17701 | erickson | 2010-09-15 13:24:54 -0400 (Wed, 15 Sep 2010) | 1 line
  
  after auto-loading the IDL class, re-set the local fmIDL handle
........
  r17702 | miker | 2010-09-15 13:25:53 -0400 (Wed, 15 Sep 2010) | 1 line
  
  Require that the matchpoint is_renewal flag be respected if set
........
  r17704 | dbs | 2010-09-15 14:53:01 -0400 (Wed, 15 Sep 2010) | 11 lines
  
  Create a unique index on authority records based on their heading, thesaurus, and heading text
  
  By providing a truly unique index for headings for a given thesaurus, this
  index sets the stage for removing the arn_value / arn_source columns from
  the database.
  
  Sites with loaded authority records who attempt to add this index may find that
  it fails due to existing duplicate entries; some suggestions for hunting down
  the trouble-doers (duplicate entries) is provided in
  Open-ILS/src/sql/Pg/0400.schema.unique_authority_index.sql
........
  r17706 | dbs | 2010-09-15 16:04:55 -0400 (Wed, 15 Sep 2010) | 9 lines
  
  Drop arn_value and arn_source from the authority.record_entry table
  
  Now that we have the unique index by thesaurus on actual headings, arn_value
  and arn_source are a dead weight that we can gleefully toss overboard.
  
  Tested with authority record import via Vandelay and authority record
  creation during bibliographic editing; confirmed that validating authorities
  still works, no apparent visible difference to the world.
........
  r17707 | phasefx | 2010-09-15 16:09:32 -0400 (Wed, 15 Sep 2010) | 1 line
  
  refactoring for readability
........
  r17708 | phasefx | 2010-09-15 16:09:34 -0400 (Wed, 15 Sep 2010) | 1 line
  
  In r15732, the Volume/Copy Creator was modified to serve double-duty as a batch interface for re-barcoding existing items.  This extends that incarnation further and allows for changing the volumes for existing items as well.  In Holdings Maintenance, the entry-point for this is Actions -> Replace Barcodes.  However, it's Acquisitions that is prompting this development, and the entry point there is on the Line Item, under Actions -> Update Barcodes
........
  r17710 | miker | 2010-09-15 16:33:53 -0400 (Wed, 15 Sep 2010) | 1 line
  
  Need to start the arrayref out right
........
  r17713 | scottmk | 2010-09-15 16:43:54 -0400 (Wed, 15 Sep 2010) | 7 lines
  
  1. Revamp the contents of permission.perm_list in the course
  of the upgrade to v2.0.
  
  2. Incorporate miscellaneous recent upgrade scripts.
  
  M    Open-ILS/src/sql/Pg/1.6.1-2.0-upgrade-db.sql
........
  r17714 | dbs | 2010-09-15 18:06:37 -0400 (Wed, 15 Sep 2010) | 13 lines
  
  Make authority.normalize_heading() more defensive, and drop back to a plain (non-unique) index
  
  NOTE: Database server now requires UUID::Tiny CPAN module in its Perl repertoire
  
  When faced with terrible input, authority.normalize_heading() will generate a
  heading based on the MD5 UUID of the input value, flagged with "BAD_MARCXML"
  if the MARCXML could not be parsed, or "NOHEADING" if there was no 1xx field.
  Previously, authority.normalize_heading() would throw raw, ugly Perl errors.
  
  Many thanks to Mike Rylander and Galen Charlton for their suggestions on how
  to break the original version of authority.normalize_heading(), this code
  should be much more robust as a result.
........
  r17715 | miker | 2010-09-15 20:40:50 -0400 (Wed, 15 Sep 2010) | 7 lines
  
  Patch from Dan Wells:
  
  I will start with the changes which I think are straightforward.  First, textual_holdings are sometimes used to augment the generated_coverage and at other times should completely replace it (generally when the holdings statement is too complex to be easily generated or has more detail than we care about).  The 'show_generated' flag in each summary table is a simple means of indicating which type of display we want.  Second, 'summary_method' will be consulted when generating the 'generated_coverage' fields, and tells us how any attached MFHD records (SREs) should be treated for this distribution in relation to the new structured data (attempt to merge the data, generate display data from both separately, or generate based on one or the other only).
  
  The changes to serial.caption_and_pattern are not as straightforward, but I think they are justifiable.  Any given caption/pattern is only valid for a certain period of time (i.e. until it changes).  As it stands, we can infer the start and end dates of a caption/pattern only by consulting the attached issuances.  In practice this means retrieving and sorting sometimes hundreds of issuances to provide for the sorted display of just a few caption/patterns.  As I work with these objects more, I am simply often wishing for a more convenient access point to this important data.  This also means that the 'active' flag is redundant (caption/patterns with end_date-s are not active), but we need to get end_date in place before we can start removing the 'active' flag from the code.
........
  r17717 | miker | 2010-09-15 21:52:51 -0400 (Wed, 15 Sep 2010) | 1 line
  
  fake "global" issuances by returning a representative subset based on like date_published and label
........
  r17718 | miker | 2010-09-15 22:25:57 -0400 (Wed, 15 Sep 2010) | 1 line
  
  teach open-ils.storage.serial.issuance.ranged_tree about "global" issuances
........
  r17719 | senator | 2010-09-15 22:30:20 -0400 (Wed, 15 Sep 2010) | 2 lines
  
  More classes for IDL chunking under web/templates
........
  r17723 | dbs | 2010-09-16 07:40:37 -0400 (Thu, 16 Sep 2010) | 7 lines
  
  Add more AutoIDL classes for Vandelay happiness
  
  Vandelay needs these class definitions for basic import operations.
  
  Ideally every templated page wouldn't need to load these, but
  this seems to be the best short-term solution.
........
  r17732 | scottmk | 2010-09-16 10:52:04 -0400 (Thu, 16 Sep 2010) | 4 lines
  
  Incorporate some late-breaking upgrades
  
  M    Pg/1.6.1-2.0-upgrade-db.sql
........
  r17733 | scottmk | 2010-09-16 11:38:03 -0400 (Thu, 16 Sep 2010) | 8 lines
  
  Make acq.provider_contact.name NOT NULL.
  
  This change corrects the effect of a typo (NULL NULL instead of NOT NULL).
  
  M    Open-ILS/src/sql/Pg/200.schema.acq.sql
  M    Open-ILS/src/sql/Pg/1.6.1-2.0-upgrade-db.sql
  A    Open-ILS/src/sql/Pg/upgrade/0404.schema.acq-provider-contact-null-null.sql
........
  r17735 | senator | 2010-09-16 11:38:48 -0400 (Thu, 16 Sep 2010) | 3 lines
  
  Crude OPAC support for expanding serial issuances when showing fully compressed
  holdings
........
  r17736 | senator | 2010-09-16 11:54:02 -0400 (Thu, 16 Sep 2010) | 2 lines
  
  Fix local admin -> circ policy interface by including some circ matrix related classes in the IDL chunking
........
  r17738 | senator | 2010-09-16 12:08:15 -0400 (Thu, 16 Sep 2010) | 2 lines
  
  More IDL chunking fixes aimed at local admin -> circ policies. this time fix it.
........
  r17744 | gmc | 2010-09-16 14:19:43 -0400 (Thu, 16 Sep 2010) | 8 lines
  
  remove internal limit with queries on facets
  
  This allows non-selective facets such a material type facet
  to bring in correct results - the tradeoff is that queries
  that involve facets will run slower.
  
  Signed-off-by: Galen Charlton <gmc at esilibrary.com>
........
  r17748 | scottmk | 2010-09-16 18:08:34 -0400 (Thu, 16 Sep 2010) | 5 lines
  
  Add column usr_summary to actor.stat_cat.  (This column was added
  before we started maintaining individual update scripts.)
  
  M    Open-ILS/src/sql/Pg/1.6.1-2.0-upgrade-db.sql
........
  r17750 | senator | 2010-09-16 18:24:50 -0400 (Thu, 16 Sep 2010) | 3 lines
  
  Still more IDL chunking fix, plus make copy template create dialog more usable
  (works as a pane, but was too tall for screen and had broken scrolling as popup)
........
  r17752 | senator | 2010-09-16 21:29:26 -0400 (Thu, 16 Sep 2010) | 2 lines
  
  Fix syntax error in r17717
........
  r17754 | miker | 2010-09-17 01:04:25 -0400 (Fri, 17 Sep 2010) | 1 line
  
  Only show "issues held" if there is something to show
........
  r17755 | miker | 2010-09-17 01:07:02 -0400 (Fri, 17 Sep 2010) | 1 line
  
  spacing, sorry, should have checked first
........
  r17757 | miker | 2010-09-17 09:32:31 -0400 (Fri, 17 Sep 2010) | 1 line
  
  OU locale lookup needs a bit more work, it needs to pass a language instead of an xx-YY locale string
........
  r17759 | miker | 2010-09-17 09:41:54 -0400 (Fri, 17 Sep 2010) | 1 line
  
  normalize all locales used in locale-lang mapping for QueryParser
........
  r17762 | scottmk | 2010-09-17 10:17:44 -0400 (Fri, 17 Sep 2010) | 7 lines
  
  -- Dropping a foreign key (which has already been dropped from the
  -- base installation scripts).
  
  M    Open-ILS/src/sql/Pg/002.schema.config.sql
  M    Open-ILS/src/sql/Pg/1.6.1-2.0-upgrade-db.sql
  A    Open-ILS/src/sql/Pg/upgrade/0405.schema.acq-hold-copy-map-drop-fkey.sql
........
  r17763 | senator | 2010-09-17 12:23:14 -0400 (Fri, 17 Sep 2010) | 2 lines
  
  Fix some cases where View MARC upon colliding import broke in Vandelay
........
  r17765 | erickson | 2010-09-17 13:10:13 -0400 (Fri, 17 Sep 2010) | 1 line
  
  protect against fetching lineitem details by ref instead of ID
........
  r17767 | senator | 2010-09-17 13:11:18 -0400 (Fri, 17 Sep 2010) | 4 lines
  
  Fix a glitch where you could only edit one field in 'Edit Attributes' in
  Vandelay before it stopped working.
........
  r17769 | dbs | 2010-09-17 13:42:14 -0400 (Fri, 17 Sep 2010) | 5 lines
  
  Make prereq installation easier on sites that block everything except 80 and 443
  
  It won't help if you need to grab SVN copies of OpenSRF and Evergreen, but if
  you're working with a tarball then you're golden. GOLDEN!
........
  r17770 | dbs | 2010-09-17 13:56:38 -0400 (Fri, 17 Sep 2010) | 4 lines
  
  Force the Class::DBI::Frozen::301 install a different, working way
  
  This formulation works on Debian Squeeze, hopefully others.
........
  r17772 | erickson | 2010-09-17 14:42:27 -0400 (Fri, 17 Sep 2010) | 1 line
  
  added option to vandelay rec list import that forces it to respond to the client w/ every record processed, instead of throttled responses.  this is useful for small batches where it's necessary to know the outcome of each record
........
  r17775 | scottmk | 2010-09-17 15:12:05 -0400 (Fri, 17 Sep 2010) | 5 lines
  
  Restore two foreign keys that were somehow inadvertently
  dropped, probably by some funky interaction with inheritance.
  
  M    Open-ILS/src/sql/Pg/1.6.1-2.0-upgrade-db.sql
........
  r17776 | dbs | 2010-09-17 15:39:37 -0400 (Fri, 17 Sep 2010) | 9 lines
  
  Revert attempt to prevent encoding corruption that was causing encoding corruption
  
  LDR/09 was never showing up as 'a' where it was being tested, and adding the
  'a' was preventing a reconversion to UTF8. It somewhat looks like the UTF8
  MARCXML input gets converted to MARC8 as part of MARC::Batch's magic, then
  gets converted back to UTF8 by MARC::File::XML::as_xml_record(). Seems like
  this would mean potential performance / encoding problems but it works, which
  is better than what my meddlesome tests were doing.
........
  r17778 | senator | 2010-09-17 16:52:18 -0400 (Fri, 17 Sep 2010) | 2 lines
  
  More IDL chunking fixes, this time for action/trigger UI
........
  r17780 | phasefx | 2010-09-17 17:20:00 -0400 (Fri, 17 Sep 2010) | 2 lines
  
  get rid of the disabled-look for the Actions for this Record menu label
........
  r17782 | phasefx | 2010-09-17 18:15:39 -0400 (Fri, 17 Sep 2010) | 2 lines
  
  change pcrud.apply to pcrud.update, and make use of closures in loop.  fixes hanging progress bar and lack of list refresh in Messages interface after modifying or archiving an existing message/penalty
........
  r17784 | gmc | 2010-09-17 18:48:11 -0400 (Fri, 17 Sep 2010) | 7 lines
  
  enable translation of location name in copy location/status summary
  
  Implementation is iffy because it exposes oils_i18n_xlate outside
  of cstore.
  
  Signed-off-by: Galen Charlton <gmc at esilibrary.com>
........
  r17786 | senator | 2010-09-17 19:23:06 -0400 (Fri, 17 Sep 2010) | 4 lines
  
  Acq: be a little better about explaining why a PO can't be activated
  
  Sure, there's still room for improvement.
........
  r17788 | erickson | 2010-09-17 19:40:50 -0400 (Fri, 17 Sep 2010) | 1 line
  
  load the right class in the on-the-fly IDL loader call
........
  r17790 | erickson | 2010-09-17 19:55:19 -0400 (Fri, 17 Sep 2010) | 1 line
  
  need cit and actsc for patron reg
........
  r17792 | gmc | 2010-09-17 19:56:43 -0400 (Fri, 17 Sep 2010) | 4 lines
  
  added format.po.jedi hook to initial seed
  
  Signed-off-By: Galen Charlton <gmc at esilibrary.com>
........
  r17794 | erickson | 2010-09-17 20:06:25 -0400 (Fri, 17 Sep 2010) | 1 line
  
  more user stat cat classes
........
  r17796 | senator | 2010-09-17 20:24:41 -0400 (Fri, 17 Sep 2010) | 8 lines
  
  Serials batch receive: usability improvements
  
  s/fundamental periodicity/frequency/
  Smart copy location batch applicator
  Dedup call numbers with same label in batch applicator
  Tooltips on the holding lib column to show dist label and stream routing label
........
  r17798 | gmc | 2010-09-17 20:28:19 -0400 (Fri, 17 Sep 2010) | 4 lines
  
  silly me, acqpo.activate is the new format.po.jedi
  
  Signed-off-by: Galen Charlton <gmc at esilibrary.com>
........
  r17800 | miker | 2010-09-17 20:53:27 -0400 (Fri, 17 Sep 2010) | 1 line
  
  Offer a global flag to cause the testing of hold matrix rules against the receiving user instead of the requestor, and set the initial value to enabled as this seems to be the less surprising value for current users of in-db hold logic
........
  r17802 | dbs | 2010-09-17 21:47:15 -0400 (Fri, 17 Sep 2010) | 7 lines
  
  Expose an RSS (Atom, actually) feed in the dynamic OPAC for search results
  
  I doubt most humans really care about RSS feeds, but this will make the
  RSS feed icon highlight in Firefox and that should satisfy one of the
  "requirements" for a Next Generation OPAC if that's the bar for research
  papers these days.
........
  r17803 | miker | 2010-09-17 21:58:25 -0400 (Fri, 17 Sep 2010) | 1 line
  
  add facets to the ATOM feed link
........
  r17804 | miker | 2010-09-17 22:02:35 -0400 (Fri, 17 Sep 2010) | 9 lines
  
  Patch from James Fournie of SITKA:
  
  This is a patch that makes the toolbar work with the little jellybean
  button on Macs.   It's that little lozenge-like button on the top
  right of Mac programs that shows/hides the toolbar.  With this patch
  it will show/hide the toolbar "button bar", making it behave more like
  most Mac programs.  It shouldn't have any affect on other platforms.
........
  r17808 | scottmk | 2010-09-18 10:43:07 -0400 (Sat, 18 Sep 2010) | 4 lines
  
  Remove UNIQUE NOT NULL from config.index_normalizer.description.
  
  M    Open-ILS/src/sql/Pg/1.6.1-2.0-upgrade-db.sql
........
  r17809 | miker | 2010-09-18 13:53:56 -0400 (Sat, 18 Sep 2010) | 1 line
  
  add pre- and post-render callback capabilities to BibTemplate
........
  r17810 | erickson | 2010-09-18 13:54:51 -0400 (Sat, 18 Sep 2010) | 1 line
  
  added cnal to autoidl pile
........
  r17812 | miker | 2010-09-18 15:06:34 -0400 (Sat, 18 Sep 2010) | 1 line
  
  more callbacks, this time pre- and post-query
........
  r17813 | erickson | 2010-09-18 15:55:44 -0400 (Sat, 18 Sep 2010) | 1 line
  
  in acq copies display, default to ws lib as recipient lib
........
  r17815 | phasefx | 2010-09-18 23:50:28 -0400 (Sat, 18 Sep 2010) | 2 lines
  
  Make sure offline interfaces correctly load printer settings outside of logins.  Some refactoring
........
  r17817 | erickson | 2010-09-19 15:15:48 -0400 (Sun, 19 Sep 2010) | 1 line
  
  for large sets of holds, usually around 10 or more, the holds display takes a little too long.  instead of collecting them all and sorting them by queue position, slot them into the display table (by queue position) as they arrive
........
  r17819 | phasefx | 2010-09-19 18:44:16 -0400 (Sun, 19 Sep 2010) | 2 lines
  
  remove redundant invocation of custom.js, and tweak how menu.js loads it
........
  r17821 | senator | 2010-09-19 19:53:36 -0400 (Sun, 19 Sep 2010) | 3 lines
  
  Acq: Delay loading of providers for invoice-linking dialogs until
  they're really needed.
........
  r17823 | senator | 2010-09-19 20:55:16 -0400 (Sun, 19 Sep 2010) | 6 lines
  
  Acq: make purchase order and invoice interfaces less annoying
  
  They're really just canned acq searches, but now they don't automatically start
  the search and hide the search terms, so you have a chance to adjust what
  you're looking for
........
  r17825 | senator | 2010-09-20 00:18:49 -0400 (Mon, 20 Sep 2010) | 2 lines
  
  Acq: replace a couple remaining instances of "Picklist" with "Selection List"
........
  r17827 | dbs | 2010-09-20 00:33:09 -0400 (Mon, 20 Sep 2010) | 6 lines
  
  Search for humans: AND and OR are more understandable than "&&" and "||"
  
  The operators && and || will not mean much to many people, whereas AND and
  OR have common meanings that will aid in understanding the advanced search
  interface.
........
  r17829 | senator | 2010-09-20 01:05:00 -0400 (Mon, 20 Sep 2010) | 11 lines
  
  Acq: change a FilteringSelect dijit to a regular <select> to avoid a
  manifestation  of Dojo bug #11062; add more refresh grid buttons to unified
  search
  
  "Refresh Grid" buttons are a sad little stopgap measure to address a problem
  where some AutoGrids show only some of the rows they're supposed to. Calling
  .refresh() on the AutoGrid consitently right the grid.  Maybe the problem
  is some kind of race condition, and maybe it's related to the use of "get"
  and "formatter" attributes for some columns.  Or maybe it's something else.
  Attempts continue to find the root of the problem and repair it.
........
  r17831 | senator | 2010-09-20 03:29:58 -0400 (Mon, 20 Sep 2010) | 9 lines
  
  Add a miniwizard for serials holding codes in the AutoGrid based interfaces,
  sparing the user from needed to input MARC breaker.
  
  TODO:
      i18n
      Don't assume we always start with 4,1,8,1
      auto-populate chronlogy caption fields based on date (this should be easy)
      make it work in a tooltipdialog? (or don't, it seems frustrating)
........
  r17833 | gmc | 2010-09-20 04:27:59 -0400 (Mon, 20 Sep 2010) | 4 lines
  
  marc_add_ids - better failure recovery
  
  Signed-off-by: Galen Charlton <gmc at esilibrary.com>
........
  r17836 | erickson | 2010-09-20 13:09:23 -0400 (Mon, 20 Sep 2010) | 1 line
  
  addd missing opac_visible col and labels to config.usr_setting_type
........
  r17838 | phasefx | 2010-09-20 13:31:51 -0400 (Mon, 20 Sep 2010) | 2 lines
  
  Change behavior of stat cat display in horizontal patron summary.  Stat Cat tab shows all patron.stat_cat_entries.  Entries with usr_summary true also get shown in the Patron Info pane, underneath Email
........
  r17840 | senator | 2010-09-20 13:52:35 -0400 (Mon, 20 Sep 2010) | 2 lines
  
  So I don't have to worry about fixing this misspelling later.
........
  r17843 | scottmk | 2010-09-20 14:07:01 -0400 (Mon, 20 Sep 2010) | 5 lines
  
  Resolving various discrepancies between an upgraded 2.0 database
  and a freshly installed one.
  
  M    Open-ILS/src/sql/Pg/1.6.1-2.0-upgrade-db.sql
........
  r17844 | erickson | 2010-09-20 14:23:56 -0400 (Mon, 20 Sep 2010) | 1 line
  
  added pgpt class to pre-load set
........
  r17848 | senator | 2010-09-20 16:40:23 -0400 (Mon, 20 Sep 2010) | 4 lines
  
  The serials perms that were missing from the DB.
  
  Later it'd be better to make these more a) comprehensive and b) elegant.
........
  r17850 | gmc | 2010-09-20 16:58:02 -0400 (Mon, 20 Sep 2010) | 4 lines
  
  add missing upgrade script for maintain_901() stored function
  
  Signed-off-by: Galen Charlton <gmc at esilibrary.com>
........
  r17853 | senator | 2010-09-20 18:47:35 -0400 (Mon, 20 Sep 2010) | 3 lines
  
  How about one more permission check for serials here? Need more comprehensive
  review of this later.
........
  r17855 | dbs | 2010-09-20 23:05:48 -0400 (Mon, 20 Sep 2010) | 6 lines
  
  Use verbose parameters for createdb
  
  Thomas Berezansky noticed that the README was using "createdb -t template0",
  which isn't a valid option.  To avoid case problems and to be more apparent
  what these options mean, let's use the verbose parameters.
........
  r17857 | dbs | 2010-09-20 23:25:05 -0400 (Mon, 20 Sep 2010) | 12 lines
  
  Append the $0 controlling subfield to newly created authorities
  
  Still a work in progress; obviously we need to try and grab a better
  institutional code, need to teach the "Create and edit..." option
  how to do the same thing, and should augment the "Authority created"
  dialog box to tell the user to save the record or lose the changes
  they just made.
  
  At some point we need to consider auto-saving records, perhaps immediately
  after we provide infinite undo capability to step back through previous
  changes.
........
  r17858 | dbs | 2010-09-20 23:44:35 -0400 (Mon, 20 Sep 2010) | 9 lines
  
  Create and edit... authority record now gets $0 control subfield auto-applied
  
  Following on r17857, when you create an authority record in the flow using
  the "Create and edit..." option, a $0 control subfield will automatically
  be appended to the target field once "Save Record" is clicked on the authority
  record editor pane. Non-savers of the bib record beware! Also subject to
  interesting effects of the bib editor tab gets destroyed before the auth
  record is created via the Save Record button.
........
  r17860 | dbs | 2010-09-20 23:54:26 -0400 (Mon, 20 Sep 2010) | 6 lines
  
  Clean up description of ARN in O:A:Cat::Authority now that arn_value is gone 
  
  A comment in the create_authority_record_from_bib_field() method stated that
  the ARN value needed to be unique across the database; that is no longer true
  as of r17722. Fix comment accordingly.
........
  r17862 | gmc | 2010-09-21 00:46:52 -0400 (Tue, 21 Sep 2010) | 8 lines
  
  add ingest.metarecord_mapping.skip_on_update internal flag
  
  Enabling this allows bibliographic reingests (for new/changed indexes
  or after data changes that don't affect the fingerprint) to be run
  in parallel without lock contention on metarecord.metarecord* operations.
  
  Signed-off-by: Galen Charlton <gmc at esilibrary.com>
........
  r17863 | gmc | 2010-09-21 10:19:31 -0400 (Tue, 21 Sep 2010) | 12 lines
  
  yet another bib ingest knob
  
  When enabled, the ingest.assume_inserts_only flag disables
  checking several tables for old index data to delete; skipping this
  makes a small but noticeable difference when doing an initial bib 
  ingest with more than one process in parallel.
  
  Note that this flag should not be used when *re*ingesting records
  unless you clear the old rows beforehand.
  
  Signed-off-by: Galen Charlton <gmc at esilibrary.com>
........
  r17866 | scottmk | 2010-09-21 11:40:23 -0400 (Tue, 21 Sep 2010) | 5 lines
  
  Correct various discrepancies, especially in the auditor schema,
  between a freshly installed 2.0 database and an upgraded one.
  
  M    Open-ILS/src/sql/Pg/1.6.1-2.0-upgrade-db.sql
........
  r17867 | phasefx | 2010-09-21 12:19:04 -0400 (Tue, 21 Sep 2010) | 2 lines
  
  HoldIsCancelled action_trigger validator
........
  r17869 | phasefx | 2010-09-21 13:02:52 -0400 (Tue, 21 Sep 2010) | 1 line
  
  offline printer role
........
  r17872 | scottmk | 2010-09-21 13:47:53 -0400 (Tue, 21 Sep 2010) | 5 lines
  
  Resolve some discrepancies in the auditor schema between a freshly installed
  database and an upgraded one.
  
  A    Open-ILS/src/sql/Pg/upgrade/0413.schema.upgrade-auditor-tables.sql
........
  r17873 | scottmk | 2010-09-21 14:16:51 -0400 (Tue, 21 Sep 2010) | 4 lines
  
  Don't update history tables to fill in new NOT NULL columns
  
  M    Open-ILS/src/sql/Pg/upgrade/0413.schema.upgrade-auditor-tables.sql
........
  r17875 | scottmk | 2010-09-21 14:31:55 -0400 (Tue, 21 Sep 2010) | 4 lines
  
  Don't make new auditor columns NOT NULL, or update them
  
  M    Open-ILS/src/sql/Pg/1.6.1-2.0-upgrade-db.sql
........
  r17877 | scottmk | 2010-09-21 15:08:54 -0400 (Tue, 21 Sep 2010) | 4 lines
  
  Replace some changes that had inadvertently been deleted
  
  M    Open-ILS/src/sql/Pg/1.6.1-2.0-upgrade-db.sql
........
  r17879 | phasefx | 2010-09-21 20:55:55 -0400 (Tue, 21 Sep 2010) | 2 lines
  
  use fieldmapper.standardRequest here for easier configuration of the network timeout (the full pull list can take a while to return)
........
  r17881 | phasefx | 2010-09-21 21:03:19 -0400 (Tue, 21 Sep 2010) | 2 lines
  
  handle null as a return result for an empty list
........
  r17883 | dbs | 2010-09-21 22:12:32 -0400 (Tue, 21 Sep 2010) | 6 lines
  
  Forward port r17847: Make query parser a bit more careful when converting convenience classes to search classes
  
  Queries like "Heart disease: a global problem" were getting converted to series searches
  due to the trailing "se:" in the search terms. This change ensures that the convenience
  class is either at the start of the input or preceded by whitespace.
........
  r17886 | scottmk | 2010-09-22 08:55:28 -0400 (Wed, 22 Sep 2010) | 9 lines
  
  In acq.fund_transfer: drop the NOT NULL constraint from dest_fund and
  dest_amount, in order to accommodate deallocations -- where we move
  money out of a fund without moving it into another fund.
  
  This change was applied via upgrade script # 0135, but apparently was
  never applied to the base installation script.
  
  M    Open-ILS/src/sql/Pg/200.schema.acq.sql
........



Property changes on: branches/serials-integration
___________________________________________________________________
Name: svnmerge-integrated
   - /trunk:1-17253
   + /trunk:1-17887

Modified: branches/serials-integration/Makefile.am
===================================================================
--- branches/serials-integration/Makefile.am	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Makefile.am	2010-10-18 13:46:56 UTC (rev 18371)
@@ -15,6 +15,7 @@
 export WEBDIR=@localstatedir@/web
 export CGIDIR=@localstatedir@/cgi-bin
 export TEMPLATEDIR=@localstatedir@/templates
+export UPDATESDIR=@localstatedir@/updates
 
 export datadir=@localstatedir@/data
 export circrulesdir=@localstatedir@/circ
@@ -38,5 +39,5 @@
 export OPENSRF_HEADERS = @OPENSRF_HEADERS@
 export OPENSRF_LIBS = @OPENSRF_LIBS@
 
-SUBDIRS = Open-ILS/src Open-ILS/web Open-ILS/xul/staff_client
+SUBDIRS = Open-ILS/src Open-ILS/web Open-ILS/updates Open-ILS/xul/staff_client
 

Modified: branches/serials-integration/Open-ILS/examples/apache/eg.conf
===================================================================
--- branches/serials-integration/Open-ILS/examples/apache/eg.conf	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/examples/apache/eg.conf	2010-10-18 13:46:56 UTC (rev 18371)
@@ -53,8 +53,8 @@
 # ----------------------------------------------------------------------------------
 # System config CGI scripts go here
 # ----------------------------------------------------------------------------------
-Alias /cgi-bin/ "/openils/var/cgi-bin/"
-<Directory "/openils/var/cgi-bin">
+Alias /cgi-bin/offline/ "/openils/var/cgi-bin/offline/"
+<Directory "/openils/var/cgi-bin/offline">
 	AddHandler cgi-script .cgi .pl
 	AllowOverride None
 	Options None
@@ -65,7 +65,30 @@
 </Directory>
 
 
+# ----------------------------------------------------------------------------------
+# Updates folder
+# ----------------------------------------------------------------------------------
+Alias /updates/ "/openils/var/updates/pub/"
+<Directory "/openils/var/updates/pub">
+	<Files check>
+		ForceType cgi-script
+	</Files>
+	<Files update.rdf>
+		ForceType cgi-script
+	</Files>
+	<Files manualupdate.html>
+		ForceType cgi-script
+	</Files>
+	<Files download>
+		ForceType cgi-script
+	</Files>
+	AllowOverride None
+	Options None
+	Allow from all
+	Options ExecCGI
+</Directory>
 
+
 # ----------------------------------------------------------------------------------
 # OPTIONAL: Set how long the client will cache our content.  Change to suit
 # ----------------------------------------------------------------------------------

Modified: branches/serials-integration/Open-ILS/examples/apache/eg_vhost.conf
===================================================================
--- branches/serials-integration/Open-ILS/examples/apache/eg_vhost.conf	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/examples/apache/eg_vhost.conf	2010-10-18 13:46:56 UTC (rev 18371)
@@ -9,9 +9,25 @@
 RedirectMatch 301 ^/$ /opac/en-US/skin/default/xml/index.xml
 
 # ----------------------------------------------------------------------------------
+# Point / to the IP address redirector
+# ----------------------------------------------------------------------------------
+#<LocationMatch ^/$>
+#    SetHandler perl-script
+#    PerlHandler OpenILS::WWW::Redirect
+#    Options +ExecCGI
+#    PerlSendHeader On
+#    #PerlSetVar OILSRedirectSkin "default"
+#    # OILSRedirectDepth defaults to the depth of the branch that the OPAC was directed to
+#    #PerlSetVar OILSRedirectDepth "0"
+#    #PerlSetVar OILSRedirectLocale "en-US"
+#    allow from all
+#</LocationMatch>
+
+
+# ----------------------------------------------------------------------------------
 # Assign a default locale to the accessible OPAC
 # ----------------------------------------------------------------------------------
-RedirectMatch 301 ^/opac/extras/slimpac/start.html$ /opac/en-US/extras/slimpac/start.html
+RedirectMatch 301 ^/opac/extras/slimpac/start.html$    /opac/en-US/extras/slimpac/start.html
 RedirectMatch 301 ^/opac/extras/slimpac/advanced.html$ /opac/en-US/extras/slimpac/advanced.html
 
 # ----------------------------------------------------------------------------------
@@ -112,7 +128,66 @@
 
 </LocationMatch>
 
+<Location /opac/>
+    # ----------------------------------------------------------------------------------
+    # Some mod_deflate fun
+    # ----------------------------------------------------------------------------------
+    <IfModule mod_deflate.c>
+        SetOutputFilter DEFLATE
 
+        BrowserMatch ^Mozilla/4 gzip-only-text/html
+        BrowserMatch ^Mozilla/4\.0[678] no-gzip
+        BrowserMatch \bMSI[E] !no-gzip !gzip-only-text/html
+
+        SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png)$ no-gzip dont-vary
+
+        <IfModule mod_headers.c>
+            Header append Vary User-Agent env=!dont-vary
+        </IfModule>
+    </IfModule>
+
+</Location>
+
+<Location //opac/>
+    # ----------------------------------------------------------------------------------
+    # Some mod_deflate fun
+    # ----------------------------------------------------------------------------------
+    <IfModule mod_deflate.c>
+        SetOutputFilter DEFLATE
+
+        BrowserMatch ^Mozilla/4 gzip-only-text/html
+        BrowserMatch ^Mozilla/4\.0[678] no-gzip
+        BrowserMatch \bMSI[E] !no-gzip !gzip-only-text/html
+
+        SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png)$ no-gzip dont-vary
+
+        <IfModule mod_headers.c>
+            Header append Vary User-Agent env=!dont-vary
+        </IfModule>
+    </IfModule>
+
+</Location>
+
+<Location /js/>
+    # ----------------------------------------------------------------------------------
+    # Some mod_deflate fun
+    # ----------------------------------------------------------------------------------
+    <IfModule mod_deflate.c>
+        SetOutputFilter DEFLATE
+
+        BrowserMatch ^Mozilla/4 gzip-only-text/html
+        BrowserMatch ^Mozilla/4\.0[678] no-gzip
+        BrowserMatch \bMSI[E] !no-gzip !gzip-only-text/html
+
+        SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png)$ no-gzip dont-vary
+
+        <IfModule mod_headers.c>
+            Header append Vary User-Agent env=!dont-vary
+        </IfModule>
+    </IfModule>
+
+</Location>
+
 # ----------------------------------------------------------------------------------
 # Force SSL on the OPAC's "My Account" page
 # ----------------------------------------------------------------------------------
@@ -367,6 +442,17 @@
 </LocationMatch>
 
 # ----------------------------------------------------------------------------------
+# EDI Message viewer
+# ----------------------------------------------------------------------------------
+<Location /edi>
+    SetHandler perl-script
+    PerlHandler OpenILS::WWW::EDI
+    Options +ExecCGI
+    PerlSendHeader On
+    allow from all
+</Location> 	
+
+# ----------------------------------------------------------------------------------
 # XML-RPC gateway
 # ----------------------------------------------------------------------------------
 <Location /xml-rpc>
@@ -456,4 +542,15 @@
     SetHandler None
 </LocationMatch>
 
+# ----------------------------------------------------------------------------------
+# Some mod_deflate logging setup
+# ----------------------------------------------------------------------------------
+<IfModule mod_deflate.c>
+    DeflateFilterNote Input instream
+    DeflateFilterNote Output outstream
+    DeflateFilterNote Ratio ratio
 
+    LogFormat '"%r" %{outstream}n/%{instream}n (%{ratio}n%%)' deflate
+    CustomLog /var/log/apache2/deflate_log deflate
+</IfModule>
+

Modified: branches/serials-integration/Open-ILS/examples/fm_IDL.xml
===================================================================
--- branches/serials-integration/Open-ILS/examples/fm_IDL.xml	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/examples/fm_IDL.xml	2010-10-18 13:46:56 UTC (rev 18371)
@@ -1398,11 +1398,9 @@
 			<link field="item" reltype="has_a" key="id" map="" class="ccbi"/>
 		</links>
 	</class>
-	<class id="are" controller="open-ils.cstore" oils_obj:fieldmapper="authority::record_entry" oils_persist:tablename="authority.record_entry" reporter:label="Authority Record Entry">
+	<class id="are" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="authority::record_entry" oils_persist:tablename="authority.record_entry" reporter:label="Authority Record Entry">
 		<fields oils_persist:primary="id" oils_persist:sequence="authority.record_entry_id_seq">
 			<field name="active" reporter:datatype="bool"/>
-			<field name="arn_source" />
-			<field name="arn_value" />
 			<field name="create_date" reporter:datatype="timestamp"/>
 			<field name="creator" />
 			<field name="deleted" reporter:datatype="bool"/>
@@ -1425,6 +1423,14 @@
 			<link field="bib_links" reltype="has_many" key="authority" map="" class="abl"/>
 			<link field="fixed_fields" reltype="might_have" key="record" map="" class="ard"/>
 		</links>
+		<permacrud xmlns="http://open-ils.org/spec/opensrf/IDL/permacrud/v1">
+			<actions>
+				<create permission="CREATE_MARC IMPORT_MARC" global_required="true"/>
+				<retrieve/>
+				<update permission="UPDATE_MARC" global_required="true"/>
+				<delete permission="UPDATE_MARC" global_required="true"/>
+			</actions>
+		</permacrud>
 	</class>
 	<class id="ard" controller="open-ils.cstore" oils_obj:fieldmapper="authority::record_descriptor" oils_persist:tablename="authority.rec_descriptor" reporter:label="Authority Record Descriptor">
 		<fields oils_persist:primary="id" oils_persist:sequence="authority.rec_descriptor_id_seq">
@@ -1773,6 +1779,7 @@
 			<field reporter:label="Flattened MARC Fields " name="full_record_entries" oils_persist:virtual="true" reporter:datatype="link"/>
 			<field reporter:label="Simple Record Extracts " name="simple_record" oils_persist:virtual="true" reporter:datatype="link"/>
 			<field reporter:label="Authority Links" name="authority_links" oils_persist:virtual="true" reporter:datatype="link"/>
+			<field reporter:label="Subscriptions" name="subscriptions" oils_persist:virtual="true" reporter:datatype="link"/>
 		</fields>
 		<links>
 			<link field="owner" reltype="has_a" key="id" map="" class="aou"/>
@@ -1792,6 +1799,7 @@
 			<link field="series_field_entries" reltype="has_many" key="source" map="" class="msefe"/>
 			<link field="full_record_entries" reltype="has_many" key="record" map="" class="mfr"/>
 			<link field="authority_links" reltype="has_many" key="bib" map="" class="abl"/>
+			<link field="subscriptions" reltype="has_many" key="record_entry" map="" class="ssub"/>
 		</links>
         <permacrud xmlns="http://open-ils.org/spec/opensrf/IDL/permacrud/v1">
             <actions>
@@ -2015,12 +2023,13 @@
 	</class>
 	<class id="cust" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="config::usr_setting_type" oils_persist:tablename="config.usr_setting_type" reporter:label="User Setting Type">
 		<fields oils_persist:primary="name">
-			<field name="name" reporter:datatype="text"/>
-			<field name="label" reporter:datatype="text"/>
-			<field name="description" reporter:datatype="text"/>
-			<field name="datatype" reporter:datatype="text"/>
-			<field name="fm_class" reporter:datatype="text"/>
-			<field name="grp" reporter:datatype="link"/>
+			<field name="name" reporter:label="Name" reporter:datatype="text"/>
+			<field name="label" reporter:label="Label" reporter:datatype="text"/>
+			<field name="description" reporter:label="Description" reporter:datatype="text"/>
+			<field name="datatype" reporter:label="Datatype" reporter:datatype="text"/>
+			<field name="fm_class" reporter:label="Fielmapper Class" reporter:datatype="text"/>
+			<field name="grp" reporter:label="Settings Group" reporter:datatype="link"/>
+			<field name="opac_visible" reporter:label="OPAC/Patron Visible" reporter:datatype="bool"/>
 		</fields>
 		<links>
 			<link field="name" reltype="has_many" key="name" map="" class="aus"/>
@@ -3048,6 +3057,8 @@
 			<field reporter:label="Owning Org Unit" name="owning_lib"  reporter:datatype="org_unit"/>
 			<field reporter:label="Copy Location Orders" name="orders" oils_persist:virtual="true" reporter:datatype="link"/>
 			<field reporter:label="Copies" name="copies" oils_persist:virtual="true" reporter:datatype="link"/>
+			<field reporter:label="Label Prefix" name="label_prefix"  reporter:datatype="text" oils_persist:i18n="true"/>
+			<field reporter:label="Label Suffix" name="label_suffix"  reporter:datatype="text" oils_persist:i18n="true"/>
 		</fields>
 		<links>
 			<link field="owning_lib" reltype="has_a" key="id" map="" class="aou"/>
@@ -3158,13 +3169,25 @@
 			<link field="subscription" reltype="has_a" key="id" map="" class="ssub"/>
 		</links>
 		<permacrud xmlns="http://open-ils.org/spec/opensrf/IDL/permacrud/v1">
+			<actions>
+				<create permission="ADMIN_SERIAL_CAPTION_PATTERN">
+					<context link="subscription" field="owning_lib" />
+				</create>
+				<retrieve />
+				<update permission="ADMIN_SERIAL_CAPTION_PATTERN">
+					<context link="subscription" field="owning_lib" />
+				</update>
+				<delete permission="ADMIN_SERIAL_CAPTION_PATTERN">
+					<context link="subscription" field="owning_lib" />
+				</delete>
+			</actions>
 		</permacrud>
 	</class>
 
-	<class id="ssub" controller="open-ils.cstore" oils_obj:fieldmapper="serial::subscription" oils_persist:tablename="serial.subscription" reporter:label="Subscription">
+	<class id="ssub" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="serial::subscription" oils_persist:tablename="serial.subscription" reporter:label="Subscription">
 		<fields oils_persist:primary="id" oils_persist:sequence="serial.subscription_id_seq">
-			<field reporter:label="Id" name="id" reporter:datatype="id"/>
-			<field reporter:label="Owning Library" name="owning_lib" reporter:datatype="link"/>
+			<field reporter:label="ID" name="id" reporter:datatype="id"/>
+			<field reporter:label="Owning Library" name="owning_lib" reporter:datatype="org_unit"/>
 			<field reporter:label="Start Date" name="start_date" reporter:datatype="timestamp"/>
 			<field reporter:label="End Date" name="end_date" reporter:datatype="timestamp"/>
 			<field reporter:label="Bibliographic Record Entry" name="record_entry" reporter:datatype="link"/>
@@ -3182,6 +3205,14 @@
 			<link field="scaps" reltype="has_many" key="subscription" map="" class="scap"/>
 			<link field="notes" reltype="has_many" key="subscription" map="" class="ssubn"/>
 		</links>
+		<permacrud xmlns="http://open-ils.org/spec/opensrf/IDL/permacrud/v1">
+			<actions>
+				<create permission="ADMIN_SERIAL_SUBSCRIPTION" context_field="owning_lib"/>
+				<retrieve />
+				<update permission="ADMIN_SERIAL_SUBSCRIPTION" context_field="owning_lib"/>
+				<delete permission="ADMIN_SERIAL_SUBSCRIPTION" context_field="owning_lib"/>
+			</actions>
+		</permacrud>
 	</class>
 
 	<class id="ssubn" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="serial::subscription_note" oils_persist:tablename="serial.subscription_note" reporter:label="Subscription Note">
@@ -3207,7 +3238,7 @@
 			<field reporter:label="ID" name="id" reporter:datatype="id"/>
 			<field reporter:label="Legacy Record Entry" name="record_entry" reporter:datatype="link"/>
 			<field reporter:label="Subscription" name="subscription" reporter:datatype="link"/>
-			<field reporter:label="Holding Lib" name="holding_lib" reporter:datatype="link"/>
+			<field reporter:label="Holding Lib" name="holding_lib" reporter:datatype="org_unit"/>
 			<field reporter:label="Label" name="label" reporter:datatype="text"/>
 			<field reporter:label="Receive Call Number" name="receive_call_number" reporter:datatype="link"/>
 			<field reporter:label="Receive Unit Template" name="receive_unit_template" reporter:datatype="link"/>
@@ -3237,10 +3268,10 @@
 		</links>
 		<permacrud xmlns="http://open-ils.org/spec/opensrf/IDL/permacrud/v1">
 			<actions>
-				<create/>
-				<retrieve/>
-				<update/>
-				<delete/>
+				<create permission="ADMIN_SERIAL_DISTRIBUTION" context_field="holding_lib" />
+				<retrieve />
+				<update permission="ADMIN_SERIAL_DISTRIBUTION" context_field="holding_lib" />
+				<delete permission="ADMIN_SERIAL_DISTRIBUTION" context_field="holding_lib" />
 			</actions>
 		</permacrud>
 	</class>
@@ -3279,6 +3310,18 @@
 			<link field="distribution" reltype="has_a" key="id" map="" class="sdist"/>
 		</links>
 		<permacrud xmlns="http://open-ils.org/spec/opensrf/IDL/permacrud/v1">
+			<actions>
+				<create permission="ADMIN_SERIAL_STREAM">
+					<context link="distribution" field="holding_lib" />
+				</create>
+				<retrieve />
+				<update permission="ADMIN_SERIAL_STREAM">
+					<context link="distribution" field="holding_lib" />
+				</update>
+				<delete permission="ADMIN_SERIAL_STREAM">
+					<context link="distribution" field="holding_lib" />
+				</delete>
+			</actions>
 		</permacrud>
 	</class>
 
@@ -4386,7 +4429,7 @@
 
 	<class id="act" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="asset::copy_template" oils_persist:tablename="asset.copy_template" reporter:label="Asset Copy Template">
 		<fields oils_persist:primary="id" oils_persist:sequence="asset.copy_template_id_seq">
-			<field reporter:label="ID" name="id" reporter:datatype="id"/>
+			<field reporter:label="ID" name="id" reporter:datatype="id" reporter:selector="name" />
 			<field reporter:label="Owning Lib" name="owning_lib" reporter:datatype="link"/>
 			<field reporter:label="Creator" name="creator" reporter:datatype="link"/>
 			<field reporter:label="Editor" name="editor" reporter:datatype="link"/>
@@ -4990,7 +5033,7 @@
 	</class>
 	<class id="cbt" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="config::billing_type" oils_persist:tablename="config.billing_type" oils_persist:restrict_primary="100" reporter:label="Billing Type">
 		<fields oils_persist:primary="id" oils_persist:sequence="config.billing_type_id_seq">
-			<field name="id" reporter:datatype="id" reporter:label="ID" />
+			<field name="id" reporter:datatype="id" reporter:label="ID" reporter:selector="name"/>
 			<field name="name" reporter:datatype="text" reporter:label="Name" oils_persist:i18n="true"/>
 			<field name="owner" reporter:datatype="org_unit" reporter:label="Org Unit" />
             <field name="default_price" reporter:datatype="money" reporter:label="Default Price"/>
@@ -5424,7 +5467,7 @@
 
 	<class id="acqfc" controller="open-ils.cstore" oils_obj:fieldmapper="acq::fiscal_calendar" oils_persist:tablename="acq.fiscal_calendar" reporter:label="Fiscal Calendar">
 		<fields oils_persist:primary="id" oils_persist:sequence="acq.fiscal_calendar_id_seq">
-			<field reporter:label="Fiscal Calendar ID" name="id" reporter:datatype="id" reporter:selector='id'/>
+			<field reporter:label="Fiscal Calendar ID" name="id" reporter:datatype="id" reporter:selector='name'/>
 			<field reporter:label="Fiscal Calendar Name" name="name" reporter:datatype="text"/>
 			<field reporter:label="Years" name="years" oils_persist:virtual="true" reporter:datatype="link"/>
 		</fields>
@@ -5447,7 +5490,7 @@
 
 	<class id="acqfy" controller="open-ils.cstore" oils_obj:fieldmapper="acq::fiscal_year" oils_persist:tablename="acq.fiscal_year" reporter:label="Fiscal Year">
 		<fields oils_persist:primary="id" oils_persist:sequence="acq.fiscal_year_id_seq">
-			<field reporter:label="Fiscal Year ID" name="id" reporter:datatype="id" reporter:selector='id'/>
+			<field reporter:label="Fiscal Year ID" name="id" reporter:datatype="id" reporter:selector='year'/>
 			<field reporter:label="Calendar" name="calendar" reporter:datatype="link"/>
 			<field reporter:label="Fiscal Year" name="year" reporter:datatype="int"/>
 			<field reporter:label="Year Begin" name="year_begin" reporter:datatype="timestamp"/>
@@ -6034,7 +6077,7 @@
 			<field reporter:label="Line Item Details" name="lineitem_details" oils_persist:virtual="true" reporter:datatype="link" />
 			<field reporter:label="Line Item Notes" name="lineitem_notes" oils_persist:virtual="true" reporter:datatype="link" />
 			<field reporter:label="Distribution Formulas" name="distribution_formulas" oils_persist:virtual="true" reporter:datatype="link" />
-			<field reporter:label="Envoice Enties" name="invoice_entries" oils_persist:virtual="true" reporter:datatype="link" />
+			<field reporter:label="Invoice Entries" name="invoice_entries" oils_persist:virtual="true" reporter:datatype="link" />
 			<field reporter:label="Order Summary" name="order_summary" oils_persist:virtual="true" reporter:datatype="link" />
 		</fields>
 		<links>

Copied: branches/serials-integration/Open-ILS/examples/list_perms.pl (from rev 17886, trunk/Open-ILS/examples/list_perms.pl)
===================================================================
--- branches/serials-integration/Open-ILS/examples/list_perms.pl	                        (rev 0)
+++ branches/serials-integration/Open-ILS/examples/list_perms.pl	2010-10-18 13:46:56 UTC (rev 18371)
@@ -0,0 +1,59 @@
+#!/usr/bin/perl -w
+
+# Extract permission names from the output of the dump_idl utility.
+
+# The logic necessarily makes assumptions about the format of
+# dump_idl's output.  If that format changes, the logic may no longer work.
+
+# In the output: each permission name appears on a separate line, 
+# flush left.  Normally the output should be piped into sort -u in
+# order to eliminate duplicates.
+
+use strict;
+
+my $in_perms = 0;
+my $perm_indent;
+
+# Return the number of leading white space characters.
+# We do not distinguish between tabs and spaces.
+sub indent_level {
+	my $str = shift;
+	return 0 unless (defined( $str ));
+	$str =~ s/\S.*//;       # Remove everything after the leading white space
+	return length $str;     # Take the length of what's left
+}
+
+while(<>) {
+	if( $in_perms ) {
+		
+		# Check the indentation to see if we're still
+		# inside the list of permissions.
+
+		if ( indent_level( $_ ) > $perm_indent ) {
+
+			# This line contains a permission name.
+			# Strip off the leading white space and write it.
+
+			s/^\s*//;
+			print;
+		} else {
+
+			# We're no longer inside the list of permissions.
+
+			$in_perms = 0;
+		}
+	} elsif (/\s+permission [(]string array[)]$/) {
+
+		# We are entering a list of permissions, each of which is
+		# indented further than this line.  When we see a line that
+		# is *not* further indented, that will end the list.
+
+		# The indentation is defined as the number of leading white
+		# space characters, be they tabs or spaces.  If the format of
+		# the dump_idl output is changed to involve some bizarre and
+		# perverse mixture of tabs and spaces, this logic may not work.
+
+		$in_perms = 1;
+		$perm_indent = indent_level( $_ );
+	}
+}

Modified: branches/serials-integration/Open-ILS/examples/oils_ctl.sh
===================================================================
--- branches/serials-integration/Open-ILS/examples/oils_ctl.sh	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/examples/oils_ctl.sh	2010-10-18 13:46:56 UTC (rev 18371)
@@ -3,6 +3,7 @@
 OPT_ACTION=""
 OPT_SIP_CONFIG=""
 OPT_PID_DIR=""
+OPT_SIP_ERR_LOG="/dev/null";
 SIP_DIR="/opt/SIPServer";
 
 # ---------------------------------------------------------------------------
@@ -13,13 +14,12 @@
 
 function usage {
 	echo "";
-	echo "usage: $0 -d <pid_dir> -s <sip_config> -a <action>";
+	echo "usage: $0 -d <pid_dir> -s <sip_config> -a <action> -l <sip_err_log>";
 	echo "";
 	echo "Actions include:"
 	echo -e "\tstart_sip"
 	echo -e "\tstop_sip"
 	echo -e "\trestart_sip"
-	echo "";
 	exit;
 }
 
@@ -27,11 +27,12 @@
 # ---------------------------------------------------------------------------
 # Load the command line options and set the global vars
 # ---------------------------------------------------------------------------
-while getopts  "a:d:s:" flag; do
+while getopts "a:d:s:l:" flag; do
 	case $flag in	
 		"a")		OPT_ACTION="$OPTARG";;
 		"s")		OPT_SIP_CONFIG="$OPTARG";;
 		"d")		OPT_PID_DIR="$OPTARG";;
+		"l")		OPT_SIP_ERR_LOG="$OPTARG";;
 		"h"|*)	usage;;
 	esac;
 done
@@ -89,7 +90,7 @@
 	do_action "start" $PID_SIP "OILS SIP Server";
 	DIR=$(pwd);
 	cd $SIP_DIR;
-    perl SIPServer.pm "$OPT_SIP_CONFIG" > /dev/null 2>&1 &
+    perl SIPServer.pm "$OPT_SIP_CONFIG" >> "$OPT_SIP_ERR_LOG" 2>&1 &
 	pid=$!;
 	cd $DIR;
 	echo $pid > $PID_SIP;

Modified: branches/serials-integration/Open-ILS/examples/oils_sip.xml.example
===================================================================
--- branches/serials-integration/Open-ILS/examples/oils_sip.xml.example	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/examples/oils_sip.xml.example	2010-10-18 13:46:56 UTC (rev 18371)
@@ -99,6 +99,10 @@
 					  default behaviour in previous versions of Evergreen.
 					-->
 					<option name='msg64_summary_datatype' value='barcode' />
+					<!--
+						If enabled, the PC field in patron-info requests will return the non-translated profile name
+					<option name='patron_type_uses_code' value='true' />
+					-->
 				</options>
 
                 <!-- If uncommented, overrides the legacy_script_support value in opensrf.xml for SIP. -->
@@ -123,3 +127,7 @@
 	
 	</institutions>
 </acsconfig>
+
+<!--
+    vim:noet:ts=4:sw=4:
+-->

Modified: branches/serials-integration/Open-ILS/examples/openils.profile.js
===================================================================
--- branches/serials-integration/Open-ILS/examples/openils.profile.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/examples/openils.profile.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -1,50 +1,223 @@
-dependencies ={
-    layers: [
-{
-    name: "openils_dojo.js",
-    dependencies: [
+dependencies = {
+    layers: [{
+        name: "openils_all_opac_dojo.js",
+        dependencies: [
+
+                   "dijit._Calendar",
+                   "dijit.Menu",
+                   "dojo.io.script",
+                   "dijit.Dialog",
+                   "dijit.form.Button",
+                   "dijit.form.CheckBox",
                    "dijit.form.CurrencyTextBox",
-                   "dijit.Menu",
+                   "dijit.form.DateTextBox",
                    "dijit.form.FilteringSelect",
+                   "dijit.form._FormWidget",
+                   "dijit.form.NumberSpinner",
+                   "dijit.form.NumberTextBox",
+                   "dijit.form.TextBox",
+                   "dijit.form.ValidationTextBox",
+                   "dijit.layout.ContentPane",
+                   "dijit.ProgressBar",
+                   "dijit._Templated",
+                   "dijit._Widget",
+                   "dojo.cookie",
+                   "dojo.data.ItemFileReadStore",
+                   "dojo.data.ItemFileWriteStore",
+                   "dojo.date.locale",
+                   "dojo.date.stamp",
+                   "dojo.query",
+                   "dojo.string",
                    "dojox.grid.compat._data.dijitEditors",
+                   "dojox.grid.compat._data.editors",
+                   "dojox.grid.compat._data.model",
+                   "dojox.grid.DataGrid",
+                   "dojox.grid.Grid",
                    "dojox.jsonPath",
+                   "dojox.xml.parser"
+        ]
+    },{
+        name: "openils_ui_dojo.js",
+        dependencies: [
+                   "dijit.Dialog",
+                   "dijit.form.Button",
+                   "dijit.form.CheckBox",
+                   "dijit.form.ComboBox",
+                   "dijit.form.CurrencyTextBox",
+                   "dijit.form.DateTextBox",
+                   "dijit.form.DropDownButton",
+                   "dijit.form.FilteringSelect",
+                   "dijit.form.Form",
+                   "dijit.form.NumberSpinner",
+                   "dijit.form.NumberTextBox",
+                   "dijit.form.RadioButton",
+                   "dijit.form.Textarea",
+                   "dijit.form.TextBox",
+                   "dijit.form.TimeTextBox",
+                   "dijit.layout.ContentPane",
+                   "dijit.layout.LayoutContainer",
+                   "dijit.layout.SplitContainer",
+                   "dijit.layout.StackContainer",
+                   "dijit.layout.TabContainer",
+                   "dijit.Menu",
+                   "dijit.MenuItem",
                    "dijit.ProgressBar",
                    "dijit.Toolbar",
-                   "dijit.form.TextBox",
+                   "dijit.Tooltip",
+                   "dijit.TooltipDialog",
+                   "dojo.cookie",
+                   "dojo.data.ItemFileReadStore",
+                   "dojo.data.ItemFileWriteStore",
+                   "dojo.date",
+                   "dojo.date.locale",
+                   "dojo.date.stamp",
+                   "dojo.dnd.Container",
+                   "dojo.dnd.Source",
+                   "dojo.io.iframe",
+                   "dojo.parser",
+                   "dojo.string",
+                   "dojox.encoding.base64",
+                   "dojox.form.CheckedMultiSelect",
+                   "dojox.grid.cells.dijit",
                    "dojox.grid.DataGrid",
-                   "dojox.fx",
-                   "dijit.layout.BorderContainer",
                    "dojox.grid.Grid",
+                   "dojox.string.sprintf",
+                   "dojox.widget.PlaceholderMenuItem",
+                   "dojox.xml.parser"
+        ]
+    },{
+        name: "openils_full_dojo.js",
+        dependencies: [
+                   "dijit._Calendar",
+                   "dijit.Dialog",
+                   "dijit.form.Button",
+                   "dijit.form.CheckBox",
+                   "dijit.form.ComboBox",
+                   "dijit.form.CurrencyTextBox",
+                   "dijit.form.DateTextBox",
+                   "dijit.form.DropDownButton",
+                   "dijit.form.FilteringSelect",
+                   "dijit.form.Form",
+                   "dijit.form._FormWidget",
+                   "dijit.form.NumberSpinner",
+                   "dijit.form.NumberTextBox",
+                   "dijit.form.RadioButton",
+                   "dijit.form.Textarea",
+                   "dijit.form.TextBox",
+                   "dijit.form.TimeTextBox",
                    "dijit.form.ValidationTextBox",
-                   "dijit.form.ComboBox",
+                   "dijit.layout.BorderContainer",
+                   "dijit.layout.ContentPane",
                    "dijit.layout.LayoutContainer",
+                   "dijit.layout.SplitContainer",
+                   "dijit.layout.StackContainer",
+                   "dijit.layout.TabContainer",
+                   "dijit.Menu",
+                   "dijit.MenuItem",
+                   "dijit.ProgressBar",
+                   "dijit._Templated",
+                   "dijit.Toolbar",
+                   "dijit.Tooltip",
+                   "dijit.TooltipDialog",
                    "dijit.Tree",
-                   "dijit.form.NumberSpinner",
-                   "dijit.Tooltip",
-                   "dojox.widget.PlaceholderMenuItem",
-                   "dijit.form.Form",
-                   "dijit.form.Textarea",
+                   "dijit._Widget",
+                   "dojo.cookie",
                    "dojo.data.ItemFileReadStore",
                    "dojo.data.ItemFileWriteStore",
+                   "dojo.date",
+                   "dojo.date.locale",
+                   "dojo.date.stamp",
+                   "dojo.dnd.Container",
+                   "dojo.dnd.Source",
+                   "dojo.io.iframe",
+                   "dojo.io.script",
+                   "dojo.parser",
+                   "dojo.query",
+                   "dojo.string",
+                   "dojox.encoding.base64",
+                   "dojox.form.CheckedMultiSelect",
+                   "dojox.fx",
+                   "dojox.grid.cells.dijit",
+                   "dojox.grid.compat._data.dijitEditors",
+                   "dojox.grid.compat._data.editors",
+                   "dojox.grid.compat._data.model",
+                   "dojox.grid.DataGrid",
+                   "dojox.grid.Grid",
+                   "dojox.jsonPath",
+                   "dojox.string.sprintf",
+                   "dojox.widget.PlaceholderMenuItem",
+                   "dojox.widget.Toaster",
+                   "dojox.xml.parser"
+        ]
+    },{
+        name: "openils_opac_dojo.js",
+        dependencies: [
+                   "dijit._Calendar",
+                   "dijit.Dialog",
                    "dijit.form.Button",
                    "dijit.form.DateTextBox",
-                   "dijit.layout.ContentPane",
+                   "dijit.form.FilteringSelect",
+                   "dijit.form.TextBox",
+                   "dijit.Menu",
+                   "dojo.cookie",
+                   "dojo.date.locale",
+                   "dojo.date.stamp",
+                   "dojo.io.script",
+                   "dojo.parser"
+        ]
+    },{
+        name: "openils_dojo.js",
+        dependencies: [
+                   "dijit._Calendar",
                    "dijit.Dialog",
-                   "dojox.widget.Toaster",
+                   "dijit.form.Button",
+                   "dijit.form.DateTextBox",
+                   "dijit.form.FilteringSelect",
+                   "dijit.form.TextBox",
+                   "dijit.Menu",
+                   "dojo.cookie",
+                   "dojo.date.locale",
+                   "dojo.date.stamp",
+                   "dojo.io.script",
+                   "dojo.parser"
+        ]
+    },{
+        name: "openils_dojo_dojo.js",
+        dependencies: [
+                   "dijit.Dialog",
+                   "dijit.form.Button",
+                   "dijit.form.CheckBox",
+                   "dijit.form.CurrencyTextBox",
+                   "dijit.form.DateTextBox",
+                   "dijit.form.FilteringSelect",
+                   "dijit.form._FormWidget",
+                   "dijit.form.NumberSpinner",
                    "dijit.form.NumberTextBox",
-                   "dijit.layout.SplitContainer",
-                   "dojox.form.CheckedMultiSelect",
-                   "dijit.form.TimeTextBox",
-                   "dijit.form.CheckBox",
-                   "dijit.layout.TabContainer",
-                   "dojo.io.script"
-                   ]
-}
-
-             ],
+                   "dijit.form.TextBox",
+                   "dijit.form.ValidationTextBox",
+                   "dijit.layout.ContentPane",
+                   "dijit.ProgressBar",
+                   "dijit._Templated",
+                   "dijit._Widget",
+                   "dojo.cookie",
+                   "dojo.data.ItemFileReadStore",
+                   "dojo.data.ItemFileWriteStore",
+                   "dojo.date.locale",
+                   "dojo.date.stamp",
+                   "dojo.query",
+                   "dojo.string",
+                   "dojox.grid.compat._data.dijitEditors",
+                   "dojox.grid.compat._data.editors",
+                   "dojox.grid.compat._data.model",
+                   "dojox.grid.DataGrid",
+                   "dojox.grid.Grid",
+                   "dojox.jsonPath",
+                   "dojox.xml.parser"
+        ]
+    }],
     prefixes: [
-               [ "dijit", "../dijit" ],
-               [ "dojox", "../dojox" ]
-               ]
+        [ "dijit", "../dijit" ],
+        [ "dojox", "../dojox" ]
+    ]
 };
                

Modified: branches/serials-integration/Open-ILS/examples/opensrf.xml.example
===================================================================
--- branches/serials-integration/Open-ILS/examples/opensrf.xml.example	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/examples/opensrf.xml.example	2010-10-18 13:46:56 UTC (rev 18371)
@@ -262,18 +262,10 @@
 
         <added_content>
 
-            <!-- XXX If you use the Amazon plugin, you must link back to Amazon in the OPAC -->
+            <!-- load the OpenLibrary added content module -->
+            <module>OpenILS::WWW::AddedContent::OpenLibrary</module>
 
-            <!-- load the Amazon added content module -->
-            <module>OpenILS::WWW::AddedContent::Amazon</module>
             <!--
-            Base URL for Amazon added content fetching.  This URL may
-            need to be shortened when new (read: non-image) content 
-            fetching capabilities are added
-            -->
-            <base_url>http://images.amazon.com/images/P/</base_url>
-
-            <!--
             Max number of seconds to wait for an added content request to 
             return data.  Data not returned within the timeout is considered
             a failure
@@ -297,6 +289,11 @@
             <userid>MY_USER_ID</userid>
 
             <!--
+            Base URL for Amazon added content fetching. Not needed by OpenLibrary
+            <base_url>http://images.amazon.com/images/P/</base_url>
+            -->
+
+            <!--
             Segregating the details for ContentCafe out for easier use.  At some point, we
             may want to support multiple services at one time.
             -->
@@ -529,6 +526,8 @@
                 <app_settings>
                     <marctemplates>
                         <K_book>LOCALSTATEDIR/templates/marc/k_book.xml</K_book>
+                        <K_audio>LOCALSTATEDIR/templates/marc/k_audio.xml</K_audio>
+                        <K_video>LOCALSTATEDIR/templates/marc/k_video.xml</K_video>
                     </marctemplates>
                 </app_settings>
             </open-ils.booking>
@@ -793,6 +792,12 @@
                     <max_spare_children>5</max_spare_children>
                 </unix_config>
                 <app_settings>
+                    <!-- default_preferred_language: Set the global, default preferred languange -->
+                    <default_preferred_language>eng</default_preferred_language>
+
+                    <!-- default_preferred_language_weight: Set the weight (higher is "better") for the preferred language -->
+                    <default_preferred_language_weight>5</default_preferred_language_weight>
+
                     <script_path>LIBDIR/javascript/</script_path>
                     <script_path>LOCALSTATEDIR/catalog/</script_path>
                     <scripts>

Modified: branches/serials-integration/Open-ILS/src/Makefile.am
===================================================================
--- branches/serials-integration/Open-ILS/src/Makefile.am	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/src/Makefile.am	2010-10-18 13:46:56 UTC (rev 18371)
@@ -153,7 +153,7 @@
 
 # Install everything that did not get installed by autotools
 
-install-data-hook: $(OILSCORE_INST) $(OILSWEB_INST) $(OILSREP_INST)
+install-data-hook: $(OILSCORE_INST) $(OILSWEB_INST) $(OILSUPDATES_INST) $(OILSREP_INST)
 
 uninstall-hook:
 	rm -R $(perldir)

Modified: branches/serials-integration/Open-ILS/src/edi_translator/README
===================================================================
--- branches/serials-integration/Open-ILS/src/edi_translator/README	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/src/edi_translator/README	2010-10-18 13:46:56 UTC (rev 18371)
@@ -26,7 +26,7 @@
 There is no such thing (yet?) as "push" from a vendor of their EDI responses.  Basically
 they just put responses in an FTP directory somewhere that you are expected to check.  It
 would be cool if there were a better way to do that like consuming some RSS feed or 
-remote API callbacks.  
+remote API callbacks.  Similarly, nobody seems willing to utilize interactive EDI.  
 
 Evergreen will only support one delivery address per PO.  That limitation is based
 on the mapping to the delivery address via the ordering_agency org_unit.  If items
@@ -36,10 +36,5 @@
 on SAN, add a new one on SAN + profile_code.  Profile code then goes in the template.
 The template logic could get rather complex to support all the optional data elements.
 
-mbklein says:
-'order' mapper won't work for EDIFACT versions later than D.96A, because of a change
-to the structure of the BGM segment.  But as long as all the supported vendors will
-accept a D.96A ORDERS (which I think they do), that's not a problem.
-
 SEE ALSO:
     http://github.com/mbklein/openils-mapper

Copied: branches/serials-integration/Open-ILS/src/edi_translator/data/BakerAndTaylor (from rev 17886, trunk/Open-ILS/src/edi_translator/data/BakerAndTaylor)

Copied: branches/serials-integration/Open-ILS/src/edi_translator/data/bergware (from rev 17886, trunk/Open-ILS/src/edi_translator/data/bergware)

Copied: branches/serials-integration/Open-ILS/src/edi_translator/data/brodart (from rev 17886, trunk/Open-ILS/src/edi_translator/data/brodart)

Copied: branches/serials-integration/Open-ILS/src/edi_translator/data/edidev.net (from rev 17886, trunk/Open-ILS/src/edi_translator/data/edidev.net)

Copied: branches/serials-integration/Open-ILS/src/edi_translator/data/ingram (from rev 17886, trunk/Open-ILS/src/edi_translator/data/ingram)

Copied: branches/serials-integration/Open-ILS/src/edi_translator/data/misc (from rev 17886, trunk/Open-ILS/src/edi_translator/data/misc)

Copied: branches/serials-integration/Open-ILS/src/edi_translator/data/sources.txt (from rev 17886, trunk/Open-ILS/src/edi_translator/data/sources.txt)
===================================================================
--- branches/serials-integration/Open-ILS/src/edi_translator/data/sources.txt	                        (rev 0)
+++ branches/serials-integration/Open-ILS/src/edi_translator/data/sources.txt	2010-10-18 13:46:56 UTC (rev 18371)
@@ -0,0 +1,8 @@
+
+
+http://www.bergware.net/bisacwww/orddatas.htm
+http://www.edidev.net/edidev-ca/samples/vbNetEdifactTran/WebFrmTran.aspx
+
+# interesting one-off... binary data element
+http://stackoverflow.com/questions/807871/does-anyone-have-a-sample-file-in-x12-or-edifact-that-contains-binary-data
+

Copied: branches/serials-integration/Open-ILS/src/edi_translator/data/stylus (from rev 17886, trunk/Open-ILS/src/edi_translator/data/stylus)

Copied: branches/serials-integration/Open-ILS/src/edi_translator/data/test_output (from rev 17886, trunk/Open-ILS/src/edi_translator/data/test_output)

Modified: branches/serials-integration/Open-ILS/src/edi_translator/test_client.pl
===================================================================
--- branches/serials-integration/Open-ILS/src/edi_translator/test_client.pl	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/src/edi_translator/test_client.pl	2010-10-18 13:46:56 UTC (rev 18371)
@@ -6,9 +6,11 @@
 
 use Getopt::Long;
 use RPC::XML::Client;
+use JSON::XS;
 use Data::Dumper;
 
 # DEFAULTS
+$Data::Dumper::Indent = 1;
 my $host = 'http://localhost';
 my $verbose = 0;
 
@@ -23,7 +25,7 @@
 $host .= '/EDI';
 
 sub get_in {
-    print "Getting " . (shift) . " from input\n";
+    print STDERR "Getting " . (shift) . " from input\n";
     my $json = join("", <STDIN>);
     $json or return;
     print $json, "\n";
@@ -39,49 +41,86 @@
     return substr($string,0,$head) . " ...\n... " . substr($string, -1*$tail);
 }
 
+sub JSONObject2Perl {
+    my $obj = shift;
+    if ( ref $obj eq 'HASH' ) { # is a hash w/o class marker; simply revivify innards
+        for my $k (keys %$obj) {
+            $obj->{$k} = JSONObject2Perl($obj->{$k}) unless ref $obj->{$k} eq 'JSON::XS::Boolean';
+        }
+    } elsif ( ref $obj eq 'ARRAY' ) {
+        for my $i (0..scalar(@$obj) - 1) {
+            $obj->[$i] = JSONObject2Perl($obj->[$i]) unless ref $obj->[$i] eq 'JSON::XS::Boolean';
+        }
+    }
+    # ELSE: return vivified non-class hashes, all arrays, and anything that isn't a hash or array ref
+    return $obj;
+}
+
 # MAIN
 print "Trying host: $host\n";
 
+my $parser;
+
 my $client = new RPC::XML::Client($host);
 $client->request->header('Content-Type' => 'text/xml;charset=utf-8');
-print "User-agent: ", Dumper($client->useragent);
-print "Request: ", Dumper($client->request);
-print "Headers: \n";
-foreach ($client->request->header_field_names) {
-    print "\t$_ =>", $client->request->header($_), "\n";
+
+if ($verbose) {
+    print "User-agent: ", Dumper($client->useragent);
+    print "Request: ", Dumper($client->request);
+    print "Headers: \n";
+    foreach ($client->request->header_field_names) {
+        print "\t$_ =>", $client->request->header($_), "\n";
+    }
 }
 
 my @commands = @ARGV ? @ARGV : 'system.listMethods';
-if ($commands[0] eq 'json2edi' or $commands[0] eq 'edi2json') {
+my $command  = lc $commands[0];
+if ($command eq 'json2edi' or $command eq 'edi2json' or $command eq 'edi2perl') {
     shift;
-    @commands > 1 and print "Ignoring commands after $commands[0]\n";
+    @commands > 1 and print STDERR "Ignoring commands after $command\n";
     my $string;
-    my $type = $commands[0] eq 'json2edi' ? 'JSON' : 'EDI';
+    my $type = $command eq 'json2edi' ? 'JSON' : 'EDI';
     while ($string = get_in($type)) {  # assignment
-        if ($commands[0] ne 'json2edi') {
-            $string =~ s/ORDRSP:0(:...:UN::)/ORDRSP:D$1/ and print "Corrected broken data 'ORDRSP:0' ==> 'ORDRSP:D'\n";
+        my $resp;
+        if ($command eq 'json2edi') {
+            $resp = $client->send_request('json2edi', $string);
+            print "# $command Response: \n", Dumper($resp);
+        } else {
+            $string =~ s/ORDRSP:0(:...:UN::)/ORDRSP:D$1/ and print STDERR "Corrected broken data 'ORDRSP:0' ==> 'ORDRSP:D'\n";
+            $resp = $client->send_request('edi2json', $string);
         }
-        my $resp = $commands[0] eq 'json2edi' ?
-                   $client->send_request('json2edi', $string) :
-                   $client->send_request('edi2json', $string) ;
-        print "Response: ", Dumper($resp);
-        $resp or next;
+        unless ($resp) {
+            warn "Response does not have a payload value!";
+            next;
+        }
         if ($resp->is_fault) {
             print "\n\nERROR code ", $resp->code, " received:\n", nice_string($resp->string) . "\n...\n";
             next;
         }
+        if ($command ne 'json2edi') {   # like the else of the first conditional
+            $parser ||= JSON::XS->new()->pretty(1)->ascii(1)->allow_nonref(1)->space_before(0);    # get it once
+            $verbose and print Dumper($resp);
+            my $parsed = $parser->decode($resp->value) or warn "Failed to decode response payload value";
+            my $perl   = JSONObject2Perl($parsed)      or warn "Failed to decode and create perl object from JSON";
+            if ($perl) {
+                print STDERR "\n########## We were able to decode and perl-ify the JSON\n";
+            } else {
+                print STDERR "\n########## ERROR: Failed to decode and perl-ify the JSON\n";
+            }
+            print "# $command Response: \n", $command eq 'edi2perl' ? Dumper($perl) : $parser->encode($parsed);
+        }
     }
     exit;
 } 
 
-print "Sending request: \n    ", join("\n    ", @commands), "\n\n";
+print STDERR "Sending request: \n    ", join("\n    ", @commands), "\n\n";
 my $resp = $client->send_request(@commands);
 
 print Dumper($resp);
 exit;
 
 if (ref $resp) {
-    print "Return is " . ref($resp), "\n";
+    print STDERR "Return is " . ref($resp), "\n";
     # print "Code: ", ($resp->{code}->as_string || 'UNKNOWN'), "\n";
     foreach (@$resp) {
         print Dumper ($_), "\n";
@@ -95,10 +134,11 @@
         print "\n";
     }
 } else {
-    print "ERROR: unrecognized response:\n\n", Dumper($resp), "\n";
+    print STDERR "ERROR: unrecognized response:\n\n", Dumper($resp), "\n";
 }
 $verbose and print Dumper($resp);
 $verbose and print "\nKEYS (level 1):\n",
     map {sprintf "%12s: %s\n", $_, scalar $resp->{$_}->value} sort keys %$resp;
 
 # print "spooled_filename: ", $resp->{spooled_filename}->value, "\n";
+

Modified: branches/serials-integration/Open-ILS/src/extras/Makefile.install
===================================================================
--- branches/serials-integration/Open-ILS/src/extras/Makefile.install	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/src/extras/Makefile.install	2010-10-18 13:46:56 UTC (rev 18371)
@@ -35,8 +35,8 @@
 
 LIBJS=js-1.7.0
 LIBJS_PERL=JavaScript-SpiderMonkey-0.20
-LIBJS_URL=ftp://ftp.mozilla.org/pub/mozilla.org/js/$(LIBJS).tar.gz
-LIBJS_PERL_URL=ftp://mirror.datapipe.net/pub/CPAN/authors/id/T/TB/TBUSCH/$(LIBJS_PERL).tar.gz
+LIBJS_URL=http://ftp.mozilla.org/pub/mozilla.org/js/$(LIBJS).tar.gz
+LIBJS_PERL_URL=http://mirror.datapipe.net/pub/CPAN/authors/id/T/TB/TBUSCH/$(LIBJS_PERL).tar.gz
 # used for installing libjs lib and header files
 JS_INSTALL_PREFIX=/usr/
 
@@ -91,6 +91,7 @@
 	libnet-server-perl\
 	libnspr4-dev\
 	libole-storage-lite-perl\
+	libparent-perl \
 	libpq-dev\
 	libreadline5-dev\
 	libspreadsheet-writeexcel-perl\
@@ -141,7 +142,6 @@
 	perl-Text-CSV
 
 CENTOS_PERL = \
-	Class::DBI::Frozen::301 \
 	Encode \
 	DBIx::ContextualFetch \
 	Getopt::Long \
@@ -163,6 +163,7 @@
 	mod_ssl \
 	ncurses-devel \
 	ncurses-libs \
+	perl-parent \
 	perl-Business-CreditCard \
 	perl-Business-ISBN \
 	perl-Business-ISBN-Data \
@@ -186,7 +187,6 @@
 FEDORA_13_CPAN = \
 	Business::OnlinePayment \
 	Business::OnlinePayment::AuthorizeNet \
-	Class::DBI::Frozen::301 \
 	MARC::Record
 
 PGSQL_84_RPMS = \
@@ -224,6 +224,7 @@
 # Chronically unpackaged CPAN modules
 CPAN_MODULES = \
     Business::EDI \
+    Library::CallNumber::LC \
     Net::uFTP \
     Net::Z3950::Simple2ZOOM \
     SRU
@@ -246,30 +247,34 @@
     MARC::File::XML \
     Net::Z3950::ZOOM
 
+CPAN_MODULES_FORCE = \
+	Class::DBI::Frozen::301
+
 # ----------------------------------------------------------------------------
 
 all: 
 	@echo "please specify an OS" && exit 0
 
 # these should be the same for any distro
-install: install_cpan install_js_sm install_libdbi install_library_callnumber_lc
+install: install_cpan install_js_sm install_libdbi install_cpan_force
 
-centos: install_centos_pgsql install_centos_rpms install_yaz install_cpan_marc install install_centos_perl create_ld_local install_cpan_safe
-rhel: install_redhat_pgsql install_centos_rpms install_yaz install_cpan_marc install install_centos_perl create_ld_local install_cpan_safe
+centos: install_centos_pgsql centos_like
+rhel: install_redhat_pgsql centos_like
+centos_like: install_centos_rpms install_yaz install_cpan_marc install install_centos_perl create_ld_local install_cpan_safe install_cpan_force
 
-fedora-13: install_fedora_13_rpms install_cpan install_cpan_fedora install_cpan_marc install_spidermonkey install_library_callnumber_lc
+fedora-13: install_fedora_13_rpms install_cpan install_cpan_fedora install_cpan_marc install_spidermonkey install_cpan_force
 
 debian-lenny: lenny generic_debian install_cpan_more install_cpan_safe
 debian-squeeze: squeeze generic_debian
 lenny: install_pgsql_client_debs_83 install_extra_debs
 squeeze: install_pgsql_client_debs_84  install_extra_debs_squeeze
-generic_debian:  install_debs install debian_sys_config
+generic_debian:  install_debs install debian_sys_config install_cpan_force
 
 ubuntu-hardy: hardy generic_ubuntu
 ubuntu-lucid: lucid generic_ubuntu
 hardy: install_pgsql_client_debs_82 install_yaz install_cpan_marc install_extra_encode
 lucid: install_pgsql_client_debs_84 install_extra_debs
-generic_ubuntu: install_debs install debian_sys_config install_cpan_more install_cpan_safe
+generic_ubuntu: install_debs install debian_sys_config install_cpan_more install_cpan_safe install_cpan_force
 
 # - COMMON TARGETS ---------------------------------------------------------
 
@@ -284,6 +289,11 @@
 install_cpan_marc: 
 	for m in $(CPAN_MODULES_MARC); do perl -MCPAN -e "install \"$$m\";"; done
 
+install_cpan_force:
+	for m in $(CPAN_MODULES_FORCE); do \
+		echo "force install $$m" | perl -MCPAN -e shell ;\
+	done
+
 # Install the Safe Perl module
 # Is this really unpackaged everywhere except for Fedora?
 install_cpan_safe: 
@@ -332,10 +342,6 @@
 	cd $(LIBDBI_DRIVERS) && ./configure  \
 		--disable-docs --with-pgsql --enable-libdbi && make all install  
 
-install_library_callnumber_lc:
-	if [ ! -d Library-CallNumber-LC ]; then svn checkout http://library-callnumber-lc.googlecode.com/svn/trunk/perl/Library-CallNumber-LC; fi;
-	cd Library-CallNumber-LC && perl Makefile.PL && make install
-
 clean:
 	make -C $(LIBDBI) clean
 	make -C $(LIBDBI_DRIVERS) clean

Modified: branches/serials-integration/Open-ILS/src/extras/ils_events.xml
===================================================================
--- branches/serials-integration/Open-ILS/src/extras/ils_events.xml	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/src/extras/ils_events.xml	2010-10-18 13:46:56 UTC (rev 18371)
@@ -952,7 +952,7 @@
 		<desc xml:lang="en-US">The lineitem has no price</desc>
 	</event>
 	<event code='10005' textcode='ACQ_LINEITEM_NO_PROVIDER'>
-		<desc xml:lang="en-US">The lineitem has no price</desc>
+		<desc xml:lang="en-US">The lineitem has no provider</desc>
 	</event>
 
 	<event code='10101' textcode='ACQ_ALREADY_CANCELED'>
@@ -972,6 +972,14 @@
         <desc xml:lang="en-US">The caption/pattern still has dependent issuances</desc>
     </event>
 
+    <event code='11101' textcode='SERIAL_DISTRIBUTION_HAS_NO_COPY_TEMPLATE'>
+        <desc xml:lang="en-US">Units cannot be created for the given item because its associated distribution does not have a copy template.</desc>
+    </event>
+
+    <event code='11102' textcode='SERIAL_DISTRIBUTION_HAS_NO_CALL_NUMBER'>
+        <desc xml:lang="en-US">Units cannot be created for the given item because its associated distribution does not have a call number.</desc>
+    </event>
+
 	<!-- ================================================================ -->
 
 </ils_events>

Modified: branches/serials-integration/Open-ILS/src/extras/import/marc2are.pl
===================================================================
--- branches/serials-integration/Open-ILS/src/extras/import/marc2are.pl	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/src/extras/import/marc2are.pl	2010-10-18 13:46:56 UTC (rev 18371)
@@ -61,9 +61,6 @@
 while ( try { $rec = $batch->next } otherwise { $rec = -1 } ) {
 	next if ($rec == -1);
 	my $id = $count;
-	my $_001 = $rec->field('001');
-	my $arn = $count;
-	$arn = $_001->data if ($_001);
 
 	(my $xml = $rec->as_xml_record()) =~ s/\n//sog;
 	$xml =~ s/^<\?xml.+\?\s*>//go;
@@ -81,8 +78,6 @@
 	$bib->create_date('now');
 	$bib->editor($user);
 	$bib->edit_date('now');
-	$bib->arn_source('LEGACY');
-	$bib->arn_value($arn);
 	$bib->last_xact_id('IMPORT-'.$starttime);
 
 	print OpenSRF::Utils::JSON->perl2JSON($bib)."\n";

Modified: branches/serials-integration/Open-ILS/src/extras/import/marc_add_ids
===================================================================
--- branches/serials-integration/Open-ILS/src/extras/import/marc_add_ids	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/src/extras/import/marc_add_ids	2010-10-18 13:46:56 UTC (rev 18371)
@@ -101,6 +101,7 @@
 
 	} otherwise {
 		warn "failed on record $., $partlist{marc}, for $@\n" if (!$quiet);
+		import MARC::File::XML; # reset SAX parser
 	};
 }
 

Modified: branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Acq/EDI.pm
===================================================================
--- branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Acq/EDI.pm	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Acq/EDI.pm	2010-10-18 13:46:56 UTC (rev 18371)
@@ -17,7 +17,6 @@
 use OpenILS::Application::Acq::EDI::Translator;
 
 use Business::EDI;
-use Business::EDI::Segment::BGM;
 
 use Data::Dumper;
 our $verbose = 0;
@@ -29,6 +28,8 @@
     return $self;
 }
 
+# our $reasons = {};   # cache for acq.cancel_reason rows ?
+
 our $translator;
 
 sub translator {
@@ -79,7 +80,7 @@
 );
 
 sub retrieve_core {
-    my ($self, $e, $set, $max) = @_;    # $e is a working editor
+    my ($self, $set, $max, $e, $test) = @_;    # $e is a working editor
 
     $e   ||= new_editor();
     $set ||= __PACKAGE__->retrieve_vendors($e);
@@ -91,31 +92,59 @@
         my $server;
         $logger->info("EDI check for vendor " . ++$vcount . " of " . scalar(@$set) . ": " . $account->host);
         unless ($server = __PACKAGE__->remote_account($account)) {   # assignment, not comparison
-            $logger->err(sprintf "Failed remote account connection for %s (%s)", $account->host, $account->id);
+            $logger->err(sprintf "Failed remote account mapping for %s (%s)", $account->host, $account->id);
             next;
         };
-        my @files    = $server->ls({remote_file => ($account->in_dir || '.')});
-        my @ok_files = grep {$_ !~ /\/\.?\.$/ } @files;
-        $logger->info(sprintf "%s of %s files at %s/%s", scalar(@ok_files), scalar(@files), $account->host, ($account->in_dir || ''));   
-        foreach (@ok_files) {
+#       my $rf_starter = './';  # default to current dir
+        if ($account->in_dir) { 
+            if ($account->in_dir =~ /\*+.*\//) {
+                $logger->err("EDI in_dir has a slash after an asterisk in value: '" . $account->in_dir . "'.  Skipping account with indeterminate target dir!");
+                next;
+            }
+#           $rf_starter = $account->in_dir;
+#           $rf_starter =~ s/((\/)?[^\/]*)\*+[^\/]*$//;  # kill up to the first (possible) slash before the asterisk: keep the preceeding static dir
+#           $rf_starter .= '/' if $rf_starter or $2;   # recap the dir, or replace leading "/" if there was one (but don't add if empty)
+        }
+        my @files    = ($server->ls({remote_file => ($account->in_dir || './')}));
+        my @ok_files = grep {$_ !~ /\/\.?\.$/ and $_ ne '0'} @files;
+        $logger->info(sprintf "%s of %s files at %s/%s", scalar(@ok_files), scalar(@files), $account->host, $account->in_dir);   
+        # $server->remote_path(undef);
+        foreach my $remote_file (@ok_files) {
+            # my $remote_file = $rf_starter . $_;
+            my $description = sprintf "%s/%s", $account->host, $remote_file;
+            
+            # deduplicate vs. acct/filenames already in DB
+            my $hits = $e->search_acq_edi_message([
+                {
+                    account     => $account->id,
+                    remote_file => $remote_file,
+                    status      => {'in' => [qw/ processed /]},     # if it never got processed, go ahead and get the new one (try again)
+                    # create_time => 'NOW() - 60 DAYS',     # if we wanted to allow filenames to be reused after a certain time
+                    # ideally we would also use the date from FTP, but that info isn't available via RemoteAccount
+                }
+                # { flesh => 1, flesh_fields => {...}, }
+            ]);
+            if (scalar(@$hits)) {
+                $logger->debug("EDI: $remote_file already retrieved.  Skipping");
+                warn "EDI: $remote_file already retrieved.  Skipping";
+                next;
+            }
+
             ++$count;
             $max and $count > $max and last;
+            $logger->info(sprintf "%s of %s targets: %s", $count, scalar(@ok_files), $description);
+            print sprintf "%s of %s targets: %s\n", $count, scalar(@ok_files), $description;
+            if ($test) {
+                push @return, "test_$count";
+                next;
+            }
             my $content;
             my $io = IO::Scalar->new(\$content);
-            unless ($server->get({remote_file => $_, local_file => $io})) {
-                $logger->error("(S)FTP get($_) failed");
+            unless ( $server->get({remote_file => $remote_file, local_file => $io}) ) {
+                $logger->error("(S)FTP get($description) failed");
                 next;
             }
-            my $incoming = Fieldmapper::acq::edi_message->new;
-            $incoming->remote_file($_);
-            $incoming->edi($content);
-            $incoming->account($account->id);
-             __PACKAGE__->attempt_translation($incoming);
-            $e->xact_begin;
-            $e->create_acq_edi_message($incoming);
-            $e->xact_commit;
-            __PACKAGE__->record_activity($account, $e);
-            __PACKAGE__->process_jedi($incoming, $server, $e);
+            my $incoming = __PACKAGE__->process_retrieval($content, $remote_file, $server, $account->id, $e);
 #           $server->delete(remote_file => $_);   # delete remote copies of saved message
             push @return, $incoming->id;
         }
@@ -123,6 +152,40 @@
     return \@return;
 }
 
+# my $in = OpenILS::Application::Acq::EDI->process_retrieval($file_content, $remote_filename, $server, $account_id, $editor);
+
+sub process_retrieval {
+    my $incoming = Fieldmapper::acq::edi_message->new;
+    my ($class, $content, $remote, $server, $account_or_id, $e) = @_;
+    $content or return;
+    $e ||= new_editor;
+
+    my $account = __PACKAGE__->record_activity( $account_or_id, $e );
+
+    my $z;  # must predeclare
+    $z = ( $content =~ s/('UNH\+\d+\+ORDRSP:)0(:96A:UN')/$1D$2/g )
+        and $logger->warn("Patching bogus spec reference ORDRSP:0:96A:UN => ORDRSP:D:96A:UN ($z times)");  # Hack/fix some faulty "0" in (B&T) data
+
+    $incoming->remote_file($remote);
+    $incoming->account($account->id);
+    $incoming->edi($content);
+    $incoming->message_type(($content =~ /'UNH\+\d+\+(\S{6}):/) ? $1 : 'ORDRSP');   # cheap sniffing, ORDRSP fallback
+    __PACKAGE__->attempt_translation($incoming);
+    $e->xact_begin;
+    $e->create_acq_edi_message($incoming);
+    $e->xact_commit;
+    # refresh: send process_jedi the updated row
+    my $res = __PACKAGE__->process_jedi($e->retrieve_acq_edi_message($incoming->id), $server, $account, $e);
+    my $outgoing = $e->retrieve_acq_edi_message($incoming->id);  # refresh again!
+    $outgoing->status($res ? 'processed' : 'proc_error');
+    if ($res) {
+        $e->xact_begin;
+        $e->update_acq_edi_message($outgoing);
+        $e->xact_commit;
+    }
+    return $outgoing;
+}
+
 # ->send_core
 # $account     is a Fieldmapper object for acq.edi_account row
 # $messageset  is an arrayref with acq.edi_message.id values
@@ -217,7 +280,7 @@
     $e ||= new_editor();
 
     my $criteria = {'+acqpro' => {active => 't'}};
-    # $criteria->{vendor_id} = $vendor_id if $vendor_id;
+    $criteria->{'+acqpro'}->{id} = $vendor_id if $vendor_id;
     return $e->search_acq_edi_account([
         $criteria, {
             'join' => 'acqpro',
@@ -267,7 +330,7 @@
     ($host =~ s/^(S?FTP)://i    and $args{type} = uc($1)) or
     ($host =~ s/^(SSH|SCP)://i  and $args{type} = 'SCP' ) ;
      $host =~ s/:(\d+)$//       and $args{port} = $1;
-     ($args{remote_host} = $host) =~ s#/+##;
+    ($args{remote_host} = $host) =~ s#/+##;
     $verbose and $logger->warn("field_map: " . Dumper(\%args));
     return %args;
 }
@@ -291,10 +354,13 @@
     );
 }
 
+# takes account ID or account Fieldmapper object
+
 sub record_activity {
-    my ($class, $account, $e) = @_;
-    $account or return;
+    my ($class, $account_or_id, $e) = @_;
+    $account_or_id or return;
     $e ||= new_editor();
+    my $account = ref($account_or_id) ? $account_or_id : $e->retrieve_acq_edi_account($account_or_id);
     $logger->info("EDI record_activity calling update_acq_edi_account");
     $account->last_activity('NOW') or return;
     $e->xact_begin;
@@ -329,34 +395,43 @@
     return $msg;
 }
 
-# ->process_jedi($message, $server, $e)
+our @datecodes = (35, 359, 17, 191, 69, 76, 75, 79, 85, 74, 84, 223);
+our @noop_6063 = (21);
+
+# ->process_jedi($message, $server, $remote, $e)
+# $message is an edi_message object
+#
 sub process_jedi {
-    my $class    = shift;
-    my $message  = shift or return;
-    my $server   = shift || {};  # context
-    my $jedi     = ref($message) ? $message->jedi : $message;  # If we got an object, it's an edi_message.  A string is the jedi content itself.
-    unless ($jedi) {
-        $logger->warn("EDI process_jedi missing required argument (edi_message object with jedi or jedi scalar)!");
+    my ($class, $message, $server, $remote, $e) = @_;
+    $message or return;
+    $server ||= {};  # context
+    $remote ||= {};  # context
+    $e ||= new_editor;
+    my $jedi;
+    unless (ref($message) and $jedi = $message->jedi) {     # assignment, not comparison
+        $logger->warn("EDI process_jedi missing required argument (edi_message object with jedi)!");
         return;
     }
-    my $e = @_ ? shift : new_editor();
-    my $perl = __PACKAGE__->jedi2perl($jedi);
+    my $perl  = __PACKAGE__->jedi2perl($jedi);
+    my $error = '';
     if (ref($message) and not $perl) {
-        $message->error(($message->error || '') . " JSON2perl (jedi2perl) FAILED to convert jedi");
+        $error = ($message->error || '') . " JSON2perl (jedi2perl) FAILED to convert jedi";
+    }
+    elsif (! $perl->{body}) {
+        $error = "EDI interchange body not found!";
+    } 
+    elsif (! $perl->{body}->[0]) {
+        $error = "EDI interchange body not a populated arrayref!";
+    }
+    if ($error) {
+        $logger->warn($error);
+        $message->error($error);
         $message->error_time('NOW');
         $e->xact_begin;
-        $e->udpate_acq_edi_message($message) or $logger->warn("EDI update_acq_edi_message failed! $!");
+        $e->update_acq_edi_message($message) or $logger->warn("EDI update_acq_edi_message failed! $!");
         $e->xact_commit;
         return;
     }
-    if (! $perl->{body}) {
-        $logger->warn("EDI interchange body not found!");
-        return;
-    } 
-    if (! $perl->{body}->[0]) {
-        $logger->warn("EDI interchange body not a populated arrayref!");
-        return;
-    }
 
 # Crazy data structure.  Most of the arrays will be 1 element... we think.
 # JEDI looks like:
@@ -365,8 +440,9 @@
 # So you might access it like:
 #   $obj->{body}->[0]->{ORDERS}->[0]->[0] eq 'UNH'
 
-    $logger->info("EDI interchange body has " . scalar(@{$perl->{body}}) . " messages(s)");
-    my @li;
+    $logger->info("EDI interchange body has " . scalar(@{$perl->{body}}) . " message(s)");
+    my @ok_msg_codes = qw/ORDRSP OSTRPT/;
+    my @messages;
     my $i = 0;
     foreach my $part (@{$perl->{body}}) {
         $i++;
@@ -375,96 +451,169 @@
             next;
         }
         foreach my $key (keys %$part) {
-            unless ($key eq 'ORDRSP') {     # We only do one type for now.  TODO: other types here
-                $logger->warn("EDI interchange message $i contains unhandled type '$key'.  Ignoring.");
+            if (! grep {$_ eq $key} @ok_msg_codes) {     # We only do one type for now.  TODO: other types here
+                $logger->warn("EDI interchange $i contains unhandled '$key' message.  Ignoring it.");
                 next;
             }
-            my @li_chunk = __PACKAGE__->parse_ordrsp($part->{$key}, $server, $e);
-            $logger->info("EDI $key parsing returned " . scalar(@li_chunk) . " line items");
-            push @li, @li_chunk;
-        }
-    }
-    return \@li, $perl;   # TODO process perl
-}
+            my $msg = __PACKAGE__->message_object($part->{$key}) or next;
+            push @messages, $msg;
 
+            my $bgm = $msg->xpath('BGM') or $logger->warn("EDI No BGM segment found?!");
+            my $tag4343 = $msg->xpath('BGM/4343');
+            my $tag1225 = $msg->xpath('BGM/1225');
+            if (ref $tag4343) {
+                $logger->info(sprintf "EDI $key BGM/4343 Response Type: %s - %s", $tag4343->value, $tag4343->label)
+            } else {
+                $logger->warn("EDI $key BGM/4343 Response Type Code unrecognized"); # next; #?
+            }
+            if (ref $tag1225) {
+                $logger->info(sprintf "EDI $key BGM/1225 Message Function: %s - %s", $tag1225->value, $tag1225->label);
+            } else {
+                $logger->warn("EDI $key BGM/1225 Message Function Code unrecognized"); # next; #?
+            }
 
-=head2 ->parse_ordrsp($segments, $server, $e)
+            # TODO: currency check, just to be paranoid
+            # *should* be unnecessary (vendor should reply in currency we send in ORDERS)
+            # That begs a policy question: how to handle mismatch?  convert (bad accuracy), reject, or ignore?  I say ignore.
 
-Returns array of lineitems.
+            # ALL those codes below are basically some form of (lastest) delivery date/time
+            # see, e.g.: http://www.stylusstudio.com/edifact/D04B/2005.htm
+            # The order is the order of definitiveness (first match wins)
+            # Note: if/when we do serials via EDI, dates (and ranges/periods) will need massive special handling
+            my @dates;
+            my $ddate;
 
-=cut
-
-# TODO: Build Business::EDI::Message::ORDRSP object instead
-# TODO: Convert access to methods, not reaching inside the data/object like $segbody->{S009}->{'0065'}
-
-sub parse_ordrsp {
-    my ($class, $segments, $server, $e, $test) = @_;    # test not implemented
-    $e ||= new_editor();
-    my $type = 'ORDRSP';
-    $logger->info("EDI " . scalar(@$segments) . " segments in $type message");
-    my (@lins, $bgm);
-    foreach my $segment (@$segments) {  # Prepass: catch the conditions that might cause us to bail
-        my ($tag, $segbody, @extra) = @$segment;
-        unless ($tag    ) {$logger->warn("EDI empty segment received"     ); next;}
-        unless ($segbody) {$logger->warn("EDI segment '$tag' missing body"); next;}
-        @extra and $logger->warn("EDI extra data (" . scalar(@extra) . " elements) found after pseudohash pair for $tag");
-        if ($tag eq 'UNH') {
-            unless ($segbody->{S009}->{'0065'} and $segbody->{S009}->{'0065'} eq $type) {
-                $logger->error("EDI $tag/S009/0065 ('" . ($segbody->{S009}->{'0065'} || '') . "') conflict w/ message type $type\.  Aborting");
-                return;
+            foreach my $date ($msg->xpath('delivery_schedule')) {
+                my $val_2005 = $date->xpath_value('DTM/2005') or next;
+                (grep {$val_2005 eq $_} @datecodes) or next; # no match means some other kind of date we don't care about
+                push @dates, $date;
             }
-            unless ($segbody->{S009}->{'0051'} and $segbody->{S009}->{'0051'} eq 'UN') {
-                $logger->warn("EDI $tag/S009/0051 does not designate 'UN' as controlling agency.  Will attempt to process anyway");
+            if (@dates) {
+                DATECODE: foreach my $dcode (@datecodes) {   # now cycle back through hits in order of dcode definitiveness
+                    foreach my $date (@dates) {
+                        $date->xpath_value('DTM/2005') == $dcode or next;
+                        $ddate = $date->xpath_value('DTM/2380') and last DATECODE;
+                        # TODO: conversion based on format specified in DTM/2379 (best encapsulated in Business::EDI)
+                    }
+                }
             }
-        } elsif ($tag eq 'BGM') {
-            $bgm = Business::EDI::Segment::BGM->new($segbody);
-            $bgm->seg4343 or $logger->warn(sprintf "EDI $tag/4343 Response Type Code '%s' unrecognized", ($segbody->{4343} || ''));
-            $logger->info(sprintf "EDI $tag/4343 response type: %s - %s (%s)", $bgm->seg4343->value, $bgm->seg4343->label, $bgm->seg4343->desc);
-            my $fcn = $bgm->seg1225;
-            unless ($fcn) {
-                $logger->error(sprintf "EDI $tag/1225 Message Function Code '%s' unrecognized.  Aborting", ($segbody->{1225} || ''));
-                return;
-            }
-        }
-    }
-    my @ignored;
-    foreach my $segment (@$segments) {  # The main pass
-        my ($tag, $segbody, @extra) = @$segment;
-        next unless ($tag and $segbody);    # warnings above
-        if ($tag eq 'LIN') {
-            my @chunks = @{$segbody->{SG26}};
-            my $count = scalar(@chunks);
-            $logger->debug("EDI LIN/SG26 has $count chunks");
-# CHUNK:
-# ["RFF", {
-#   "C506": {
-#      "1153": "LI",
-#      "1154": "4639/1"
-#   }
-# }]
-            foreach (@chunks) {
-                my $label = $_->[0];
-                my $body  = $_->[1];
-                # $label eq 'QTY' and push @qtys, $body;
-                $label eq 'RFF' or next;
-                my $obj;
-                unless ($obj = Business::EDI::Segment::RFF->new($body)) {   # assignment, not comparison
-                    $logger->error("EDI $tag/$label failed to convert to an object");
+            foreach my $detail ($msg->part('line_detail')) {
+                my $eg_line = __PACKAGE__->eg_li($detail, $remote, $server->{remote_host}, $e) or next;
+                my $li_date = $detail->xpath_value('DTM/2380') || $ddate;
+                my $price   = $detail->xpath_value('line_price/PRI/5118') || '';
+                $eg_line->expected_recv_time($li_date) if $li_date;
+                $eg_line->estimated_unit_price($price) if $price;
+                if (not $message->purchase_order) {                     # first good lineitem sets the message PO link
+                    $message->purchase_order($eg_line->purchase_order); # EG $message object NOT Business::EDI $msg object
+                    $e->xact_begin;
+                    $e->update_acq_edi_message($message) or $logger->warn("EDI update_acq_edi_message (for PO number) failed! $!");
+                    $e->xact_commit;
                 }
-                $obj->seg1153 and $obj->seg1153->value eq 'LI' or $logger->warn("EDI $tag/$label object unexpected 1153 value (not 'LI')");
-                __PACKAGE__->update_li($obj->seg1154->value, $segbody, $server, $e);
+                # $e->search_acq_edi_account([]);
+                my $touches = 0;
+                my $eg_lids = $e->search_acq_lineitem_detail({lineitem => $eg_line->id}); # should be the same as $eg_line->lineitem_details
+                my $lidcount = scalar(@$eg_lids);
+                $lidcount == $eg_line->item_count or $logger->warn(
+                    sprintf "EDI: LI %s itemcount (%d) mismatch, %d LIDs found", $eg_line->id, $eg_line->item_count, $lidcount
+                );
+                foreach my $qty ($detail->part('all_QTY')) {
+                    my $ubound   = $qty->xpath_value('6060') or next;   # nothing to do if qty is 0
+                    my $val_6063 = $qty->xpath_value('6063');
+                    $ubound > 0 or next; # don't be crazy!
+                    if (! $val_6063) {
+                        $logger->warn("EDI: Response for LI " . $eg_line->id . " specifies quantity $ubound with no 6063 code! Contact vendor to resolve.");
+                        next;
+                    }
+                    
+                    my $eg_reason = $e->retrieve_acq_cancel_reason(1200 + $val_6063);  # DB populated w/ 6063 keys in 1200's
+                    if (! $eg_reason) {
+                        $logger->warn("EDI: Unhandled quantity code '$val_6063' (LI " . $eg_line->id . ") $ubound items unprocessed");
+                        next;
+                    } elsif (grep {$val_6063 == $_} @noop_6063) {      # an FYI like "ordered quantity"
+                        $ubound eq $lidcount
+                            or $logger->warn("EDI: LI " . $eg_line->id . " -- Vendor says we ordered $ubound, but we have $lidcount LIDs!)");
+                        next;
+                    }
+                    # elsif ($val_6063 == 83) { # backorder
+                   #} elsif ($val_6063 == 85) { # cancel
+                   #} elsif ($val_6063 == 12 or $val_6063 == 57 or $val_6063 == 84 or $val_6063 == 118) {
+                            # despatched, in transit, urgent delivery, or quantity manifested
+                   #}
+                    if ($touches >= $lidcount) {
+                        $logger->warn("EDI: LI "  . $eg_line->id . ", We already updated $touches of $lidcount LIDS, " .
+                                      "but message wants QTY $ubound more set to " . $eg_reason->label . ".  Ignoring!");
+                        next;
+                    }
+                    $e->xact_begin;
+                    foreach (1 .. $ubound) {
+                        my $eg_lid = shift @$eg_lids or $logger->warn("EDI: Used up all $lidcount LIDs!  Ignoring extra status " . $eg_reason->label);
+                        $eg_lid or next;
+                        $logger->debug(sprintf "Updating LID %s to %s", $eg_lid->id, $eg_reason->label);
+                        $eg_lid->cancel_reason($eg_reason->id);
+                        $e->update_acq_lineitem_detail($eg_lid);
+                        $touches++;
+                    }
+                    $e->xact_commit;
+                    if ($ubound == $eg_line->item_count) {
+                        $eg_line->cancel_reason($eg_reason->id);    # if ALL the items have the same cancel_reason, the PO gets it too
+                    }
+                }
+                $eg_line->edit_time('NOW'); # TODO: have this field automatically updated via ON UPDATE trigger.  
+                $e->xact_begin;
+                $e->update_acq_lineitem($eg_line) or $logger->warn("EDI: update_acq_lineitem FAILED");
+                $e->xact_commit;
+                # print STDERR "Lineitem update: ", Dumper($eg_line);
             }
-            push @lins, \@chunks;
-        } elsif ($tag ne 'UNH' and $tag ne 'BGM') {
-            push @ignored, $tag;
         }
     }
-    @ignored and $logger->debug("EDI: ignoring " . scalar(@ignored) . " segment(s): " . join(', ', @ignored));
-    return @lins;
+    return \@messages;
 }
 
-=head2 ->update_li($lineitem_id, $lineitem_object, [$server, $editor])
+# returns message object if processing should continue
+# returns false/undef value if processing should abort
 
+sub message_object {
+    my $class = shift;
+    my $body  = shift or return;
+    my $key   = shift if @_;
+    my $keystring = $key || 'UNSPECIFIED';
+
+    my $msg = Business::EDI::Message->new($body);
+    unless ($msg) {
+        $logger->error("EDI interchange message: $keystring body failed Business::EDI constructor. Skipping it.");
+        return;
+    }
+    $key = $msg->code if ! $key;  # Now we set the key for reference if it wasn't specified
+    my $val_0065 = $msg->xpath_value('UNH/S009/0065') || '';
+    unless ($val_0065 eq $key) {
+        $logger->error("EDI $key UNH/S009/0065 ('$val_0065') conflicts w/ message type $key.  Aborting");
+        return;
+    }
+    my $val_0051 = $msg->xpath_value('UNH/S009/0051') || '';
+    unless ($val_0051 eq 'UN') {
+        $logger->warn("EDI $key UNH/S009/0051 designates '$val_0051', not 'UN' as controlling agency.  Attempting to process anyway");
+    }
+    my $val_0054 = $msg->xpath_value('UNH/S009/0054') || '';
+    if ($val_0054) {
+        $logger->info("EDI $key UNH/S009/0054 uses Spec revision version '$val_0054'");
+        # Possible Spec Version limitation
+        # my $yy = $tag_0054 ? substr($val_0054,0,2) : '';
+        # unless ($yy eq '00' or $yy > 94 ...) {
+        #     $logger->warn("EDI $key UNH/S009/0051 Spec revision version '$val_0054' not supported");
+        # }
+    } else {
+        $logger->warn("EDI $key UNH/S009/0054 does not reference a known Spec revision version");
+    }
+    return $msg;
+}
+
+=head2 ->eg_li($lineitem_object, [$remote, $server_log_string, $editor])
+
+my $line_item = OpenILS::Application::Acq::EDI->eg_li($edi_line, $remote, "test_server_01", $e);
+
+ $remote is a acq.edi_account Fieldmapper object.
+ $server_log_string is an arbitrary string use to identify the remote host in potential log messages.
+
 Updates:
  acq.lineitem.estimated_unit_price, 
  acq.lineitem.state (dependent on mapping codes), 
@@ -473,17 +622,49 @@
 
 =cut
 
-sub update_li {
-    my ($class, $id, $object, $server, $e) = @_;
+sub eg_li {
+    my ($class, $line, $server, $server_log_string, $e) = @_;
+    $line or return;
     $e ||= new_editor();
-    $id =~ s#^.*\/##;   # Temporary fix for mbklein's testdata
-    print STDERR "Here we would retrieve/update lineitem $id\n";
-    my $li = OpenILS::Application::Acq::Lineitem::retrieve_lineitem_impl($e, $id); # Could send {options}
+
+    my $id;
+    # my $rff      = $line->part('line_reference/RFF') or $logger->warn("EDI ORDRSP line_detail/RFF missing!");
+    my $val_1153 = $line->xpath_value('line_reference/RFF/1153') || '';
+    my $val_1154 = $line->xpath_value('line_reference/RFF/1154') || '';
+    my $val_1082 = $line->xpath_value('LIN/1082') || '';
+
+    my @po_nums;
+
+    $val_1154 =~ s#^(.*)\/##;   # Many sources send the ID as 'order_ID/LI_ID'
+    $1 and push @po_nums, $1;
+    $val_1082 =~ s#^(.*)\/##;   # Many sources send the ID as 'order_ID/LI_ID'
+    $1 and push @po_nums, $1;
+
+    # TODO: possible check of po_nums
+    # now do a lot of checking
+
+    if ($val_1153 eq 'LI') {
+        $id = $val_1154 or $logger->warn("EDI ORDRSP RFF/1154 reference to LI empty.  Attempting failover to LIN/1082");
+    } else {
+        $logger->warn("EDI ORDRSP RFF/1153 unexpected value ('$val_1153', not 'LI').  Attempting failover to LIN/1082");
+    }
+
+    if ($id and $val_1082 and $val_1082 ne $id) {
+        $logger->warn("EDI ORDRSP LIN/1082 Line Item ID mismatch ($id vs. $val_1082): cannot target update");
+        return;
+    }
+    $id ||= $val_1082 || '';
+    print STDERR "EDI retrieve/update lineitem $id\n";
+
+    my $li = OpenILS::Application::Acq::Lineitem::retrieve_lineitem_impl($e, $id, {
+        flesh_li_details => 1,
+    }, 1); # Could send more {options}.  The 1 is for no_auth.
+
     if (! $li or ref($li) ne 'Fieldmapper::acq::lineitem') {
-        $logger->error("EDI failed to retrieve lineitem by id '$id'");
+        $logger->error("EDI failed to retrieve lineitem by id '$id' for server $server_log_string");
         return;
     }
-    unless ((! $server) or (! $server->provider)) {
+    unless ((! $server) or (! $server->provider)) {     # but here we want $server to be acq.edi_account instead of RemoteAccount
         if ($server->provider != $li->provider) {
             # links go both ways: acq.provider.edi_default and acq.edi_account.provider
             $logger->info("EDI acct provider (" . $server->provider. ") doesn't match lineitem provider("
@@ -496,12 +677,135 @@
             }
         }
     }
-    return; # TODO: actual updates
-    $e->xact_begin;
-    $e->update_acq_lineitem($li) or $logger->warn("EDI: in update_li, update_acq_lineitem FAILED");
-    $e->xact_commit;
-    # print STDERR "Lineitem to update: ", Dumper($li);
+    
+    my @lin_1229 = $line->xpath('LIN/1229') or $logger->warn("EDI LIN/1229 Action Code missing!");
+    my $key = $lin_1229[0] or return;
+
+    my $eg_reason = $e->retrieve_acq_cancel_reason(1000 + $key->value);  # DB populated w/ spec keys in 1000's
+    $eg_reason or $logger->warn(sprintf "EDI LIN/1229 Action Code '%s' (%s) not recognized in acq.cancel_reason", $key->value, $key->label);
+    $eg_reason or return;
+
+    $li->cancel_reason($eg_reason->id);
+    unless ($eg_reason->keep_debits) {
+        $logger->warn("EDI LIN/1229 Action Code '%s' (%s) has keep_debits=0", $key->value, $key->label);
+    }
+
+    my @prices = $line->xpath_value("line_price/PRI/5118");
+    $li->estimated_unit_price($prices[0]) if @prices;
+
+    return $li;
 }
 
+# caching not needed for now (edi_fetcher is asynchronous)
+# sub get_reason {
+#     my ($class, $key, $e) = @_;
+#     $reasons->{$key} and return $reasons->{$key};
+#     $e ||= new_editor();
+#     $reasons->{$key} = $e->retrieve_acq_cancel_reason($key);
+#     return $reasons->{$key};
+# }
+
 1;
 
+__END__
+
+Example JSON data.
+
+Note the pseudo-hash 2-element arrays.  
+
+[
+  'SG26',
+  [
+    [
+      'LIN',
+      {
+        '1229' => '5',
+        '1082' => 1,
+        'C212' => {
+          '7140' => '9780446360272',
+          '7143' => 'EN'
+        }
+      }
+    ],
+    [
+      'IMD',
+      {
+        '7081' => 'BST',
+        '7077' => 'F',
+        'C273' => {
+          '7008' => [
+            'NOT APPLIC WEBSTERS NEW WORLD THESA'
+          ]
+        }
+      }
+    ],
+    [
+      'QTY',
+      {
+        'C186' => {
+          '6063' => '21',
+          '6060' => 10
+        }
+      }
+    ],
+    [
+      'QTY',
+      {
+        'C186' => {
+          '6063' => '12',
+          '6060' => 10
+        }
+      }
+    ],
+    [
+      'QTY',
+      {
+        'C186' => {
+          '6063' => '85',
+          '6060' => 0
+        }
+      }
+    ],
+    [
+      'FTX',
+      {
+        '4451' => 'LIN',
+        'C107' => {
+          '4441' => '01',
+          '3055' => '28',
+          '1131' => '8B'
+        }
+      }
+    ],
+    [
+      'SG30',
+      [
+        [
+          'PRI',
+          {
+            'C509' => {
+              '5118' => '4.5',
+              '5387' => 'SRP',
+              '5125' => 'AAB'
+            }
+          }
+        ]
+      ]
+    ],
+    [
+      'SG31',
+      [
+        [
+          'RFF',
+          {
+            'C506' => {
+              '1154' => '8/1',
+              '1153' => 'LI'
+            }
+          }
+        ]
+      ]
+    ]
+  ]
+],
+

Modified: branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Acq/Invoice.pm
===================================================================
--- branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Acq/Invoice.pm	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Acq/Invoice.pm	2010-10-18 13:46:56 UTC (rev 18371)
@@ -163,11 +163,11 @@
     my $lineitem = $e->retrieve_acq_lineitem($entry->lineitem) or return $e->die_event;
 
     for my $debit (@$debits) {
-
         # revert to the original estimated amount re-encumber
         $debit->encumbrance('t');
         $debit->amount($lineitem->estimated_unit_price());
         $e->update_acq_fund_debit($debit) or return $e->die_event;
+        update_copy_cost($e, $debit) or return $e->die_event; # clear the cost
     }
 
     return undef;
@@ -188,15 +188,44 @@
     }
 
     for my $debit (@$debits) {
-        $debit->amount(entry_amount_per_item($entry));
+        my $amount = entry_amount_per_item($entry);
+        $debit->amount($amount);
         $debit->encumbrance('f');
         $e->update_acq_fund_debit($debit) or return $e->die_event;
+
+        # TODO: this does not reflect ancillary charges, like taxes, etc.
+        # We may need a way to indicate whether the amount attached to an 
+        # invoice_item should be prorated and included in the copy cost.
+        # Note that acq.invoice_item_type.prorate does not necessarily 
+        # mean a charge should be included in the copy price, only that 
+        # it should spread accross funds.
+        update_copy_cost($e, $debit, $amount) or return $e->die_event;
     }
 
     return undef;
 }
 
+# update the linked copy to reflect the amount paid for the item
+# returns true on success, false on error
+sub update_copy_cost {
+    my ($e, $debit, $amount) = @_;
 
+    my $lid = $e->search_acq_lineitem_detail([
+        {fund_debit => $debit->id},
+        {flesh => 1, flesh_fields => {acqlid => ['eg_copy_id']}}
+    ])->[0];
+
+    if($lid and my $copy = $lid->eg_copy_id) {
+        defined $amount and $copy->cost($amount) or $copy->clear_cost;
+        $copy->editor($e->requestor->id);
+        $copy->edit_date('now');
+        $e->update_asset_copy($copy) or return 0;
+    }
+
+    return 1;
+}
+
+
 sub entry_amount_per_item {
     my $entry = shift;
     return $entry->amount_paid if $U->is_true($entry->billed_per_item);

Modified: branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Acq/Lineitem.pm
===================================================================
--- branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Acq/Lineitem.pm	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Acq/Lineitem.pm	2010-10-18 13:46:56 UTC (rev 18371)
@@ -54,6 +54,8 @@
             or return $e->die_event;
         return $e->die_event unless 
             $e->allowed('MANAGE_PROVIDER', $po->ordering_agency, $po);
+
+        $li->provider($po->provider) unless defined $li->provider;
     }
 
     $li->selector($e->requestor->id);
@@ -92,7 +94,7 @@
 }
 
 sub retrieve_lineitem_impl {
-    my ($e, $li_id, $options) = @_;
+    my ($e, $li_id, $options, $no_auth) = @_;   # no_auth needed for EDI scripts
     $options ||= {};
 
     my $flesh = {
@@ -106,16 +108,16 @@
 
     my $fields = $flesh->{flesh_fields};
 
-    push(@{$fields->{jub}}, 'attributes') if $$options{flesh_attrs};
-    push(@{$fields->{jub}}, 'lineitem_notes') if $$options{flesh_notes};
-    push(@{$fields->{acqlin}}, 'alert_text') if $$options{flesh_notes};
-    push(@{$fields->{jub}}, 'order_summary') if $$options{flesh_order_summary};
+    push(@{$fields->{jub}   },    'attributes') if $$options{flesh_attrs};
+    push(@{$fields->{jub}   },'lineitem_notes') if $$options{flesh_notes};
+    push(@{$fields->{acqlin}},    'alert_text') if $$options{flesh_notes};
+    push(@{$fields->{jub}   }, 'order_summary') if $$options{flesh_order_summary};
     push(@{$fields->{acqlin}}, 'cancel_reason') if $$options{flesh_cancel_reason};
 
     if($$options{flesh_li_details}) {
-        push(@{$fields->{jub}}, 'lineitem_details');
-        push(@{$fields->{acqlid}}, 'fund') if $$options{flesh_fund};
-        push(@{$fields->{acqlid}}, 'fund_debit') if $$options{flesh_fund_debit};
+        push(@{$fields->{jub}   }, 'lineitem_details');
+        push(@{$fields->{acqlid}}, 'fund'         ) if $$options{flesh_fund};
+        push(@{$fields->{acqlid}}, 'fund_debit'   ) if $$options{flesh_fund_debit};
         push(@{$fields->{acqlid}}, 'cancel_reason') if $$options{flesh_cancel_reason};
     }
 
@@ -149,12 +151,12 @@
 
     return $e->event unless (
         $li->purchase_order and 
-            $e->allowed(['VIEW_PURCHASE_ORDER', 'CREATE_PURCHASE_ORDER'], 
-                $li->purchase_order->ordering_agency, $li->purchase_order)
+            ($no_auth or $e->allowed(['VIEW_PURCHASE_ORDER', 'CREATE_PURCHASE_ORDER'], 
+                $li->purchase_order->ordering_agency, $li->purchase_order))
     ) or (
         $li->picklist and !$li->purchase_order and # user doesn't have view_po perms
-            $e->allowed(['VIEW_PICKLIST', 'CREATE_PICKLIST'], 
-                $li->picklist->org_unit, $li->picklist)
+            ($no_auth or $e->allowed(['VIEW_PICKLIST', 'CREATE_PICKLIST'], 
+                $li->picklist->org_unit, $li->picklist))
     );
 
     unless ($$options{flesh_po}) {

Modified: branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Acq/Order.pm
===================================================================
--- branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Acq/Order.pm	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Acq/Order.pm	2010-10-18 13:46:56 UTC (rev 18371)
@@ -482,9 +482,8 @@
         $lid->location($loc);
     }
 
-    if(!$lid->circ_modifier and my $mod = get_default_circ_modifier($mgr, $lid->owning_lib)) {
-        $lid->circ_modifier($mod);
-    }
+    $lid->circ_modifier(get_default_circ_modifier($mgr, $lid->owning_lib))
+        unless defined $lid->circ_modifier;
 
     $mgr->editor->update_acq_lineitem_detail($lid) or return 0;
     return $lid;
@@ -492,10 +491,9 @@
 
 sub get_default_circ_modifier {
     my($mgr, $org) = @_;
-    my $mod = $mgr->cache($org, 'def_circ_mod');
-    return $mod if $mod;
-    $mod = $U->ou_ancestor_setting_value($org, 'acq.default_circ_modifier');
-    return $mgr->cache($org, 'def_circ_mod', $mod) if $mod;
+    my $code = $mgr->cache($org, 'def_circ_mod');
+    $code = $U->ou_ancestor_setting_value($org, 'acq.default_circ_modifier') unless defined $code;
+    return $mgr->cache($org, 'def_circ_mod', $code) if defined $code;
     return undef;
 }
 
@@ -660,7 +658,9 @@
         ]);
     }
 
-    unless(ref $lid and ref $lid->fund) {
+    if(ref $lid) {
+        $lid->fund($mgr->editor->retrieve_acq_fund($lid->fund)) unless(ref $lid->fund);
+    } else {
         $lid = $mgr->editor->retrieve_acq_lineitem_detail([
             $lid,
             {   flesh => 1, 
@@ -669,6 +669,13 @@
         ]);
     }
 
+    unless ($lid->fund) {
+        $mgr->editor->event(
+            new OpenILS::Event("ACQ_FUND_NOT_FOUND") # close enough
+        );
+        return 0;
+    }
+
     my $amount = $li->estimated_unit_price;
     if($li->provider->currency_type ne $lid->fund->currency_type and !$no_translate) {
 
@@ -988,7 +995,7 @@
             $volume = create_volume($mgr, $li, $lid) or return 0;
             $mgr->cache($org, "cn.$bibid.$label", $volume);
         }
-        create_copy($mgr, $volume, $lid) or return 0;
+        create_copy($mgr, $volume, $lid, $li) or return 0;
     }
 
     return { li => $li, new_bib => $new_bib };
@@ -1036,7 +1043,7 @@
 }
 
 sub create_copy {
-    my($mgr, $volume, $lid) = @_;
+    my($mgr, $volume, $lid, $li) = @_;
     my $copy = Fieldmapper::asset::copy->new;
     $copy->isnew(1);
     $copy->loan_duration(2);
@@ -1048,6 +1055,10 @@
     $copy->circ_lib($volume->owning_lib);
     $copy->circ_modifier($lid->circ_modifier);
 
+    # AKA list price.  We might need a $li->list_price field since 
+    # estimated price is not necessarily the same as list price
+    $copy->price($li->estimated_unit_price); 
+
     my $evt = OpenILS::Application::Cat::AssetCommon->create_copy($mgr->editor, $volume, $copy);
     if($evt) {
         $mgr->editor->event($evt);
@@ -1158,9 +1169,9 @@
 # ----------------------------------------------------------------------------
 
 __PACKAGE__->register_method(
-    method => 'upload_records',
+    method   => 'upload_records',
     api_name => 'open-ils.acq.process_upload_records',
-    stream => 1,
+    stream   => 1,
 );
 
 sub upload_records {
@@ -1173,14 +1184,14 @@
     my $cache = OpenSRF::Utils::Cache->new;
 
     my $data = $cache->get_cache("vandelay_import_spool_$key");
-	my $purpose = $data->{purpose};
-    my $filename = $data->{path};
-    my $provider = $data->{provider};
-    my $picklist = $data->{picklist};
-    my $create_po = $data->{create_po};
-    my $activate_po = $data->{activate_po};
+    my $purpose         = $data->{purpose};
+    my $filename        = $data->{path};
+    my $provider        = $data->{provider};
+    my $picklist        = $data->{picklist};
+    my $create_po       = $data->{create_po};
+    my $activate_po     = $data->{activate_po};
     my $ordering_agency = $data->{ordering_agency};
-    my $create_assets = $data->{create_assets};
+    my $create_assets   = $data->{create_assets};
     my $po;
     my $evt;
 
@@ -1212,8 +1223,7 @@
 
     $logger->info("acq processing MARC file=$filename");
 
-    my $marctype = 'USMARC'; # ?
-	my $batch = new MARC::Batch ($marctype, $filename);
+	my $batch = new MARC::Batch ('USMARC', $filename);
 	$batch->strict_off;
 
 	my $count = 0;
@@ -1221,10 +1231,8 @@
 
 	while(1) {
 
-	    my $err;
-        my $xml;
+	    my ($err, $xml, $r);
 		$count++;
-        my $r;
 
 		try {
             $r = $batch->next;
@@ -1281,7 +1289,7 @@
     unlink($filename);
     $cache->delete_cache('vandelay_import_spool_' . $key);
 
-    if($create_assets) {
+    if ($create_assets) {
         create_lineitem_list_assets($mgr, \@li_list) or return $e->die_event;
     }
 
@@ -1313,14 +1321,15 @@
         last unless $$compiled{quantity};
 
         for(1..$$compiled{quantity}) {
-            my $lid = create_lineitem_detail($mgr, 
-                lineitem => $li->id,
-                owning_lib => $$compiled{owning_lib},
-                cn_label => $$compiled{call_number},
-                fund => $$compiled{fund},
-                circ_modifier => $$compiled{circ_modifier},
-                note => $$compiled{note},
-                location => $$compiled{copy_location},
+            my $lid = create_lineitem_detail(
+                $mgr, 
+                lineitem        => $li->id,
+                owning_lib      => $$compiled{owning_lib},
+                cn_label        => $$compiled{call_number},
+                fund            => $$compiled{fund},
+                circ_modifier   => $$compiled{circ_modifier},
+                note            => $$compiled{note},
+                location        => $$compiled{copy_location},
                 collection_code => $$compiled{collection_code}
             ) or return 0;
         }
@@ -1386,23 +1395,22 @@
     # ---------------------------------------------------------------------
     # Circ Modifier
     my $code = $compiled{circ_modifier};
-    my $mod;
 
-    if($code) {
+    if(defined $code) {
 
-        $mod = $mgr->cache($base_org, "mod.$code") ||
+        # verify this is a valid circ modifier
+        return $killme->("invlalid circ_modifier $code") unless 
+            defined $mgr->cache($base_org, "mod.$code") or 
             $mgr->editor->retrieve_config_circ_modifier($code);
-        return $killme->("invlalid circ_modifier $code") unless $mod;
-        $mgr->cache($base_org, "mod.$code", $mod);
 
+            # if valid, cache for future tests
+            $mgr->cache($base_org, "mod.$code", $code);
+
     } else {
-        # try the default
-        $mod = get_default_circ_modifier($mgr, $base_org);
+        $compiled{circ_modifier} = get_default_circ_modifier($mgr, $base_org);
     }
 
-    $compiled{circ_modifier} = $mod if $mod;
 
-
     # ---------------------------------------------------------------------
     # Shelving Location
     if( my $name = $compiled{copy_location}) {
@@ -1482,10 +1490,10 @@
 
 
 __PACKAGE__->register_method(
-	method => 'create_purchase_order_api',
-	api_name	=> 'open-ils.acq.purchase_order.create',
-	signature => {
-        desc => 'Creates a new purchase order',
+    method    => 'create_purchase_order_api',
+    api_name  => 'open-ils.acq.purchase_order.create',
+    signature => {
+        desc   => 'Creates a new purchase order',
         params => [
             {desc => 'Authentication token', type => 'string'},
             {desc => 'purchase_order to create', type => 'object'}
@@ -1505,10 +1513,10 @@
 
     # create the PO
     my %pargs = (ordering_agency => $e->requestor->ws_ou); # default
-    $pargs{provider} = $po->provider if $po->provider;
-    $pargs{ordering_agency} = $po->ordering_agency if $po->ordering_agency;
-    $pargs{prepayment_required} = $po->prepayment_required
-        if $po->prepayment_required;
+    $pargs{provider}            = $po->provider            if $po->provider;
+    $pargs{ordering_agency}     = $po->ordering_agency     if $po->ordering_agency;
+    $pargs{prepayment_required} = $po->prepayment_required if $po->prepayment_required;
+        
     $po = create_purchase_order($mgr, %pargs) or return $e->die_event;
 
     my $li_ids = $$args{lineitems};
@@ -1543,14 +1551,11 @@
 
 
 __PACKAGE__->register_method(
-	method => 'update_lineitem_fund_batch',
-	api_name => 'open-ils.acq.lineitem.fund.update.batch',
-    stream => 1,
+    method   => 'update_lineitem_fund_batch',
+    api_name => 'open-ils.acq.lineitem.fund.update.batch',
+    stream   => 1,
     signature => { 
-        desc => q/
-            Given a set of lineitem IDS, updates the fund for all attached
-            lineitem details
-        /
+        desc => q/Given a set of lineitem IDS, updates the fund for all attached lineitem details/
     }
 );
 
@@ -1833,8 +1838,8 @@
 
 
 __PACKAGE__->register_method(
-	method => 'rollback_receive_po_api',
-	api_name	=> 'open-ils.acq.purchase_order.receive.rollback'
+    method   => 'rollback_receive_po_api',
+    api_name => 'open-ils.acq.purchase_order.receive.rollback'
 );
 
 sub rollback_receive_po_api {
@@ -1862,10 +1867,10 @@
 
 
 __PACKAGE__->register_method(
-	method => 'rollback_receive_lineitem_detail_api',
-	api_name	=> 'open-ils.acq.lineitem_detail.receive.rollback',
-	signature => {
-        desc => 'Mark a lineitem_detail as Un-received',
+    method    => 'rollback_receive_lineitem_detail_api',
+    api_name  => 'open-ils.acq.lineitem_detail.receive.rollback',
+    signature => {
+        desc   => 'Mark a lineitem_detail as Un-received',
         params => [
             {desc => 'Authentication token', type => 'string'},
             {desc => 'lineitem detail ID', type => 'number'}
@@ -2191,11 +2196,24 @@
     update_purchase_order($mgr, $po) or return $e->die_event;
 
     my $query = [
-        {purchase_order => $po_id, state => 'pending-order'},
+        {
+            purchase_order => $po_id, 
+            '-or' => [{state => 'pending-order'}, {state => 'new'}]
+        },
         {limit => 1}
     ];
 
-    while( my $li = $e->search_acq_lineitem($query)->[0] ) {
+    while( my $li_id = $e->search_acq_lineitem($query, {idlist => 1})->[0] ) {
+
+        my $li;
+        if($dry_run) {
+            $li = $e->retrieve_acq_lineitem($li_id);
+        } else {
+            # can't activate a PO w/o assets.  Create lineitem assets as necessary
+            my $data = create_lineitem_assets($mgr, $li_id) or return $e->die_event;
+            $li = $data->{li};
+        }
+
         $li->state('on-order');
         create_lineitem_debits($mgr, $li, $dry_run) or return $e->die_event;
         update_lineitem($mgr, $li) or return $e->die_event;
@@ -3110,4 +3128,48 @@
 }
 
 
+__PACKAGE__->register_method(
+	method => "clone_distrib_form",
+	api_name => "open-ils.acq.distribution_formula.clone",
+    stream => 1,
+	signature => {
+        desc => q/Clone a distribution formula/,
+        params => [
+            {desc => "Authentication token", type => "string"},
+            {desc => "Original formula ID", type => 'integer'},
+            {desc => "Name of new formula", type => 'string'},
+        ],
+        return => {desc => "ID of newly created formula"}
+    }
+);
+
+sub clone_distrib_form {
+    my($self, $client, $auth, $form_id, $new_name) = @_;
+
+    my $e = new_editor("xact"=> 1, "authtoken" => $auth);
+    return $e->die_event unless $e->checkauth;
+
+    my $old_form = $e->retrieve_acq_distribution_formula($form_id) or return $e->die_event;
+    return $e->die_event unless $e->allowed('ADMIN_ACQ_DISTRIB_FORMULA', $old_form->owner);
+
+    my $new_form = Fieldmapper::acq::distribution_formula->new;
+
+    $new_form->owner($old_form->owner);
+    $new_form->name($new_name);
+    $e->create_acq_distribution_formula($new_form) or return $e->die_event;
+
+    my $entries = $e->search_acq_distribution_formula_entry({formula => $form_id});
+    for my $entry (@$entries) {
+       my $new_entry = Fieldmapper::acq::distribution_formula_entry->new;
+       $new_entry->$_($entry->$_()) for $entry->real_fields;
+       $new_entry->formula($new_form->id);
+       $new_entry->clear_id;
+       $e->create_acq_distribution_formula_entry($new_entry) or return $e->die_event;
+    }
+
+    $e->commit;
+    return $new_form->id;
+}
+
 1;
+

Modified: branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Actor/UserGroups.pm
===================================================================
--- branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Actor/UserGroups.pm	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Actor/UserGroups.pm	2010-10-18 13:46:56 UTC (rev 18371)
@@ -24,21 +24,21 @@
 	my $e = new_editor(authtoken=>$auth);
 	return $e->event unless $e->checkauth;
 	return $e->event unless $e->allowed('VIEW_USER');
-    return $e->json_query(
-        {
-            select => {mous => ['usr', 'balance_owed']},
-            from => 'mous',
-            where => {
-                usr => {
-                    in => {
-                        select => {au => ['id']}, 
-                        from => 'au', 
-                        where => {usrgroup => $group_id}
-                    }
-                }
+
+	my $users = $e->search_actor_user({usrgroup => $group_id}, {idlist => 1});
+    my @mous;
+
+    for my $uid ( @$users ) {
+        push @mous, @{$e->json_query(
+            {
+                select => {mous => ['usr', 'balance_owed']},
+                from => 'mous',
+                where => { usr => $uid }
             }
-        }
-    );
+        )};
+    }
+
+    return \@mous;
 }
 
 

Modified: branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Actor.pm
===================================================================
--- branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Actor.pm	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Actor.pm	2010-10-18 13:46:56 UTC (rev 18371)
@@ -1528,6 +1528,73 @@
 }
 
 
+__PACKAGE__->register_method(
+    method        => "user_opac_vitals",
+    api_name      => "open-ils.actor.user.opac.vital_stats",
+    argc          => 1,
+    authoritative => 1,
+    signature     => {
+        desc   => 'Returns a short summary of the users vital stats, including '  .
+                  'identification information, accumulated balance, number of holds, ' .
+                  'and current open circulation stats' ,
+        params => [
+            {desc => 'Authentication token',                          type => 'string'},
+            {desc => 'Optional User ID, for use in the staff client', type => 'number'}  # number?
+        ],
+        return => {
+            desc => "An object with four properties: user, fines, checkouts and holds."
+        }
+    }
+);
+
+sub user_opac_vitals {
+	my( $self, $client, $auth, $user_id ) = @_;
+
+	my $e = new_editor(authtoken=>$auth);
+	return $e->event unless $e->checkauth;
+
+    $user_id ||= $e->requestor->id;
+
+    my $user = $e->retrieve_actor_user( $user_id );
+
+    my ($fines) = $self
+        ->method_lookup('open-ils.actor.user.fines.summary')
+        ->run($auth => $user_id);
+    return $fines if (defined($U->event_code($fines)));
+
+    if (!$fines) {
+        $fines = new Fieldmapper::money::open_user_summary ();
+        $fines->balance_owed(0.00);
+        $fines->total_owed(0.00);
+        $fines->total_paid(0.00);
+        $fines->usr($user_id);
+    }
+
+    my ($holds) = $self
+        ->method_lookup('open-ils.actor.user.hold_requests.count')
+        ->run($auth => $user_id);
+    return $holds if (defined($U->event_code($holds)));
+
+    my ($out) = $self
+        ->method_lookup('open-ils.actor.user.checked_out.count')
+        ->run($auth => $user_id);
+    return $out if (defined($U->event_code($out)));
+
+    return {
+        user => {
+            first_given_name  => $user->first_given_name,
+            second_given_name => $user->second_given_name,
+            family_name       => $user->family_name,
+            alias             => $user->alias,
+            usrname           => $user->usrname
+        },
+        fines => $fines->to_bare_hash,
+        checkouts => $out,
+        holds => $holds
+    };
+}
+
+
 ##### a small consolidation of related method registrations
 my $common_params = [
     { desc => 'Authentication token', type => 'string' },

Modified: branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Booking.pm
===================================================================
--- branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Booking.pm	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Booking.pm	2010-10-18 13:46:56 UTC (rev 18371)
@@ -791,7 +791,7 @@
 
     my $e = new_editor("authtoken" => $auth);
     return $e->die_event unless $e->checkauth;
-    return $e->die_event unless $e->allowed("CAPTURE_RESERVATION");
+    return $e->die_event unless $e->allowed("COPY_CHECKIN");
 
     my $dt_parser = new DateTime::Format::ISO8601;
     my $now = now DateTime; # sic
@@ -940,7 +940,7 @@
 
     my $e = new_editor(authtoken => $auth);
     return $e->die_event unless $e->checkauth;
-    return $e->die_event unless $e->allowed("CAPTURE_RESERVATION");
+    return $e->die_event unless $e->allowed("COPY_CHECKIN");
 
     my $uncaptured = get_uncaptured_bresv_for_brsrc(
         $e, {"barcode" => $barcode}
@@ -987,7 +987,7 @@
 
     my $e = new_editor("xact" => 1, "authtoken" => $auth);
     return $e->die_event unless $e->checkauth;
-    return $e->die_event unless $e->allowed('CAPTURE_RESERVATION');
+    return $e->die_event unless $e->allowed("COPY_CHECKIN");
     my $here = $e->requestor->ws_ou;
 
     my $reservation = $e->retrieve_booking_reservation([

Modified: branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Cat/AuthCommon.pm
===================================================================
--- branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Cat/AuthCommon.pm	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Cat/AuthCommon.pm	2010-10-18 13:46:56 UTC (rev 18371)
@@ -36,10 +36,6 @@
 	$rec->edit_date('now');
 	$rec->marc($U->entityize($marc_doc->documentElement->toString));
 
-    my ($arn, $evt) = find_arn($e, $marc_doc);
-    return $evt if $evt;
-    $rec->arn_value($arn);
-
     $rec = $e->create_authority_record_entry($rec) or return $e->die_event;
 
     # we don't care about the result, just fire off the request
@@ -68,24 +64,4 @@
 	return $rec;
 }
 
-sub find_arn {
-    my($e, $marc_doc) = @_;
-
-    my $xpath = '//marc:controlfield[@tag="001"]';
-    my ($arn) = $marc_doc->documentElement->findvalue($xpath);
-
-    if(my $existing_rec = $e->search_authority_record_entry({arn_value => $arn, deleted => 'f'})->[0]) {
-        # this arn is taken
-        return (
-            undef, 
-            OpenILS::Event->new(
-                'AUTHORITY_RECORD_NUMBER_EXISTS', 
-                payload => {existing_record => $existing_rec, arn => $arn}
-            )
-        );
-    }
-
-    return ($arn);
-}
-
 1;

Modified: branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Cat/Authority.pm
===================================================================
--- branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Cat/Authority.pm	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Cat/Authority.pm	2010-10-18 13:46:56 UTC (rev 18371)
@@ -32,13 +32,88 @@
 	my $e = new_editor(authtoken=>$auth, xact=>1);
 	return $e->die_event unless $e->checkauth;
 	return $e->die_event unless $e->allowed('CREATE_AUTHORITY_RECORD');
-    my $rec = OpenILS::Utils::Cat::AuthCommon->import_authority_record($marc_xml, $source);
+    my $rec = OpenILS::Application::Cat::AuthCommon->import_authority_record($marc_xml, $source);
     $e->commit unless $U->event_code($rec);
     return $rec;
 }
 
+__PACKAGE__->register_method(
+    method => 'create_authority_record_from_bib_field',
+    api_name => 'open-ils.cat.authority.record.create_from_bib',
+    signature => {
+        desc => q/Create an authority record entry from a field in a bibliographic record/,
+        params => q/
+            @param field A hash representing the field to control, consisting of: { tag: string, ind1: string, ind2: string, subfields: [ [code, value] ... ] }
+            @param authtoken A valid authentication token
+            @returns The new record object 
+ /}
+);
 
 __PACKAGE__->register_method(
+    method => 'create_authority_record_from_bib_field',
+    api_name => 'open-ils.cat.authority.record.create_from_bib.readonly',
+    signature => {
+        desc => q/Creates MARCXML for an authority record entry from a field in a bibliographic record/,
+        params => q/
+            @param field A hash representing the field to control, consisting of: { tag: string, ind1: string, ind2: string, subfields: [ [code, value] ... ] }
+            @returns The MARCXML for the authority record
+ /}
+);
+
+sub create_authority_record_from_bib_field {
+    my($self, $conn, $field, $auth) = @_;
+
+    # Change the first character of the incoming bib field tag to a '1'
+    # for use in our authority record; close enough for now?
+    my $tag = $field->{'tag'};
+    $tag =~ s/^./1/;
+
+    my $ind1 = $field->{ind1} || ' ';
+    my $ind2 = $field->{ind2} || ' ';
+
+    my $control = qq{<datafield tag="$tag" ind1="$ind1" ind2="$ind2">};
+    foreach my $sf (@{$field->{subfields}}) {
+        my $code = $sf->[0];
+        my $val = $U->entityize($sf->[1]);
+        $control .= qq{<subfield code="$code">$val</subfield>};
+    }
+    $control .= '</datafield>';
+
+    # ARN, or "authority record number", used to need to be unique across the database.
+    # Of course, we have no idea what's in the database, and if the
+    # cat.maintain_control_numbers flag is set to "TRUE" then the 001 will
+    # be reset to the record ID anyway.
+    my $arn = 'AUTOGEN-' . time();
+
+    # Placeholder MARCXML; 
+    #   001/003 can be filled in via database triggers
+    #   005 will be filled in automatically at creation time
+    #   008 needs to be set by a cataloguer (could be some OU settings, I suppose)
+    #   040 should come from OU settings / OU shortname
+    #   
+    my $marc_xml = <<MARCXML;
+<record xmlns:marc="http://www.loc.gov/MARC21/slim" xmlns="http://www.loc.gov/MARC21/slim"><leader>     nz  a22     o  4500</leader>
+<controlfield tag="001">$arn</controlfield>
+<controlfield tag="003">CONS</controlfield>
+<controlfield tag="008">      ||||||||||||||||||||||||||||||||||</controlfield>
+<datafield tag="040" ind1=" " ind2=" "><subfield code="a">CONS</subfield><subfield code="c">CONS</subfield></datafield>
+$control
+</record>
+MARCXML
+
+    if ($self->api_name =~ m/readonly$/) {
+        return $marc_xml;
+    } else {
+        my $e = new_editor(authtoken=>$auth, xact=>1);
+        return $e->die_event unless $e->checkauth;
+        return $e->die_event unless $e->allowed('CREATE_AUTHORITY_RECORD');
+        my $rec = OpenILS::Application::Cat::AuthCommon->import_authority_record($e, $marc_xml);
+        $e->commit unless $U->event_code($rec);
+        return $rec;
+    }
+}
+
+__PACKAGE__->register_method(
 	method	=> 'overlay_authority_record',
 	api_name	=> 'open-ils.cat.authority.record.overlay',
 );
@@ -48,7 +123,7 @@
 	my $e = new_editor(authtoken=>$auth, xact=>1);
 	return $e->die_event unless $e->checkauth;
 	return $e->die_event unless $e->allowed('UPDATE_AUTHORITY_RECORD');
-    my $rec = OpenILS::Utils::Cat::AuthCommon->overlay_authority_record($rec_id, $marc_xml, $source);
+    my $rec = OpenILS::Application::Cat::AuthCommon->overlay_authority_record($rec_id, $marc_xml, $source);
     $e->commit unless $U->event_code($rec);
     return $rec;
 
@@ -98,4 +173,51 @@
     return undef;
 }
 
+__PACKAGE__->register_method(
+    method    => 'count_linked_bibs',
+    api_name  => 'open-ils.cat.authority.records.count_linked_bibs',
+    signature => q/
+        Counts the number of bib records linked to each authority record in the input list
+        @param records Array of authority records to return counts
+        @return A list of hashes containing the authority record ID ("id") and linked bib count ("bibs")
+    /
+);
+
+sub count_linked_bibs {
+    my( $self, $conn, $records ) = @_;
+
+    my $editor = new_editor();
+
+    my $link_count;
+    my @clean_records;
+    for my $auth ( @$records ) {
+        # Protection against SQL injection? Might be overkill.
+        my $intauth = int($auth);
+        if ($intauth) {
+            push(@clean_records, $intauth);
+        }
+    }
+    return $link_count if !@clean_records;
+    
+    $link_count = $editor->json_query({
+        "select" => {
+            "abl" => [
+                {
+                    "column" => "authority"
+                },
+                {
+                    "alias" => "bibs",
+                    "transform" => "count",
+                    "column" => "bib",
+                    "aggregate" => 1
+                }
+            ]
+        },
+        "from" => "abl",
+        "where" => { "authority" => \@clean_records }
+    });
+
+    return $link_count;
+}
+
 1;

Modified: branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Cat/BibCommon.pm
===================================================================
--- branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Cat/BibCommon.pm	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Cat/BibCommon.pm	2010-10-18 13:46:56 UTC (rev 18371)
@@ -89,6 +89,9 @@
 		return $evt if $evt;
 	}
 
+	# Silence warnings when _find_tcn_info() fails
+	$tcn ||= '';
+	$tcn_source ||= '';
 	$logger->info("user ".$e->requestor->id.
 		" creating new biblio entry with tcn=$tcn and tcn_source $tcn_source");
 

Modified: branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Cat.pm
===================================================================
--- branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Cat.pm	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Cat.pm	2010-10-18 13:46:56 UTC (rev 18371)
@@ -676,7 +676,45 @@
     return $count;
 }
 
+__PACKAGE__->register_method(
+    method    => 'in_db_auth_merge',
+    api_name  => 'open-ils.cat.authority.records.merge',
+    signature => q/
+        Merges a group of authority records
+        @param auth The login session key
+        @param master The id of the record all other records should be merged into
+        @param records Array of records to be merged into the master record
+        @return 1 on success, Event on error.
+    /
+);
 
+sub in_db_auth_merge {
+    my( $self, $conn, $auth, $master, $records ) = @_;
+
+    my $editor = new_editor( authtoken => $auth, xact => 1 );
+    return $editor->die_event unless $editor->checkauth;
+    return $editor->die_event unless $editor->allowed('MERGE_AUTH_RECORDS'); # TODO see below about record ownership
+
+    my $count = 0;
+    for my $source ( @$records ) {
+        $count += $editor->json_query({
+            select => {
+                are => [{
+                    alias => 'count',
+                    transform => 'authority.merge_records',
+                    column => 'id',
+                    params => [$source]
+                }]
+            },
+            from   => 'are',
+            where  => { id => $master }
+        })->[0]->{count}; # count of objects moved, of all types
+    }
+
+    $editor->commit;
+    return $count;
+}
+
 __PACKAGE__->register_method(
 	method	=> "fleshed_volume_update",
 	api_name	=> "open-ils.cat.asset.volume.fleshed.batch.update",);

Modified: branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Circ/Circulate.pm
===================================================================
--- branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Circ/Circulate.pm	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Circ/Circulate.pm	2010-10-18 13:46:56 UTC (rev 18371)
@@ -14,6 +14,11 @@
 my $script_libs;
 my $legacy_script_support = 0;
 
+my $MK_ENV_FLESH = { 
+    flesh => 2, 
+    flesh_fields => {acp => ['call_number'], acn => ['record']} 
+};
+
 sub initialize {
 
     my $self = shift;
@@ -188,7 +193,7 @@
             my $res_id_list = [ map { $_->id } @$resources ];
             my $transit = $circulator->editor->search_action_reservation_transit_copy(
                 [
-                    { target_copy => $res_id_list, dest => $circulator->circ_lib },
+                    { target_copy => $res_id_list, dest => $circulator->circ_lib, dest_recv_time => undef },
                     { order_by => { artc => 'source_send_time' }, limit => 1 }
                 ]
             )->[0]; # Any transit for this barcode?
@@ -198,12 +203,21 @@
                 my $reservation = $circulator->editor->retrieve_booking_reservation( $transit->reservation );
                 my $res_type    = $circulator->editor->retrieve_booking_resource_type( $reservation->target_resource_type );
 
+                my $success_event = new OpenILS::Event(
+                    "SUCCESS", "payload" => {"reservation" => $reservation}
+                );
                 if ($U->is_true($res_type->catalog_item)) { # is there a copy to be had here?
-                    if (my $copy = $circulator->editor->search_asset_copy({ barcode => $bc, deleted => 'f' })->[0]) { # got a copy
+                    if (my $copy = $circulator->editor->search_asset_copy([
+                        { barcode => $bc, deleted => 'f' }, $MK_ENV_FLESH
+                    ])->[0]) { # got a copy
                         $copy->status( $transit->copy_status );
                         $copy->editor($circulator->editor->requestor->id);
                         $copy->edit_date('now');
-                        $circulator->editor->update_asset_copy( $copy );
+                        $circulator->editor->update_asset_copy($copy);
+                        $success_event->{"payload"}->{"record"} =
+                            $U->record_to_mvr($copy->call_number->record);
+                        $copy->call_number($copy->call_number->id);
+                        $success_event->{"payload"}->{"copy"} = $copy;
                     }
                 }
 
@@ -211,51 +225,9 @@
                 $circulator->editor->update_action_reservation_transit_copy( $transit );
 
                 $circulator->editor->commit;
-
-                #XXX need to return here, with info about the resource/copy and the "put it on the booking shelf" message
-
-            } else { # no transit, look for an upcoming reservation to capture for
-
-                my $reservation = $circulator->editor->search_booking_reservation(
-                    [
-                        { current_resource => $res_id_list,
-                          pickup_lib => $circulator->circ_lib,
-                          cancel_time => undef,
-                          capture_time => undef
-                        },
-                        { order_by => { bresv => 'start_time' }, limit => 1 }
-                    ]
-                )->[0];
-
-                if ($reservation) { # we have a reservation for which we could capture this resource.  wheee!
-                    my $res_type = $circulator->editor->retrieve_booking_resource_type( $reservation->target_resource_type );
-                    my $elbow_room = $res_type->elbow_room ||
-                        $U->ou_ancestor_setting_value( $circulator->circ_lib, 'circ.booking_reservation.default_elbow_room', $circulator->editor );
-                
-                    if ($elbow_room) {
-                        $reservation = $circulator->editor->search_booking_reservation(
-                            [
-                                { id => $reservation->id, start_time => { '<=' => DateTime->now->add( seconds => interval_to_seconds($elbow_room) )->strftime('%FT%T%z') } },
-                                { order_by => { bresv => 'start_time' }, limit => 1 }
-                            ]
-                        )->[0];
-                    }
-
-                    if ($reservation) { # no elbow room specified, or we still have a reservation within the elbow_room time
-                        my $b_ses = OpenSRF::AppSession->create('open-ils.booking');
-                        my $result = $b_ses->request(
-                            'open-ils.booking.reservations.capture',
-                            $auth => $reservation->id
-                        )->gather(1);
-
-                        if (ref($result) && $result->{ilsevent} == 0) { # captured!
-                            #XXX what to return here???
-                            return $result; # the booking capture success
-                        } else {
-                            #XXX how to fail???  Probably, just move on.
-                        }
-                    }
-                }
+                # Formerly this branch just stopped here. Argh!
+                $conn->respond_complete($success_event);
+                return;
             }
         }
     }
@@ -266,11 +238,24 @@
     # Go ahead and load the script runner to make sure we have all 
     # of the objects we need
     # --------------------------------------------------------------------------
-    $circulator->is_res_checkin($circulator->is_checkin(1)) if $api =~ /reservation.return/;
+
+    # XXX I wanted to make this better so it might support blocking renewals
+    # if a reservation has been placed on an item, but that will need more
+    # design, as institutions will differ in their policy on that.  In the
+    # meantime making sure we're trying some kind of checkin will at least
+    # keep OPAC renewals from breaking since patrons don't have VIEW_USER...
+
+    $circulator->is_res_checkin($circulator->is_checkin(1))
+        if $api =~ /reservation.return/ or (
+            $api =~ /checkin/ and $circulator->seems_like_reservation()
+        );
+
     $circulator->is_res_checkout(1) if $api =~ /reservation.pickup/;
 
     $circulator->is_renewal(1) if $api =~ /renew/;
     $circulator->is_checkin(1) if $api =~ /checkin/;
+
+    $circulator->mk_env();
     $circulator->noop if $circulator->claims_never_checked_out;
 
     if($legacy_script_support and not $circulator->is_checkin) {
@@ -280,8 +265,6 @@
         $circulator->circ_permit_copy($scripts{circ_permit_copy});      
         $circulator->circ_duration($scripts{circ_duration});             
         $circulator->circ_permit_renew($scripts{circ_permit_renew});
-    } elsif (not $circulator->is_res_checkin) { # mk_env cannot work w/ reservation.return
-        $circulator->mk_env();
     }
     return circ_events($circulator) if $circulator->bail_out;
 
@@ -455,8 +438,8 @@
     is_renewal
     is_checkout
     is_res_checkout
+    is_precat
     is_noncat
-    is_precat
     request_precat
     is_checkin
     is_res_checkin
@@ -600,6 +583,9 @@
     my( $self, @evts ) = @_;
     for my $e (@evts) {
         next unless $e;
+        $e->{payload} = $self->copy if 
+              ($e->{textcode} eq 'COPY_NOT_AVAILABLE');
+
         $logger->info("circulator: pushing event ".$e->{textcode});
         push( @{$self->events}, $e ) unless
             grep { $_->{textcode} eq $e->{textcode} } @{$self->events};
@@ -625,6 +611,49 @@
     return ($one) ? 1 : 0;
 }
 
+sub seems_like_reservation {
+    my $self = shift;
+
+    # Some words about the following method:
+    # 1) It requires the VIEW_USER permission, but that's not an
+    # issue, right, since all staff should have that?
+    # 2) It returns only one reservation at a time, even if an item can be
+    # and is currently overbooked.  Hmmm....
+    my $booking_ses = create OpenSRF::AppSession("open-ils.booking");
+    my $result = $booking_ses->request(
+        "open-ils.booking.reservations.by_returnable_resource_barcode",
+        $self->editor->authtoken,
+        $self->copy_barcode
+    )->gather(1);
+    $booking_ses->disconnect;
+
+    return $self->bail_on_events($result) if defined $U->event_code($result);
+
+    if (@$result > 0) {
+        $self->reservation(shift @$result);
+        return 1;
+    } else {
+        return 0;
+    }
+
+}
+
+# save_trimmed_copy() used just to be a block in mk_env(), but was separated for re-use
+sub save_trimmed_copy {
+    my ($self, $copy) = @_;
+
+    $self->copy($copy);
+    $self->volume($copy->call_number);
+    $self->title($self->volume->record);
+    $self->copy->call_number($self->volume->id);
+    $self->volume->record($self->title->id);
+    $self->is_precat(1) if $self->volume->id == OILS_PRECAT_CALL_NUMBER;
+    if($self->copy->deposit_amount and $self->copy->deposit_amount > 0) {
+        $self->is_deposit(1) if $U->is_true($self->copy->deposit);
+        $self->is_rental(1) unless $U->is_true($self->copy->deposit);
+    }
+}
+
 sub mk_env {
     my $self = shift;
     my $e = $self->editor;
@@ -634,31 +663,49 @@
     # --------------------------------------------------------------------------
     unless($self->is_noncat) {
         my $copy;
-	    my $flesh = { 
-		    flesh => 2, 
-		    flesh_fields => {acp => ['location', 'status', 'circ_lib', 'age_protect', 'call_number'], acn => ['record']}
-	    };
 	    if($self->copy_id) {
 		    $copy = $e->retrieve_asset_copy(
-			    [$self->copy_id, $flesh ]) or return $e->event;
+			    [$self->copy_id, $MK_ENV_FLESH ]) or return $e->event;
     
 	    } elsif( $self->copy_barcode ) {
     
 		    $copy = $e->search_asset_copy(
-			    [{barcode => $self->copy_barcode, deleted => 'f'}, $flesh ])->[0];
-	    }
+			    [{barcode => $self->copy_barcode, deleted => 'f'}, $MK_ENV_FLESH ])->[0];
+	    } elsif( $self->reservation ) {
+            my $res = $e->json_query(
+                {
+                    "select" => {"acp" => ["id"]},
+                    "from" => {
+                        "acp" => {
+                            "brsrc" => {
+                                "fkey" => "barcode",
+                                "field" => "barcode",
+                                "join" => {
+                                    "bresv" => {
+                                        "fkey" => "id",
+                                        "field" => "current_resource"
+                                    }
+                                }
+                            }
+                        }
+                    },
+                    "where" => {
+                        "+bresv" => {
+                            "id" => (ref $self->reservation) ?
+                                $self->reservation->id : $self->reservation
+                        }
+                    }
+                }
+            );
+            if (ref $res eq "ARRAY" and scalar @$res) {
+                $logger->info("circulator: mapped reservation " .
+                    $self->reservation . " to copy " . $res->[0]->{"id"});
+                $copy = $e->retrieve_asset_copy([$res->[0]->{"id"}, $MK_ENV_FLESH]);
+            }
+        }
     
         if($copy) {
-            $self->copy($copy);
-            $self->volume($copy->call_number);
-            $self->title($self->volume->record);
-            $self->copy->call_number($self->volume->id);
-            $self->volume->record($self->title->id);
-            $self->is_precat(1) if $self->volume->id == OILS_PRECAT_CALL_NUMBER;
-            if($self->copy->deposit_amount and $self->copy->deposit_amount > 0) {
-                $self->is_deposit(1) if $U->is_true($self->copy->deposit);
-                $self->is_rental(1) unless $U->is_true($self->copy->deposit);
-            }
+            $self->save_trimmed_copy($copy);
         } else {
             # We can't renew if there is no copy
             return $self->bail_on_events(OpenILS::Event->new('ASSET_COPY_NOT_FOUND'))
@@ -951,7 +998,7 @@
                 # ahead and renew the item instead of warning about open circulations.
     
                 my $auto_renew_intvl = $U->ou_ancestor_setting_value(        
-                    $self->editor->requestor->ws_ou, 
+                    $self->circ_lib,
                     'circ.checkout_auto_renew_age', 
                     $self->editor
                 );
@@ -1074,7 +1121,7 @@
     my $results = $self->editor->json_query(
         {   from => [
                 $dbfunc,
-                $self->editor->requestor->ws_ou,
+                $self->circ_lib,
                 ($self->is_noncat or ($self->is_precat and !$self->override and !$self->is_renewal)) ? undef : $self->copy->id, 
                 $self->patron->id,
             ]
@@ -1230,11 +1277,6 @@
    my %hash = map { ($_->{ilsevent} => $_) } @allevents;
    @allevents = values %hash;
 
-   for (@allevents) {
-      $_->{payload} = $copy if 
-            ($_->{textcode} eq 'COPY_NOT_AVAILABLE');
-   }
-
     $logger->info("circulator: permit_copy script returned events: @allevents") if @allevents;
 
     $self->push_events(@allevents);
@@ -1309,7 +1351,7 @@
 
         $CR->checkin_time('now');   
         $CR->checkin_scan_time('now');   
-        $CR->checkin_lib($self->editor->requestor->ws_ou);
+        $CR->checkin_lib($self->circ_lib);
         $CR->checkin_workstation($self->editor->requestor->wsid);
         $CR->checkin_staff($self->editor->requestor->id);
 
@@ -1571,7 +1613,7 @@
     $hold->capture_time('now') unless $hold->capture_time;
     $hold->fulfillment_time('now');
     $hold->fulfillment_staff($e->requestor->id);
-    $hold->fulfillment_lib($e->requestor->ws_ou);
+    $hold->fulfillment_lib($self->circ_lib);
 
     return $self->bail_on_events($e->event)
         unless $e->update_action_hold_request($hold);
@@ -1594,7 +1636,7 @@
     return undef if $self->volume->id == OILS_PRECAT_CALL_NUMBER; 
 
     return undef unless $U->ou_ancestor_setting_value(        
-        $e->requestor->ws_ou, 'circ.checkout_fills_related_hold', $e);
+        $self->circ_lib, 'circ.checkout_fills_related_hold', $e);
 
     # find the oldest unfulfilled hold that has not yet hit the holds shelf.
     my $args = {
@@ -1831,13 +1873,17 @@
 
     $self->log_me("do_reservation_return()");
 
-    my ($reservation, $evt) = $U->fetch_booking_reservation($self->reservation);
-    return $self->bail_on_events($evt) if $evt;
+    if (not ref $self->reservation) {
+        my ($reservation, $evt) =
+            $U->fetch_booking_reservation($self->reservation);
+        return $self->bail_on_events($evt) if $evt;
+        $self->reservation($reservation);
+    }
 
-    $self->reservation( $reservation );
     $self->generate_fines(1);
     $self->reservation->return_time('now');
     $self->update_reservation();
+    $self->reshelve_copy if $self->copy;
 
     if ( $self->reservation->current_resource && $self->reservation->current_resource->catalog_item ) {
         $self->copy( $self->reservation->current_resource->catalog_item );
@@ -1877,7 +1923,7 @@
         my $booking_ses = OpenSRF::AppSession->create( 'open-ils.booking' );
         my $bookings = $booking_ses->request(
             'open-ils.booking.reservations.filtered_id_list', $self->editor->authtoken,
-            { resource => $booking_item->id, search_start => 'now', search_end => $circ->due_date }
+            { resource => $booking_item->id, search_start => 'now', search_end => $circ->due_date, fields => { cancel_time => undef }}
         )->gather(1);
         $booking_ses->disconnect;
         
@@ -1943,7 +1989,7 @@
 
         # due-date overlap should be determined by the location the item
         # is checked out from, not the owning or circ lib of the item
-        my $org = $self->editor->requestor->ws_ou;
+        my $org = $self->circ_lib;
 
       $logger->info("circulator: circ searching for closed date overlap on lib $org".
             " with an item due date of ".$circ->due_date );
@@ -2058,7 +2104,7 @@
     my $circ;
     my $evt;
 
-   my $lib      = $self->noncat_circ_lib || $self->editor->requestor->ws_ou;
+   my $lib      = $self->noncat_circ_lib || $self->circ_lib;
    my $count    = $self->noncat_count || 1;
    my $cotime   = cleanse_ISO8601($self->checkout_time) || "";
 
@@ -2210,12 +2256,33 @@
    # this copy can fulfill a hold or needs to be routed to a different location
    # ------------------------------------------------------------------------------
 
+    my $needed_for_something = 0; # formerly "needed_for_hold"
+
     if(!$self->noop) { # /not/ a no-op checkin, capture for hold or put item into transit
 
-        my $needed_for_hold = (!$self->remote_hold and $self->attempt_checkin_hold_capture());
+        if (!$self->remote_hold) {
+            my $potential_hold = $self->hold_capture_is_possible;
+            my $potential_reservation = $self->reservation_capture_is_possible;
+
+            if ($potential_hold and $potential_reservation) {
+                $logger->info("circulator: item could fulfill either hold or reservation");
+                $self->push_events(new OpenILS::Event(
+                    "HOLD_RESERVATION_CONFLICT",
+                    "hold" => $potential_hold,
+                    "reservation" => $potential_reservation
+                ));
+                return if $self->bail_out;
+            } elsif ($potential_hold) {
+                $needed_for_something =
+                    $self->attempt_checkin_hold_capture;
+            } elsif ($potential_reservation) {
+                $needed_for_something =
+                    $self->attempt_checkin_reservation_capture;
+            }
+        }
         return if $self->bail_out;
     
-        unless($needed_for_hold) {
+        unless($needed_for_something) {
             my $circ_lib = (ref $self->copy->circ_lib) ? 
                     $self->copy->circ_lib->id : $self->copy->circ_lib;
     
@@ -2225,9 +2292,9 @@
                     " is on a remote hold's shelf, sending to $circ_lib");
             }
     
-            $logger->debug("circulator: circlib=$circ_lib, workstation=".$self->editor->requestor->ws_ou);
+            $logger->debug("circulator: circlib=$circ_lib, workstation=".$self->circ_lib);
     
-            if( $circ_lib == $self->editor->requestor->ws_ou ) {
+            if( $circ_lib == $self->circ_lib) {
                 # copy is where it needs to be, either for hold or reshelving
     
                 $self->checkin_handle_precat();
@@ -2238,7 +2305,7 @@
     
                 if ($U->is_true( $self->copy->floating ) && !$self->remote_hold) { # copy is floating, stick here
                     $self->checkin_changed(1);
-                    $self->copy->circ_lib( $self->editor->requestor->ws_ou );
+                    $self->copy->circ_lib( $self->circ_lib );
                     $self->update_copy;
                 } else {
                     my $bc = $self->copy->barcode;
@@ -2252,10 +2319,11 @@
     } else { # no-op checkin
         if ($U->is_true( $self->copy->floating )) { # XXX floating items still stick where they are even with no-op checkin?
             $self->checkin_changed(1);
-            $self->copy->circ_lib( $self->editor->requestor->ws_ou );
+            $self->copy->circ_lib( $self->circ_lib );
             $self->update_copy;
         }
     }
+    $logger->info("LFW XXX: way down here"); # LFW XXX
 
     if($self->claims_never_checked_out and 
             $U->ou_ancestor_setting_value($self->circ->circ_lib, 'circ.claim_never_checked_out.mark_missing')) {
@@ -2265,7 +2333,7 @@
         $self->update_copy;
 
     } else {
-        $self->reshelve_copy;
+        $self->reshelve_copy unless $needed_for_something;
     }
 
     return if $self->bail_out;
@@ -2358,7 +2426,7 @@
     $logger->info("circulator: we found a captured, un-fulfilled hold [".
         $hold->id. "] for copy ".$self->copy->barcode);
 
-    if( $hold->pickup_lib == $self->editor->requestor->ws_ou ) {
+    if( $hold->pickup_lib == $self->circ_lib ) {
         $logger->info("circulator: hold is for here .. we're done: ".$self->copy->barcode);
         return 1;
     }
@@ -2391,7 +2459,7 @@
     #$dest  ||= (ref($copy->circ_lib)) ? $copy->circ_lib->id : $copy->circ_lib;
     $logger->info("circulator: transiting copy to $dest");
 
-   $transit->source($self->editor->requestor->ws_ou);
+   $transit->source($self->circ_lib);
    $transit->dest($dest);
    $transit->target_copy($copy->id);
    $transit->source_send_time('now');
@@ -2408,6 +2476,42 @@
 }
 
 
+sub hold_capture_is_possible {
+    my $self = shift;
+    my $copy = $self->copy;
+
+    # we've been explicitly told not to capture any holds
+    return 0 if $self->capture eq 'nocapture';
+
+    # See if this copy can fulfill any holds
+    my $hold = $holdcode->find_nearest_permitted_hold(
+        $self->editor, $copy, $self->editor->requestor, 1 # check_only
+    );
+    return undef if ref $hold eq "HASH" and
+        $hold->{"textcode"} eq "ACTION_HOLD_REQUEST_NOT_FOUND";
+    return $hold;
+}
+
+sub reservation_capture_is_possible {
+    my $self = shift;
+    my $copy = $self->copy;
+
+    # we've been explicitly told not to capture any holds
+    return 0 if $self->capture eq 'nocapture';
+
+    my $booking_ses = OpenSRF::AppSession->connect("open-ils.booking");
+    my $resv = $booking_ses->request(
+        "open-ils.booking.reservations.could_capture",
+        $self->editor->authtoken, $copy->barcode
+    )->gather(1);
+    $booking_ses->disconnect;
+    if (ref($resv) eq "HASH" and exists $resv->{"textcode"}) {
+        $self->push_events($resv);
+    } else {
+        return $resv;
+    }
+}
+
 # returns true if the item was used (or may potentially be used 
 # in subsequent calls) to capture a hold.
 sub attempt_checkin_hold_capture {
@@ -2444,7 +2548,7 @@
     $hold->current_copy($copy->id);
     $hold->capture_time('now');
     $self->put_hold_on_shelf($hold) 
-        if $hold->pickup_lib == $self->editor->requestor->ws_ou;
+        if $hold->pickup_lib == $self->circ_lib;
 
     # prevent DB errors caused by fetching 
     # holds from storage, and updating through cstore
@@ -2462,7 +2566,7 @@
 
     return 0 if $self->bail_out;
 
-    if( $hold->pickup_lib == $self->editor->requestor->ws_ou ) {
+    if( $hold->pickup_lib == $self->circ_lib ) {
 
         # This hold was captured in the correct location
         $copy->status(OILS_COPY_STATUS_ON_HOLDS_SHELF);
@@ -2486,6 +2590,69 @@
     return 1;
 }
 
+sub attempt_checkin_reservation_capture {
+    my $self = shift;
+    my $copy = $self->copy;
+
+    # we've been explicitly told not to capture any holds
+    return 0 if $self->capture eq 'nocapture';
+
+    my $booking_ses = OpenSRF::AppSession->connect("open-ils.booking");
+    my $evt = $booking_ses->request(
+        "open-ils.booking.resources.capture_for_reservation",
+        $self->editor->authtoken,
+        $copy->barcode,
+        1 # don't update copy - we probably have it locked
+    )->gather(1);
+    $booking_ses->disconnect;
+
+    if (ref($evt) ne "HASH" or not exists $evt->{"textcode"}) {
+        $logger->warn(
+            "open-ils.booking.resources.capture_for_reservation " .
+            "didn't return an event!"
+        );
+    } else {
+        if (
+            $evt->{"textcode"} eq "RESERVATION_NOT_FOUND" and
+            $evt->{"payload"}->{"fail_cause"} eq "not-transferable"
+        ) {
+            # not-transferable is an error event we'll pass on the user
+            $logger->warn("reservation capture attempted against non-transferable item");
+            $self->push_events($evt);
+            return 0;
+        } elsif ($evt->{"textcode"} eq "SUCCESS") {
+            # Re-retrieve copy as reservation capture may have changed
+            # its status and whatnot.
+            $logger->info(
+                "circulator: booking capture win on copy " . $self->copy->id
+            );
+            if (my $new_copy_status = $evt->{"payload"}->{"new_copy_status"}) {
+                $logger->info(
+                    "circulator: changing copy " . $self->copy->id .
+                    "'s status from " . $self->copy->status . " to " .
+                    $new_copy_status
+                );
+                $self->copy->status($new_copy_status);
+                $self->update_copy;
+            }
+            $self->reservation($evt->{"payload"}->{"reservation"});
+
+            if (exists $evt->{"payload"}->{"transit"}) {
+                $self->push_events(
+                    new OpenILS::Event(
+                        "ROUTE_ITEM",
+                        "org" => $evt->{"payload"}->{"transit"}->dest
+                    )
+                );
+            }
+            $self->checkin_changed(1);
+            return 1;
+        }
+    }
+    # other results are treated as "nothing to capture"
+    return 0;
+}
+
 sub do_hold_notify {
     my( $self, $holdid ) = @_;
 
@@ -2541,7 +2708,7 @@
     $logger->debug("circulator: building hold transit for ".$copy->barcode);
 
    $trans->hold($hold->id);
-   $trans->source($self->editor->requestor->ws_ou);
+   $trans->source($self->circ_lib);
    $trans->dest($hold->pickup_lib);
    $trans->source_send_time("now");
    $trans->target_copy($copy->id);
@@ -2567,11 +2734,11 @@
 
     my $transit = $self->transit;
 
-    if( $transit->dest != $self->editor->requestor->ws_ou ) {
+    if( $transit->dest != $self->circ_lib ) {
         # - this item is in-transit to a different location
 
         my $tid = $transit->id; 
-        my $loc = $self->editor->requestor->ws_ou;
+        my $loc = $self->circ_lib;
         my $dest = $transit->dest;
 
         $logger->info("circulator: Fowarding transit on copy which is destined ".
@@ -2706,7 +2873,7 @@
     $circ->checkin_scan_time('now');
 
     $circ->checkin_staff($self->editor->requestor->id);
-    $circ->checkin_lib($self->editor->requestor->ws_ou);
+    $circ->checkin_lib($self->circ_lib);
     $circ->checkin_workstation($self->editor->requestor->wsid);
 
     my $circ_lib = (ref $self->copy->circ_lib) ?  
@@ -2718,7 +2885,7 @@
         $circ_lib, OILS_SETTING_LOST_IMMEDIATELY_AVAILABLE, $self->editor) || 0;
 
 
-    if ( (!$lost_immediately_available) && ($circ_lib != $self->editor->requestor->ws_ou) ) {
+    if ( (!$lost_immediately_available) && ($circ_lib != $self->circ_lib) ) {
 
         if( ($stat == OILS_COPY_STATUS_LOST or $stat == OILS_COPY_STATUS_MISSING) ) {
             $logger->info("circulator: not updating copy status on checkin because copy is lost/missing");
@@ -2933,6 +3100,9 @@
         $payload->{cancelled_hold_transit} = 1 if $self->cancelled_hold_transit;
         $payload->{hold}    = $hold;
         $payload->{patron}  = $self->patron;
+        $payload->{reservation} = $self->reservation
+            unless (not $self->reservation or $self->reservation->cancel_time);
+
         $evt->{payload}     = $payload;
     }
 }

Modified: branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Circ/CopyLocations.pm
===================================================================
--- branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Circ/CopyLocations.pm	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Circ/CopyLocations.pm	2010-10-18 13:46:56 UTC (rev 18371)
@@ -18,25 +18,56 @@
 	signature	=> q/
 		Retrieves the ranged set of copy locations for the requested org.
 		If no org is provided, all copy locations are returned
-		@param authtoken The login session key
 		@param orgId The org location id
+		@param noi18n No i18n in result
+        @param flesh_owning_lib Flesh owning lib in results
 		@return An array of copy location objects
 		/);
 
 sub cl_retrieve_all {
-	my( $self, $client, $org_id, $no_i18n ) = @_;
+	my ($self, $client, $org_id, $no_i18n, $flesh_owning_lib) = @_;
 
 	if(!$org_id) {
 		my $otree = $U->get_org_tree();
 		$org_id = $otree->id;
 	}
 
+    my $second_cstore_arg = {"no_i18n" => scalar($no_i18n)};
+    if ($flesh_owning_lib) {
+        $second_cstore_arg->{"flesh"} = 1;
+        $second_cstore_arg->{"flesh_fields"} = {"acpl" => ["owning_lib"]};
+    }
+
     return new_editor()->search_asset_copy_location([{
         owning_lib => $U->get_org_full_path($org_id)
-    }, {"no_i18n" => scalar($no_i18n)}]);
+    }, $second_cstore_arg]);
 }
 
 __PACKAGE__->register_method(
+    "api_name" => "open-ils.circ.copy_location.retrieve.distinct",
+    "method" => "cl_retrieve_distinct",
+    "stream" => 1,
+    "argc" => 0,
+    "signature" => q/Retrieve copy locations with distinct names globally/
+);
+
+sub cl_retrieve_distinct {
+    my ($self, $client) = @_;
+
+    my $e = new_editor();
+    my $names = $e->json_query({
+        "select" => {
+            "acpl" => [{"transform" => "distinct", "column" => "name"}]
+        },
+        "from" => {"acpl" => {}}
+    }) or return $e->die_event;
+    $e->disconnect;
+
+    $client->respond($_->{"name"}) for @$names;
+    undef;
+}
+
+__PACKAGE__->register_method(
 	api_name		=> 'open-ils.circ.copy_location.create',
 	method		=> 'cl_create',
 	argc			=> 2,

Modified: branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Circ/CreditCard.pm
===================================================================
--- branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Circ/CreditCard.pm	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Circ/CreditCard.pm	2010-10-18 13:46:56 UTC (rev 18371)
@@ -21,6 +21,7 @@
 
 use Business::CreditCard;
 use Business::OnlinePayment;
+use UUID::Tiny qw/:std/;
 use Locale::Country;
 
 use OpenILS::Event;
@@ -68,24 +69,32 @@
     );
 }
 
+# Provide default arguments for calls using the PayflowPro processor
+sub bop_args_PayflowPro {
+    my $argshash = shift;
+    return (
+        "vendor" => $argshash->{vendor},
+        "partner" => $argshash->{partner} || "PayPal" # reasonable default?
+    );
+}
+
 sub get_processor_settings {
     my $org_unit = shift;
     my $processor = lc shift;
 
+    # XXX TODO: make this one single cstore request instead of many
     +{ map { ($_ =>
         $U->ou_ancestor_setting_value(
             $org_unit, CREDIT_NS . ".processor.${processor}.${_}"
-        )) } qw/enabled login password signature server testmode/
+        )) } qw/enabled login password signature server testmode vendor partner/
     };
 }
 
-#    signature => {
-#        desc   => 'Process a payment via a supported processor (AuthorizeNet, Paypal)',
-#        params => [
-#            { desc => q/Hash of arguments with these keys:
+#        argshash (Hash of arguments with these keys):
 #                patron_id: Not a barcode, but a patron's internal ID
 #                       ou: Org unit where transaction happens
-#                processor: Payment processor to use (AuthorizeNet, PayPal, etc)
+#                processor: Payment processor to use
+#                           (AuthorizeNet/PayPal/PayflowPro)
 #                       cc: credit card number
 #                     cvv2: 3 or 4 digits from back of card
 #                   amount: transaction value
@@ -98,10 +107,6 @@
 #                      zip: optional (default: patron's zip field)
 #                  country: optional (some processor APIs: 2 letter code.)
 #              description: optional
-#                /, type => 'hash' }
-#        ],
-#        return => { desc => 'an ilsevent' }
-#    }
 
 sub process_payment {
     my ($argshash) = @_;
@@ -209,6 +214,8 @@
     # PayPal must have 2 letter country field (ISO 3166) that's uppercase.
     if (length($content{country}) > 2 && $argshash->{processor} eq 'PayPal') {
         $content{country} = uc country2code($content{country});
+    } elsif($argshash->{processor} eq "PayflowPro") {
+        ($content{request_id} = create_uuid_as_string(UUID_V4)) =~ s/-//;
     }
 
     %content;
@@ -249,35 +256,33 @@
     my %bop_args = get_bop_args_filler($argshash);
 
     # We're assuming that all B:OP processors accept this argument to the
-    # contstructor.
+    # constructor.
     $bop_args{test_transaction} = $argshash->{testmode};
 
     my $transaction = new Business::OnlinePayment(
         $argshash->{processor}, %bop_args
     );
 
-    $transaction->content(prepare_bop_content($argshash, $patron, $cardtype));
+    my %content = prepare_bop_content($argshash, $patron, $cardtype);
+    $transaction->content(%content);
 
-    # XXX submit() does not return a value, although crashing is possible here
+    # submit() does not return a value, although crashing is possible here
     # with some bad input depending on the payment processor.
     $transaction->submit;
 
     my $payload = {
-        "processor" => $argshash->{"processor"},
-        "card_type" => $cardtype,
-        "server_response" => $transaction->server_response
+        "processor" => $argshash->{"processor"}, "card_type" => $cardtype
     };
 
-    foreach (qw/authorization correlationid avs_code cvv2_code error_message/) {
-        # authorization should always be present for successes, and
-        # error_message should always be present for failures. The remaining
-        # field may be important in PayPal transacations? Not sure.
+    # Put the values of any of these fields into the event payload, if present.
+    foreach (qw/authorization correlationid avs_code request_id
+        server_response cvv2_response cvv2_code error_message order_number/) {
         $payload->{$_} = $transaction->$_ if $transaction->can($_);
     }
 
     my $event_name;
 
-    if ($transaction->is_success()) {
+    if ($transaction->is_success) {
         $logger->info($argshash->{processor} . " payment succeeded");
         $event_name = "SUCCESS";
     } else {

Modified: branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Circ/Holds.pm
===================================================================
--- branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Circ/Holds.pm	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Circ/Holds.pm	2010-10-18 13:46:56 UTC (rev 18371)
@@ -177,8 +177,14 @@
         return $e->event unless $e->allowed('TITLE_HOLDS',  $porg);
     } elsif ( $t eq OILS_HOLD_TYPE_VOLUME ) {
         return $e->event unless $e->allowed('VOLUME_HOLDS', $porg);
+    } elsif ( $t eq OILS_HOLD_TYPE_ISSUANCE ) {
+        return $e->event unless $e->allowed('ISSUANCE_HOLDS', $porg);
     } elsif ( $t eq OILS_HOLD_TYPE_COPY ) {
         return $e->event unless $e->allowed('COPY_HOLDS',   $porg);
+    } elsif ( $t eq OILS_HOLD_TYPE_FORCE ) {
+        return $e->event unless $e->allowed('COPY_HOLDS',   $porg);
+    } elsif ( $t eq OILS_HOLD_TYPE_RECALL ) {
+        return $e->event unless $e->allowed('COPY_HOLDS',   $porg);
     }
 
     if( @events ) {
@@ -215,58 +221,6 @@
 	return undef;
 }
 
-sub __create_hold {
-	my( $self, $client, $login_session, @holds) = @_;
-
-	if(!@holds){return 0;}
-	my( $user, $evt ) = $apputils->checkses($login_session);
-	return $evt if $evt;
-
-	my $holdsref = (ref($holds[0]) eq 'ARRAY') ? $holds[0] : [ @holds ];
-
-	$logger->debug("Iterating over " . scalar(@$holdsref) . " holds requests...");
-
-	for my $hold (@$holdsref) {
-        $hold or next;
-		my $type = $hold->hold_type;
-
-		$logger->activity("User " . $user->id . 
-			" creating new hold of type $type for user " . $hold->usr);
-
-		my $recipient;
-		if($user->id ne $hold->usr) {
-			( $recipient, $evt ) = $apputils->fetch_user($hold->usr);
-			return $evt if $evt;
-		} else {
-			$recipient = $user;
-		}
-
-		# am I allowed to place holds for this user?
-		if($hold->requestor ne $hold->usr) {
-			my $perm = _check_request_holds_perm($user->id, $user->home_ou);
-            return $perm if $perm;
-		}
-
-		# is this user allowed to have holds of this type?
-		my $perm = _check_holds_perm($type, $hold->requestor, $recipient->home_ou);
-        return $perm if $perm;
-
-		#enforce the fact that the login is the one requesting the hold
-		$hold->requestor($user->id); 
-		$hold->selection_ou($recipient->home_ou) unless $hold->selection_ou;
-
-		my $resp = $apputils->simplereq(
-			'open-ils.storage',
-			'open-ils.storage.direct.action.hold_request.create', $hold );
-
-		if(!$resp) { 
-			return OpenSRF::EX::ERROR ("Error creating hold"); 
-		}
-	}
-
-	return 1;
-}
-
 # makes sure that a user has permission to place the type of requested hold
 # returns the Perm exception if not allowed, returns undef if all is well
 sub _check_holds_perm {
@@ -1284,6 +1238,46 @@
 }
 
 __PACKAGE__->register_method(
+    method    => "print_hold_pull_list",
+    api_name  => "open-ils.circ.hold_pull_list.print",
+    signature => {
+        desc   => 'Returns an HTML-formatted holds pull list',
+        params => [
+            { desc => 'Authtoken', type => 'string'},
+            { desc => 'Org unit ID.  Optional, defaults to workstation org unit', type => 'number'},
+        ],
+        return => {
+            desc => 'HTML string',
+            type => 'string'
+        }
+    }
+);
+
+sub print_hold_pull_list {
+    my($self, $client, $auth, $org_id) = @_;
+
+    my $e = new_editor(authtoken=>$auth, xact=>1);
+    return $e->die_event unless $e->checkauth;
+
+    $org_id = (defined $org_id) ? $org_id : $e->requestor->ws_ou;
+    return $e->die_event unless $e->allowed('VIEW_HOLD', $org_id);
+
+    my $hold_ids = $U->storagereq(
+        'open-ils.storage.direct.action.hold_request.pull_list.id_list.current_copy_circ_lib.status_filtered.atomic',
+        $org_id, 10000);
+
+    return undef unless @$hold_ids;
+    $client->status(new OpenSRF::DomainObject::oilsContinueStatus);
+
+    my $holds = $e->search_action_hold_request({id => $hold_ids}, {substream => 1});
+    $client->status(new OpenSRF::DomainObject::oilsContinueStatus);
+
+    return $U->fire_object_event(undef, 'ahr.format.pull_list', $holds, $org_id);
+}
+
+
+
+__PACKAGE__->register_method(
     method        => 'fetch_hold_notify',
     api_name      => 'open-ils.circ.hold_notification.retrieve_by_hold',
     authoritative => 1,
@@ -1486,7 +1480,7 @@
 		Returns a list ids of un-fulfilled holds for a given title id
 		@param authtoken The login session key
 		@param id the id of the item whose holds we want to retrieve
-		@param type The hold type - M, T, V, C
+		@param type The hold type - M, T, I, V, C, F, R
 	/
 );
 
@@ -1699,11 +1693,12 @@
  depth        - hold range depth          (default 0)
  pickup_lib   - destination for hold, fallback value for selection_ou
  selection_ou - ID of org_unit establishing hard and soft hold boundary settings
+ issuanceid   - ID of the issuance to be held, required for Issuance level hold
  titleid      - ID (BRN) of the title to be held, required for Title level hold
  volume_id    - required for Volume level hold
  copy_id      - required for Copy level hold
  mrid         - required for Meta-record level hold
- hold_type    - T,C,V or M for Title, Copy, Volume or Meta-record  (default "T")
+ hold_type    - T, C (or R or F), I, V or M for Title, Copy, Issuance, Volume or Meta-record  (default "T")
 
 All key/value pairs are passed on to do_possibility_checks.
 
@@ -1789,6 +1784,7 @@
 sub do_possibility_checks {
     my($e, $patron, $request_lib, $depth, %params) = @_;
 
+    my $issuanceid   = $params{issuanceid}      || "";
     my $titleid      = $params{titleid}      || "";
     my $volid        = $params{volume_id};
     my $copyid       = $params{copy_id};
@@ -1802,7 +1798,7 @@
 	my $volume;
 	my $title;
 
-	if( $hold_type eq OILS_HOLD_TYPE_COPY ) {
+	if( $hold_type eq OILS_HOLD_TYPE_FORCE || $hold_type eq OILS_HOLD_TYPE_RECALL || $hold_type eq OILS_HOLD_TYPE_COPY ) {
 
         return $e->event unless $copy   = $e->retrieve_asset_copy($copyid);
         return $e->event unless $volume = $e->retrieve_asset_call_number($copy->call_number);
@@ -1827,6 +1823,12 @@
 			$titleid, $depth, $request_lib, $patron, $e->requestor, $pickup_lib, $selection_ou
         );
 
+	} elsif( $hold_type eq OILS_HOLD_TYPE_ISSUANCE ) {
+
+		return _check_issuance_hold_is_possible(
+			$issuanceid, $depth, $request_lib, $patron, $e->requestor, $pickup_lib, $selection_ou
+        );
+
 	} elsif( $hold_type eq OILS_HOLD_TYPE_METARECORD ) {
 
 		my $maps = $e->search_metabib_metarecord_source_map({metarecord=>$mrid});
@@ -1976,7 +1978,7 @@
 
          unless($title) { # grab the title if we don't already have it
             my $vol = $e->retrieve_asset_call_number(
-               [ $copy->call_number, { flesh => 1, flesh_fields => { acn => ['record'] } } ] );
+               [ $copy->call_number, { flesh => 1, flesh_fields => { bre => ['fixed_fields'], acn => ['record'] } } ] );
             $title = $vol->record;
          }
    
@@ -1990,7 +1992,141 @@
     return @status;
 }
 
+sub _check_issuance_hold_is_possible {
+    my( $issuanceid, $depth, $request_lib, $patron, $requestor, $pickup_lib, $selection_ou ) = @_;
+   
+    my $e = new_editor();
+    my %org_filter = create_ranged_org_filter($e, $selection_ou, $depth);
 
+    # this monster will grab the id and circ_lib of all of the "holdable" copies for the given record
+    my $copies = $e->json_query(
+        { 
+            select => { acp => ['id', 'circ_lib'] },
+              from => {
+                acp => {
+                    sitem => {
+                        field  => 'unit',
+                        fkey   => 'id',
+                        filter => { issuance => $issuanceid }
+                    },
+                    acpl => { field => 'id', filter => { holdable => 't'}, fkey => 'location' },
+                    ccs  => { field => 'id', filter => { holdable => 't'}, fkey => 'status'   }
+                }
+            }, 
+            where => {
+                '+acp' => { circulate => 't', deleted => 'f', holdable => 't', %org_filter }
+            },
+            distinct => 1
+        }
+    );
+
+    $logger->info("issuance possible found ".scalar(@$copies)." potential copies");
+
+    my $empty_ok;
+    if (!@$copies) {
+        $empty_ok = $e->retrieve_config_global_flag('circ.holds.empty_issuance_ok');
+        $empty_ok = ($empty_ok and $U->is_true($empty_ok->enabled));
+
+        return (
+            0, 0, [
+                new OpenILS::Event(
+                    "HIGH_LEVEL_HOLD_HAS_NO_COPIES",
+                    "payload" => {"fail_part" => "no_ultimate_items"}
+                )
+            ]
+        ) unless $empty_ok;
+
+        return (1, 0);
+    }
+
+    # -----------------------------------------------------------------------
+    # sort the copies into buckets based on their circ_lib proximity to 
+    # the patron's home_ou.  
+    # -----------------------------------------------------------------------
+
+    my $home_org = $patron->home_ou;
+    my $req_org = $request_lib->id;
+
+    $logger->info("prox cache $home_org " . $prox_cache{$home_org});
+
+    $prox_cache{$home_org} = 
+        $e->search_actor_org_unit_proximity({from_org => $home_org})
+        unless $prox_cache{$home_org};
+    my $home_prox = $prox_cache{$home_org};
+
+    my %buckets;
+    my %hash = map { ($_->to_org => $_->prox) } @$home_prox;
+    push( @{$buckets{ $hash{$_->{circ_lib}} } }, $_->{id} ) for @$copies;
+
+    my @keys = sort { $a <=> $b } keys %buckets;
+
+
+    if( $home_org ne $req_org ) {
+      # -----------------------------------------------------------------------
+      # shove the copies close to the request_lib into the primary buckets 
+      # directly before the farthest away copies.  That way, they are not 
+      # given priority, but they are checked before the farthest copies.
+      # -----------------------------------------------------------------------
+        $prox_cache{$req_org} = 
+            $e->search_actor_org_unit_proximity({from_org => $req_org})
+            unless $prox_cache{$req_org};
+        my $req_prox = $prox_cache{$req_org};
+
+        my %buckets2;
+        my %hash2 = map { ($_->to_org => $_->prox) } @$req_prox;
+        push( @{$buckets2{ $hash2{$_->{circ_lib}} } }, $_->{id} ) for @$copies;
+
+        my $highest_key = $keys[@keys - 1];  # the farthest prox in the exising buckets
+        my $new_key = $highest_key - 0.5; # right before the farthest prox
+        my @keys2   = sort { $a <=> $b } keys %buckets2;
+        for my $key (@keys2) {
+            last if $key >= $highest_key;
+            push( @{$buckets{$new_key}}, $_ ) for @{$buckets2{$key}};
+        }
+    }
+
+    @keys = sort { $a <=> $b } keys %buckets;
+
+    my $title;
+    my %seen;
+    my @status;
+    OUTER: for my $key (@keys) {
+      my @cps = @{$buckets{$key}};
+
+      $logger->info("looking at " . scalar(@{$buckets{$key}}). " copies in proximity bucket $key");
+
+      for my $copyid (@cps) {
+
+         next if $seen{$copyid};
+         $seen{$copyid} = 1; # there could be dupes given the merged buckets
+         my $copy = $e->retrieve_asset_copy($copyid);
+         $logger->debug("looking at bucket_key=$key, copy $copyid : circ_lib = " . $copy->circ_lib);
+
+         unless($title) { # grab the title if we don't already have it
+            my $vol = $e->retrieve_asset_call_number(
+               [ $copy->call_number, { flesh => 1, flesh_fields => { bre => ['fixed_fields'], acn => ['record'] } } ] );
+            $title = $vol->record;
+         }
+   
+         @status = verify_copy_for_hold(
+            $patron, $requestor, $title, $copy, $pickup_lib, $request_lib);
+
+         last OUTER if $status[0];
+      }
+    }
+
+    if (!$status[0]) {
+        if (!defined($empty_ok)) {
+            $empty_ok = $e->retrieve_config_global_flag('circ.holds.empty_issuance_ok');
+            $empty_ok = ($empty_ok and $U->is_true($empty_ok->enabled));
+        }
+
+        return (1,0) if ($empty_ok);
+    }
+    return @status;
+}
+
+
 sub _check_volume_hold_is_possible {
 	my( $vol, $title, $depth, $request_lib, $patron, $requestor, $pickup_lib, $selection_ou ) = @_;
     my %org_filter = create_ranged_org_filter(new_editor(), $selection_ou, $depth);
@@ -2327,6 +2463,7 @@
 	my $tid;
 	my $copy;
 	my $volume;
+    my $issuance;
 
 	if( $hold->hold_type eq OILS_HOLD_TYPE_METARECORD ) {
 		my $mr = $e->retrieve_metabib_metarecord($hold->target)
@@ -2341,11 +2478,21 @@
 			or return $e->event;
 		$tid = $volume->record;
 
+    } elsif( $hold->hold_type eq OILS_HOLD_TYPE_ISSUANCE ) {
+        $issuance = $e->retrieve_serial_issuance([
+            $hold->target,
+            {flesh => 1, flesh_fields => {siss => [ qw/subscription/ ]}}
+        ]) or return $e->event;
+
+        $tid = $issuance->subscription->record_entry;
+
 	} elsif( $hold->hold_type eq OILS_HOLD_TYPE_COPY ) {
-		$copy = $e->retrieve_asset_copy($hold->target)
-			or return $e->event;
-		$volume = $e->retrieve_asset_call_number($copy->call_number)
-			or return $e->event;
+		$copy = $e->retrieve_asset_copy([
+            $hold->target, 
+            {flesh => 1, flesh_fields => {acp => ['call_number']}}
+        ]) or return $e->event;
+        
+		$volume = $copy->call_number;
 		$tid = $volume->record;
 	}
 
@@ -2360,7 +2507,7 @@
 
     # TODO return metarcord mvr for M holds
 	my $title = $e->retrieve_biblio_record_entry($tid);
-	return ( $U->record_to_mvr($title), $volume, $copy );
+	return ( $U->record_to_mvr($title), $volume, $copy, $issuance );
 }
 
 
@@ -2638,14 +2785,22 @@
         limit => 1
     };
 
-    if($hold_type eq 'C') {
+    if($hold_type eq 'C' || $hold_type eq 'R' || $hold_type eq 'F') {
 
         $query->{where}->{'+acp'}->{id}->{in}->{where}->{'target_copy'} = $hold_target;
 
     } elsif($hold_type eq 'V') {
 
         $query->{where}->{'+acp'}->{call_number} = $hold_target;
-    
+
+     } elsif($hold_type eq 'I') {
+
+        $query->{from}->{acp}->{sitem} = {
+            field  => 'unit',
+            fkey   => 'id',
+            filter => {issuance => $hold_target},
+        };
+
     } elsif($hold_type eq 'T') {
 
         $query->{from}->{acp}->{acn} = {

Modified: branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Fielder.pm
===================================================================
--- branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Fielder.pm	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Fielder.pm	2010-10-18 13:46:56 UTC (rev 18371)
@@ -9,6 +9,7 @@
 
 use OpenSRF::AppSession;
 use OpenSRF::Utils::SettingsClient;
+use OpenSRF::Utils::Cache;
 use OpenSRF::Utils::Logger qw/:level/;
 
 use OpenILS::Utils::Fieldmapper;
@@ -16,6 +17,8 @@
 
 use OpenILS::Utils::CStoreEditor qw/:funcs/;
 
+use Digest::MD5 qw(md5_hex);
+
 use XML::LibXML;
 use XML::LibXML::XPathContext;
 use XML::LibXSLT;
@@ -31,6 +34,8 @@
 
 my $log = 'OpenSRF::Utils::Logger';
 
+my $cache;
+my $cache_timeout;
 my $parser = XML::LibXML->new();
 my $xslt = XML::LibXSLT->new();
 
@@ -48,10 +53,15 @@
 
     $log->debug( 'IDL XML file loaded' );
 
+    $cache_timeout = $conf->config_value(
+            "apps", "open-ils.fielder", "app_settings", "cache_timeout" ) || 300;
+
     generate_methods();
 
 }
-sub child_init {}
+sub child_init {
+    $cache = OpenSRF::Utils::Cache->new('global');
+}
 
 sub fielder_fetch {
     my $self = shift;
@@ -59,9 +69,12 @@
     my $obj = shift;
 
     my $query = $obj->{query};
+    my $nocache = $obj->{cache} ? 0 : 1;
     my $fields = $obj->{fields};
     my $distinct = $obj->{distinct} ? 1 : 0;
 
+    return undef unless $query;
+
     my $obj_class = $self->{class_hint};
     my $fm_class = $self->{class_name};
 
@@ -69,18 +82,34 @@
         $fields = [ $fm_class->real_fields ];
     }
 
-    $log->debug( 'Field list: '. OpenSRF::Utils::JSON->perl2JSON( $fields ) );
-    $log->debug( 'Query: '. OpenSRF::Utils::JSON->perl2JSON( $query ) );
-
-    return undef unless $fields;
-    return undef unless $query;
-
     $fields = [$fields] if (!ref($fields));
 
+    my $qstring = OpenSRF::Utils::JSON->perl2JSON( $query );
+    my $fstring = OpenSRF::Utils::JSON->perl2JSON( [ sort { $a cmp $b } @$fields ] );
 
     $log->debug( 'Query Class: '. $obj_class );
+    $log->debug( 'Field list: '. $fstring );
+    $log->debug( 'Query: '. $qstring );
 
-    my $res = new_editor()->json_query({
+    my ($key,$res);
+    unless ($nocache) {
+        $key = 'open-ils.fielder_' . md5_hex(
+            $self->api_name . 
+            $qstring .
+            $fstring .
+            $distinct .
+            $obj_class
+        );
+
+        $res = $cache->get_cache( $key );
+
+        if ($res) {
+            $client->respond($_) for (@$res);
+            return undef;
+        }
+    }
+
+    $res = new_editor()->json_query({
         select  => { $obj_class => $fields },
         from    => $obj_class,
         where   => $query,
@@ -91,8 +120,10 @@
         $client->respond($value);
     }
 
+    $client->respond_complete();
+
+    $cache->put_cache( $key => $res => $cache_timeout ) unless ($nocache);
     return undef;
-
 }
 
 sub generate_methods {

Modified: branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Search/Biblio.pm
===================================================================
--- branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Search/Biblio.pm	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Search/Biblio.pm	2010-10-18 13:46:56 UTC (rev 18371)
@@ -260,7 +260,7 @@
     return [] unless $record_id;
 
     my $key = $self->api_name =~ /metarecord/ ? 'metarecord' : 'record';
-    my $staff =~ $self->api_name =~ /staff/ ? 't' : 'f';
+    my $staff = $self->api_name =~ /staff/ ? 't' : 'f';
 
     my $data = $U->cstorereq(
         "open-ils.cstore.json_query.atomic",
@@ -689,12 +689,13 @@
     $query =~ s/^\s+//go;
 
     # convert convenience classes (e.g. kw for keyword) to the full class name
-    $query =~ s/kw(:|\|)/keyword$1/go;
-    $query =~ s/ti(:|\|)/title$1/go;
-    $query =~ s/au(:|\|)/author$1/go;
-    $query =~ s/su(:|\|)/subject$1/go;
-    $query =~ s/se(:|\|)/series$1/go;
-    $query =~ s/name(:|\|)/author$1/og;
+    # ensure that the convenience class isn't part of a word (e.g. 'playhouse')
+    $query =~ s/(^|\s)kw(:|\|)/$1keyword$2/go;
+    $query =~ s/(^|\s)ti(:|\|)/$1title$2/go;
+    $query =~ s/(^|\s)au(:|\|)/$1author$2/go;
+    $query =~ s/(^|\s)su(:|\|)/$1subject$2/go;
+    $query =~ s/(^|\s)se(:|\|)/$1series$2/go;
+    $query =~ s/(^|\s)name(:|\|)/$1author$2/og;
 
     $logger->debug("cleansed query string => $query");
     my $search = {};
@@ -789,8 +790,10 @@
         if $sclient->config_value(apps => 'open-ils.search',
             app_settings => 'use_staged_search') =~ /true/i;
 
-    $arghash->{preferred_language} = $U->get_org_locale($arghash->{org_unit})
-        unless $arghash->{preferred_language};
+    # XXX This stops the session locale from doing the right thing.
+    # XXX Revisit this and have it translate to a lang instead of a locale.
+    #$arghash->{preferred_language} = $U->get_org_locale($arghash->{org_unit})
+    #    unless $arghash->{preferred_language};
 
 	$method = $self->method_lookup($method);
     my ($data) = $method->run($arghash, $docache);
@@ -1316,10 +1319,28 @@
     my $self   = shift;
     my $client = shift;
     my $key    = shift;
+    my $limit    = shift;
 
     return undef unless ($key and $key =~ /_facets$/);
 
-    return $cache->get_cache($key) || {};
+    my $blob = $cache->get_cache($key) || {};
+
+    my $facets = {};
+    if ($limit) {
+       for my $f ( keys %$blob ) {
+            my @sorted = map{ { $$_[1] => $$_[0] } } sort {$$b[0] <=> $$a[0] || $$a[1] cmp $$b[1]} map { [$$blob{$f}{$_}, $_] } keys %{ $$blob{$f} };
+            @sorted = @sorted[0 .. $limit - 1] if (scalar(@sorted) > $limit);
+            for my $s ( @sorted ) {
+                my ($k) = keys(%$s);
+                my ($v) = values(%$s);
+                $$facets{$f}{$k} = $v;
+            }
+        }
+    } else {
+        $facets = $blob;
+    }
+
+    return $facets;
 }
 
 __PACKAGE__->register_method(

Modified: branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Search/Serial.pm
===================================================================
--- branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Search/Serial.pm	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Search/Serial.pm	2010-10-18 13:46:56 UTC (rev 18371)
@@ -112,7 +112,7 @@
 sub bib_to_svr {
 	my ($self, $client, $bib) = @_;
 	
-	my $svrs;
+	my $svrs = [];
 
 	my $e = OpenILS::Utils::CStoreEditor->new();
     # TODO: 'deleted' ssub support

Modified: branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Serial.pm
===================================================================
--- branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Serial.pm	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Serial.pm	2010-10-18 13:46:56 UTC (rev 18371)
@@ -37,13 +37,16 @@
 use strict;
 use warnings;
 
+
 use OpenILS::Application;
 use base qw/OpenILS::Application/;
 use OpenILS::Application::AppUtils;
+use OpenILS::Event;
 use OpenSRF::AppSession;
-use OpenSRF::Utils qw/:datetime/;;
-use OpenSRF::Utils::Logger qw($logger);
+use OpenSRF::Utils qw/:datetime/;
+use OpenSRF::Utils::Logger qw/:logger/;
 use OpenILS::Utils::CStoreEditor q/:funcs/;
+use OpenILS::Utils::Fieldmapper;
 use OpenILS::Utils::MFHD;
 use MARC::File::XML (BinaryEncoding => 'utf8');
 my $U = 'OpenILS::Application::AppUtils';
@@ -57,8 +60,8 @@
 my %MFHD_TAGS_BY_NAME = (  $MFHD_NAMES[0] => '853',
                         $MFHD_NAMES[1] => '854',
                         $MFHD_NAMES[2] => '855');
+my $_strp_date = new DateTime::Format::Strptime(pattern => '%F');
 
-
 # helper method for conforming dates to ISO8601
 sub _cleanse_dates {
     my $item = shift;
@@ -70,7 +73,15 @@
     return 0;
 }
 
+sub _get_mvr {
+    $U->simplereq(
+        "open-ils.search",
+        "open-ils.search.biblio.record.mods_slim.retrieve",
+        @_
+    );
+}
 
+
 ##########################################################################
 # item methods
 #
@@ -310,7 +321,182 @@
         });
 }
 
+__PACKAGE__->register_method(
+    method  => "pub_fleshed_serial_issuance_retrieve_batch",
+    api_name    => "open-ils.serial.issuance.pub_fleshed.batch.retrieve",
+    signature => {
+        desc => q/
+            Public (i.e. OPAC) call for getting at the sub and 
+            ultimately the record entry from an issuance
+        /,
+        params => [{name => 'ids', desc => 'Array of IDs', type => 'array'}],
+        return => {
+            desc => q/
+                issuance objects, fleshed with subscriptions
+            /,
+            class => 'siss'
+        }
+    }
+);
+sub pub_fleshed_serial_issuance_retrieve_batch {
+    my( $self, $client, $ids ) = @_;
+    return [] unless $ids and @$ids;
+    return new_editor()->search_serial_issuance([
+        { id => $ids },
+        { 
+            flesh => 1,
+            flesh_fields => {siss => [ qw/subscription/ ]}
+        }
+    ]);
+}
 
+sub received_siss_by_bib {
+    my $self = shift;
+    my $client = shift;
+    my $bib = shift;
+
+    my $args = shift || {};
+    $$args{order} ||= 'asc';
+
+    my $global = $$args{global} == 0 ? 0 : 1;
+
+    my $e = new_editor();
+    my $issuances = $e->json_query({
+        select  => {
+            siss => [
+                $global ? { transform => "min", column => "id", aggregate => 1 } : "id",
+                "label",
+                "date_published"
+        ]},
+        from => {
+            ssub => {
+                siss => {
+                    field => 'subscription',
+                    fkey  => 'id',
+                    join  => {
+                        sitem => {
+                            field  => 'issuance',
+                            fkey   => 'id',
+                            $$args{ou} ? ( join  => {
+                                sstr => {
+                                    field => 'id',
+                                    fkey  => 'stream',
+                                    join  => {
+                                        sdist => {
+                                            field  => 'id',
+                                            fkey   => 'distribution'
+                                        }
+                                    }
+                                }
+                            }) : ()
+                        }
+                    }
+                }
+            }
+        },
+        where => {
+            '+ssub'  => { record_entry => $bib },
+            $$args{type} ? ( '+siss' => { 'holding_type' => $$args{type} } ) : (),
+            '+sitem' => {
+                # XXX should we also take specific item statuses into account?
+                date_received => { '!=' => undef },
+                $$args{status} ? ( 'status' => $$args{status} ) : ()
+            },
+            $$args{ou} ? ( '+sdist' => {
+                holding_lib => {
+                    'in' => $U->get_org_descendants($$args{ou}, $$args{depth})
+                }
+            }) : ()
+        },
+        $$args{limit}  ? ( limit  => $$args{limit}  ) : (),
+        $$args{offset} ? ( offset => $$args{offset} ) : (),
+        order_by => [{ class => 'siss', field => 'date_published', direction => $$args{order} }],
+        distinct => 1
+    });
+
+    $client->respond($e->retrieve_serial_issuance($_->{id})) for @$issuances;
+    return undef;
+}
+__PACKAGE__->register_method(
+    method    => 'received_siss_by_bib',
+    api_name  => 'open-ils.serial.received_siss.retrieve.by_bib',
+    api_level => 1,
+    argc      => 1,
+    stream    => 1,
+    signature => {
+        desc   => 'Receives a Bib ID and other optional params and returns "siss" (issuance) objects',
+        params => [
+            {   name => 'bibid',
+                desc => 'id of the bre to which the issuances belong',
+                type => 'number'
+            },
+            {   name => 'args',
+                desc =>
+q/A hash of optional arguments.  Valid keys and their meanings:
+    global := If true, return only one representative version of a conceptual issuance regardless of the number of subscriptions, otherwise return all issuance objects meeting the requested criteria, including conceptual duplicates. Valid values are 0 (false) and 1 (true, default).
+    order  := date_published sort direction, either "asc" (chronological, default) or "desc" (reverse chronological)
+    limit  := Number of issuances to return.  Useful for paging results, or finding the oldest or newest
+    offest := Number of issuance to skip before returning results.  Useful for paging.
+    orgid  := OU id used to scope retrieval, based on distribution.holding_lib
+    depth  := OU depth used to range the scope of orgid
+    type   := Holding type filter. Valid values are "basic", "supplement" and "index". Can be a scalar (one) or arrayref (one or more).
+    status := Item status filter. Valid values are "Bindery", "Bound", "Claimed", "Discarded", "Expected", "Not Held", "Not Published" and "Received". Can be a scalar (one) or arrayref (one or more).
+/
+            }
+        ]
+    }
+);
+
+
+sub scoped_bib_holdings_summary {
+    my $self = shift;
+    my $client = shift;
+    my $bibid = shift;
+    my $args = shift || {};
+
+    $args->{order} = 'asc';
+
+    my ($issuances) = $self->method_lookup('open-ils.serial.received_siss.retrieve.by_bib.atomic')->run( $bibid => $args );
+
+    # split into issuance type sets
+    my %type_blob = (basic => [], supplement => [], index => []);
+    push @{ $type_blob{ $_->holding_type } }, $_ for (@$issuances);
+
+    # generate a statement list for each type
+    my %statement_blob;
+    for my $type ( keys %type_blob ) {
+        my ($mfhd,$list) = _summarize_contents(new_editor(), $type_blob{$type});
+        $statement_blob{$type} = $list;
+    }
+
+    return \%statement_blob;
+}
+__PACKAGE__->register_method(
+    method    => 'scoped_bib_holdings_summary',
+    api_name  => 'open-ils.serial.bib.summary_statements',
+    api_level => 1,
+    argc      => 1,
+    signature => {
+        desc   => 'Receives a Bib ID and other optional params and returns set of holdings statements',
+        params => [
+            {   name => 'bibid',
+                desc => 'id of the bre to which the issuances belong',
+                type => 'number'
+            },
+            {   name => 'args',
+                desc =>
+q/A hash of optional arguments.  Valid keys and their meanings:
+    orgid  := OU id used to scope retrieval, based on distribution.holding_lib
+    depth  := OU depth used to range the scope of orgid
+    type   := Holding type filter. Valid values are "basic", "supplement" and "index". Can be a scalar (one) or arrayref (one or more).
+    status := Item status filter. Valid values are "Bindery", "Bound", "Claimed", "Discarded", "Expected", "Not Held", "Not Published" and "Received". Can be a scalar (one) or arrayref (one or more).
+/
+            }
+        ]
+    }
+);
+
+
 ##########################################################################
 # unit methods
 #
@@ -482,13 +668,39 @@
 
     my $editor = OpenILS::Utils::CStoreEditor->new();
     my $ssub_id = $args->{ssub_id};
+    my $all_dists = $args->{all_dists};
     my $mfhd = MFHD->new(MARC::Record->new());
 
     my $ssub = $editor->retrieve_serial_subscription([$ssub_id]);
     my $scaps = $editor->search_serial_caption_and_pattern({ subscription => $ssub_id, active => 't'});
     my $sdists = $editor->search_serial_distribution( [{ subscription => $ssub->id }, {  flesh => 1,
-              flesh_fields => {sdist => [ qw/ streams / ]}, limit => 1 }] ); #TODO: 'deleted' support?
+              flesh_fields => {sdist => [ qw/ streams / ]}, $all_dists ? () : (limit => 1) }] ); #TODO: 'deleted' support?
 
+    if ($all_dists) {
+        my $total_streams = 0;
+        foreach (@$sdists) {
+            $total_streams += scalar(@{$_->streams});
+        }
+        if ($total_streams < 1) {
+            $editor->disconnect;
+            # XXX TODO new event type
+            return new OpenILS::Event(
+                "BAD_PARAMS", note =>
+                    "There are no streams to direct items. Can't predict."
+            );
+        }
+    }
+
+    unless (@$scaps) {
+        $editor->disconnect;
+        # XXX TODO new event type
+        return new OpenILS::Event(
+            "BAD_PARAMS", note =>
+                "There are no active caption-and-pattern objects associated " .
+                "with this subscription. Can't predict."
+        );
+    }
+
     my @predictions;
     my $link_id = 1;
     foreach my $scap (@$scaps) {
@@ -498,7 +710,9 @@
         my $options = {
                 'caption' => $caption_field,
                 'scap_id' => $scap->id,
-                'num_to_predict' => $args->{num_to_predict}
+                'num_to_predict' => $args->{num_to_predict},
+                'end_date' => defined $args->{end_date} ?
+                    $_strp_date->parse_datetime($args->{end_date}) : undef
                 };
         if ($args->{base_issuance}) { # predict from a given issuance
             $options->{predict_from} = _revive_holding($args->{base_issuance}->holding_code, $caption_field, 1); # fresh MFHD Record, so we simply default to 1 for seqno
@@ -510,9 +724,21 @@
                 );
             if ($last_published->[0]) {
                 my $last_siss = $last_published->[0];
+                unless ($last_siss->holding_code) {
+                    $editor->disconnect;
+                    # XXX TODO new event type
+                    return new OpenILS::Event(
+                        "BAD_PARAMS", note =>
+                            "Last issuance has no holding code. Can't predict."
+                    );
+                }
                 $options->{predict_from} = _revive_holding($last_siss->holding_code, $caption_field, 1);
             } else {
-                #TODO: throw event (can't predict from nothing!)
+                $editor->disconnect;
+                # XXX TODO make a new event type instead of hijacking this one
+                return new OpenILS::Event(
+                    "BAD_PARAMS", note => "No issuance from which to predict!"
+                );
             }
         }
         push( @predictions, _generate_issuance_values($mfhd, $options) );
@@ -577,6 +803,7 @@
     my $caption = $options->{caption};
     my $scap_id = $options->{scap_id};
     my $num_to_predict = $options->{num_to_predict};
+    my $end_date = $options->{end_date};
     my $predict_from = $options->{predict_from};   # issuance to predict from
     #my $last_rec_date = $options->{last_rec_date};   # expected or actual
 
@@ -603,12 +830,11 @@
 # add a note marker for system use (?)
     $predict_from->notes('private', ['AUTOGEN']);
 
-    my $strp = new DateTime::Format::Strptime(pattern => '%F');
     my $pub_date;
     my @issuance_values;
-    my @predictions = $mfhd->generate_predictions({'base_holding' => $predict_from, 'num_to_predict' => $num_to_predict});
+    my @predictions = $mfhd->generate_predictions({'base_holding' => $predict_from, 'num_to_predict' => $num_to_predict, 'end_date' => $end_date});
     foreach my $prediction (@predictions) {
-        $pub_date = $strp->parse_datetime($prediction->chron_to_date);
+        $pub_date = $_strp_date->parse_datetime($prediction->chron_to_date);
         push(
                 @issuance_values,
                 {
@@ -867,13 +1093,285 @@
     return {'num_items_received' => scalar @$items, 'new_unit_id' => $new_unit_id};
 }
 
+sub _find_or_create_call_number {
+    my ($e, $lib, $cn_string, $record) = @_;
+
+    my $existing = $e->search_asset_call_number({
+        "owning_lib" => $lib,
+        "label" => $cn_string,
+        "record" => $record,
+        "deleted" => "f"
+    }) or return $e->die_event;
+
+    if (@$existing) {
+        return $existing->[0]->id;
+    } else {
+        return $e->die_event unless
+            $e->allowed("CREATE_VOLUME", $lib);
+
+        my $acn = new Fieldmapper::asset::call_number;
+
+        $acn->creator($e->requestor->id);
+        $acn->editor($e->requestor->id);
+        $acn->record($record);
+        $acn->label($cn_string);
+        $acn->owning_lib($lib);
+
+        $e->create_asset_call_number($acn) or return $e->die_event;
+        return $e->data->id;
+    }
+}
+
+sub _issuances_received {
+    my ($e, $sitem) = @_;
+
+    my $results = $e->json_query({
+        "select" => {
+            "sitem" => [
+                {"transform" => "distinct", "column" => "issuance"}
+            ]
+        },
+        "from" => {"sitem" => {"sstr" => {}, "siss" => {}}},
+        "where" => {
+            "+sstr" => {"distribution" => $sitem->stream->distribution->id},
+            "+siss" => {"holding_type" => $sitem->issuance->holding_type},
+            "+sitem" => {"date_received" => {"!=" => undef}}
+        }
+    }) or return $e->die_event;
+
+    return [ map { $e->retrieve_serial_issuance($_->{"issuance"}) } @$results ];
+}
+
+# XXX _prepare_unit_label() duplicates some code from unitize_items().
+# Hopefully we can unify code paths down the road.
+sub _prepare_unit_label {
+    my ($e, $sunit, $sdist, $issuance) = @_;
+
+    my ($mfhd, $formatted_parts) = _summarize_contents($e, [$issuance]);
+
+    # special case for single formatted_part (may have summarized version)
+    if (@$formatted_parts == 1) {
+        #TODO: MFHD.pm should have a 'format_summary' method for this
+    }
+
+    $sunit->detailed_contents(
+        join(
+            " ",
+            $sdist->unit_label_prefix,
+            join(", ", @$formatted_parts),
+            $sdist->unit_label_suffix
+        )
+    );
+
+    # TODO: change this when real summary contents are available
+    $sunit->summary_contents($sunit->detailed_contents);
+
+    # Create sort_key by left padding numbers to 6 digits.
+    (my $sort_key = $sunit->detailed_contents) =~
+        s/(\d+)/sprintf '%06d', $1/eg;
+    $sunit->sort_key($sort_key);
+}
+
+# XXX duplicates a block of code from unitize_items().  Once I fully understand
+# what's going on and I'm sure it's working right, I'd like to have
+# unitize_items() just use this, keeping the logic in one place.
+sub _prepare_summaries {
+    my ($e, $sitem, $issuances) = @_;
+
+    my $dist_id = $sitem->stream->distribution->id;
+    my $type = $sitem->issuance->holding_type;
+
+    # Make sure @$issuances contains the new issuance from sitem.
+    unless (grep { $_->id == $sitem->issuance->id } @$issuances) {
+        push @$issuances, $sitem->issuance;
+    }
+
+    my ($mfhd, $formatted_parts) = _summarize_contents($e, $issuances);
+
+    my $search_method = "search_serial_${type}_summary";
+    my $summary = $e->$search_method([{"distribution" => $dist_id}]);
+
+    my $cu_method = "update";
+
+    if (@$summary) {
+        $summary = $summary->[0];
+    } else {
+        my $class = "Fieldmapper::serial::${type}_summary";
+        $summary = $class->new;
+        $summary->distribution($dist_id);
+        $cu_method = "create";
+    }
+
+    $summary->generated_coverage(join(", ", @$formatted_parts));
+    my $method = "${cu_method}_serial_${type}_summary";
+    return $e->die_event unless $e->$method($summary);
+}
+
+__PACKAGE__->register_method(
+    "method" => "receive_items_one_unit_per",
+    "api_name" => "open-ils.serial.receive_items.one_unit_per",
+    "stream" => 1,
+    "api_level" => 1,
+    "argc" => 3,
+    "signature" => {
+        "desc" => "Marks items in a list as received, creates a new unit for each item if any unit is fleshed on, and updates summaries as needed",
+        "params" => [
+            {
+                 "name" => "auth",
+                 "desc" => "authtoken",
+                 "type" => "string"
+            },
+            {
+                 "name" => "items",
+                 "desc" => "array of serial items, possibly fleshed with units and definitely fleshed with stream->distribution",
+                 "type" => "array"
+            },
+            {
+                "name" => "record",
+                "desc" => "id of bib record these items are associated with
+                    (XXX could/should be derived from items)",
+                "type" => "number"
+            }
+        ],
+        "return" => {
+            "desc" => "The item ID for each item successfully received",
+            "type" => "int"
+        }
+    }
+);
+
+sub receive_items_one_unit_per {
+    # XXX This function may be temporary, as it does some of what
+    # unitize_items() does, just in a different way.
+    my ($self, $client, $auth, $items, $record) = @_;
+
+    my $e = new_editor("authtoken" => $auth, "xact" => 1);
+    return $e->die_event unless $e->checkauth;
+    return $e->die_event unless $e->allowed("RECEIVE_SERIAL");
+
+    my $user_id = $e->requestor->id;
+
+    # Get a list of all the non-virtual field names in a serial::unit for
+    # merging given unit objects with template-built units later.
+    # XXX move this somewhere global so it isn't re-run all the time
+    my $all_unit_fields =
+        $Fieldmapper::fieldmap->{"Fieldmapper::serial::unit"}->{"fields"};
+    my @real_unit_fields = grep {
+        not $all_unit_fields->{$_}->{"virtual"}
+    } keys %$all_unit_fields;
+
+    foreach my $item (@$items) {
+        # Note that we expect a certain fleshing on the items we're getting.
+        my $sdist = $item->stream->distribution;
+
+        # Create unit if given by user
+        if (ref $item->unit) {
+            # detach from the item, as we need to create separately
+            my $user_unit = $item->unit;
+
+            # get a unit based on associated template
+            my $template_unit = _build_unit($e, $sdist, "receive", 1);
+            if ($U->event_code($template_unit)) {
+                $e->rollback;
+                $template_unit->{"note"} = "Item ID: " . $item->id;
+                return $template_unit;
+            }
+
+            # merge built unit with provided unit from user
+            foreach (@real_unit_fields) {
+                unless ($user_unit->$_) {
+                    $user_unit->$_($template_unit->$_);
+                }
+            }
+
+            # Treat call number specially: the provided value from the
+            # user will really be a string.
+            if ($user_unit->call_number) {
+                my $real_cn = _find_or_create_call_number(
+                    $e, $sdist->holding_lib->id,
+                    $user_unit->call_number, $record
+                );
+
+                if ($U->event_code($real_cn)) {
+                    $e->rollback;
+                    return $real_cn;
+                } else {
+                    $user_unit->call_number($real_cn);
+                }
+            }
+
+            my $evt = _prepare_unit_label(
+                $e, $user_unit, $sdist, $item->issuance
+            );
+            if ($U->event_code($evt)) {
+                $e->rollback;
+                return $evt;
+            }
+
+            # fetch a list of issuances with received copies already existing
+            # on this distribution.
+            my $issuances = _issuances_received($e, $item); #XXX optimize later
+            if ($U->event_code($issuances)) {
+                $e->rollback;
+                return $issuances;
+            }
+
+            # create/update summary objects related to this distribution
+            $evt = _prepare_summaries($e, $item, $issuances);
+            if ($U->event_code($evt)) {
+                $e->rollback;
+                return $evt;
+            }
+
+            # set the incontrovertibles on the unit
+            $user_unit->edit_date("now");
+            $user_unit->create_date("now");
+            $user_unit->editor($user_id);
+            $user_unit->creator($user_id);
+
+            return $e->die_event unless $e->create_serial_unit($user_unit);
+
+            # save reference to new unit
+            $item->unit($e->data->id);
+        }
+
+        # Create notes if given by user
+        if (ref($item->notes) and @{$item->notes}) {
+            foreach my $note (@{$item->notes}) {
+                $note->creator($user_id);
+                $note->create_date("now");
+
+                return $e->die_event unless $e->create_serial_item_note($note);
+            }
+
+            $item->clear_notes; # They're saved; we no longer want them here.
+        }
+
+        # Set the incontrovertibles on the item
+        $item->status("Received");
+        $item->date_received("now");
+        $item->edit_date("now");
+        $item->editor($user_id);
+
+        return $e->die_event unless $e->update_serial_item($item);
+
+        # send client a response
+        $client->respond($item->id);
+    }
+
+    $e->commit or return $e->die_event;
+    undef;
+}
+
 sub _build_unit {
     my $editor = shift;
     my $sdist = shift;
     my $mode = shift;
+    my $skip_call_number = shift;
 
     my $attr = $mode . '_unit_template';
-    my $template = $editor->retrieve_asset_copy_template($sdist->$attr);
+    my $template = $editor->retrieve_asset_copy_template($sdist->$attr) or
+        return new OpenILS::Event("SERIAL_DISTRIBUTION_HAS_NO_COPY_TEMPLATE");
 
     my @parts = qw( status location loan_duration fine_level age_protect circulate deposit ref holdable deposit_amount price circ_modifier circ_as_type alert_message opac_visible floating mint_condition );
 
@@ -888,8 +1386,15 @@
     $unit->circ_lib($sdist->holding_lib);
     $unit->creator($editor->requestor->id);
     $unit->editor($editor->requestor->id);
-    $attr = $mode . '_call_number';
-    $unit->call_number($sdist->$attr);
+
+    unless ($skip_call_number) {
+        $attr = $mode . '_call_number';
+        my $cn = $sdist->$attr or
+            return new OpenILS::Event("SERIAL_DISTRIBUTION_HAS_NO_CALL_NUMBER");
+
+        $unit->call_number($cn);
+    }
+
     $unit->barcode('AUTO');
     $unit->sort_key('');
     $unit->summary_contents('');
@@ -1604,4 +2109,221 @@
     );
 }
 
+__PACKAGE__->register_method(
+    "method" => "bre_by_identifier",
+    "api_name" => "open-ils.serial.biblio.record_entry.by_identifier",
+    "stream" => 1,
+    "signature" => {
+        "desc" => "Find instances of biblio.record_entry given a search token" .
+            " that could be a value for any identifier defined in " .
+            "config.metabib_field",
+        "params" => [
+            {"desc" => "Search token", "type" => "string"},
+            {"desc" => "Options: require_subscriptions, add_mvr, is_actual_id" .
+                " (all boolean)", "type" => "object"}
+        ],
+        "return" => {
+            "desc" => "Any matching BREs, or if the add_mvr option is true, " .
+                "objects with a 'bre' key/value pair, and an 'mvr' " .
+                "key-value pair.  BREs have subscriptions fleshed on.",
+            "type" => "object"
+        }
+    }
+);
+
+sub bre_by_identifier {
+    my ($self, $client, $term, $options) = @_;
+
+    return new OpenILS::Event("BAD_PARAMS") unless $term;
+
+    $options ||= {};
+    my $e = new_editor();
+
+    my @ids;
+
+    if ($options->{"is_actual_id"}) {
+        @ids = ($term);
+    } else {
+        my $cmf =
+            $e->search_config_metabib_field({"field_class" => "identifier"})
+                or return $e->die_event;
+
+        my @identifiers = map { $_->name } @$cmf;
+        my $query = join(" || ", map { "id|$_: $term" } @identifiers);
+
+        my $search = create OpenSRF::AppSession("open-ils.search");
+        my $search_result = $search->request(
+            "open-ils.search.biblio.multiclass.query.staff", {}, $query
+        )->gather(1);
+        $search->disconnect;
+
+        # Un-nest results. They tend to look like [[1],[2],[3]] for some reason.
+        @ids = map { @{$_} } @{$search_result->{"ids"}};
+
+        unless (@ids) {
+            $e->disconnect;
+            return undef;
+        }
+    }
+
+    my $bre = $e->search_biblio_record_entry([
+        {"id" => \@ids}, {
+            "flesh" => 2, "flesh_fields" => {
+                "bre" => ["subscriptions"],
+                "ssub" => ["owning_lib"]
+            }
+        }
+    ]) or return $e->die_event;
+
+    if (@$bre && $options->{"require_subscriptions"}) {
+        $bre = [ grep { @{$_->subscriptions} } @$bre ];
+    }
+
+    $e->disconnect;
+
+    if (@$bre) { # re-evaluate after possible grep
+        if ($options->{"add_mvr"}) {
+            $client->respond(
+                {"bre" => $_, "mvr" => _get_mvr($_->id)}
+            ) foreach (@$bre);
+        } else {
+            $client->respond($_) foreach (@$bre);
+        }
+    }
+
+    undef;
+}
+
+__PACKAGE__->register_method(
+    "method" => "get_receivable_items",
+    "api_name" => "open-ils.serial.items.receivable.by_subscription",
+    "stream" => 1,
+    "signature" => {
+        "desc" => "Return all receivable items under a given subscription",
+        "params" => [
+            {"desc" => "Authtoken", "type" => "string"},
+            {"desc" => "Subscription ID", "type" => "number"},
+        ],
+        "return" => {
+            "desc" => "All receivable items under a given subscription",
+            "type" => "object"
+        }
+    }
+);
+
+__PACKAGE__->register_method(
+    "method" => "get_receivable_items",
+    "api_name" => "open-ils.serial.items.receivable.by_issuance",
+    "stream" => 1,
+    "signature" => {
+        "desc" => "Return all receivable items under a given issuance",
+        "params" => [
+            {"desc" => "Authtoken", "type" => "string"},
+            {"desc" => "Issuance ID", "type" => "number"},
+        ],
+        "return" => {
+            "desc" => "All receivable items under a given issuance",
+            "type" => "object"
+        }
+    }
+);
+
+sub get_receivable_items {
+    my ($self, $client, $auth, $term)  = @_;
+
+    my $e = new_editor("authtoken" => $auth);
+    return $e->die_event unless $e->checkauth;
+
+    # XXX permissions
+
+    my $by = ($self->api_name =~ /by_(\w+)$/)[0];
+
+    my %where = (
+        "issuance" => {"issuance" => $term},
+        "subscription" => {"+siss" => {"subscription" => $term}}
+    );
+
+    my $item_ids = $e->json_query(
+        {
+            "select" => {"sitem" => ["id"]},
+            "from" => {"sitem" => "siss"},
+            "where" => {
+                %{$where{$by}}, "date_received" => undef
+            },
+            "order_by" => {"sitem" => ["id"]}
+        }
+    ) or return $e->die_event;
+
+    return undef unless @$item_ids;
+
+    foreach (map { $_->{"id"} } @$item_ids) {
+        $client->respond(
+            $e->retrieve_serial_item([
+                $_, {
+                    "flesh" => 3,
+                    "flesh_fields" => {
+                        "sitem" => ["stream", "issuance"],
+                        "sstr" => ["distribution"],
+                        "sdist" => ["holding_lib"]
+                    }
+                }
+            ])
+        );
+    }
+
+    $e->disconnect;
+    undef;
+}
+
+__PACKAGE__->register_method(
+    "method" => "get_receivable_issuances",
+    "api_name" => "open-ils.serial.issuances.receivable",
+    "stream" => 1,
+    "signature" => {
+        "desc" => "Return all issuances with receivable items given " .
+            "a subscription ID",
+        "params" => [
+            {"desc" => "Authtoken", "type" => "string"},
+            {"desc" => "Subscription ID", "type" => "number"},
+        ],
+        "return" => {
+            "desc" => "All issuances with receivable items " .
+                "(but not the items themselves)", "type" => "object"
+        }
+    }
+);
+
+sub get_receivable_issuances {
+    my ($self, $client, $auth, $sub_id) = @_;
+
+    my $e = new_editor("authtoken" => $auth);
+    return $e->die_event unless $e->checkauth;
+
+    # XXX permissions
+
+    my $issuance_ids = $e->json_query({
+        "select" => {
+            "siss" => [
+                {"transform" => "distinct", "column" => "id"},
+                "date_published"
+            ]
+        },
+        "from" => {"siss" => "sitem"},
+        "where" => {
+            "subscription" => $sub_id,
+            "+sitem" => {"date_received" => undef}
+        },
+        "order_by" => {
+            "siss" => {"date_published" => {"direction" => "asc"}}
+        }
+
+    }) or return $e->die_event;
+
+    $client->respond($e->retrieve_serial_issuance($_->{"id"}))
+        foreach (@$issuance_ids);
+
+    $e->disconnect;
+    undef;
+}
+
 1;

Modified: branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Storage/CDBI/authority.pm
===================================================================
--- branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Storage/CDBI/authority.pm	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Storage/CDBI/authority.pm	2010-10-18 13:46:56 UTC (rev 18371)
@@ -10,7 +10,7 @@
 
 authority::record_entry->table( 'authority_record_entry' );
 authority::record_entry->columns( Primary => qw/id/ );
-authority::record_entry->columns( Essential => qw/arn_source arn_value creator editor
+authority::record_entry->columns( Essential => qw/creator editor
 				      create_date edit_date source active
 				      deleted marc last_xact_id/ );
 

Modified: branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Storage/Driver/Pg/QueryParser.pm
===================================================================
--- branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Storage/Driver/Pg/QueryParser.pm	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Storage/Driver/Pg/QueryParser.pm	2010-10-18 13:46:56 UTC (rev 18371)
@@ -659,8 +659,7 @@
 
                 $from .= ")";
 
-                my $core_limit = $self->QueryParser->core_limit || 25000;
-                $from .= "\n\t\tLIMIT $core_limit\n\t) AS $talias ON (m.source = $talias.source)";
+                $from .= "\n\t\t) AS $talias ON (m.source = $talias.source)";
 
                 $where .= 'TRUE';
 

Modified: branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Storage/Publisher/action.pm
===================================================================
--- branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Storage/Publisher/action.pm	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Storage/Publisher/action.pm	2010-10-18 13:46:56 UTC (rev 18371)
@@ -1338,7 +1338,7 @@
 	
 					$current_loop++ if (!@keepers);
 	
-					if ($self->{max_loops}{$pu_lib} && $self->{max_loops}{$pu_lib} <= $current_loop) {
+					if ($self->{max_loops}{$pu_lib} && $self->{max_loops}{$pu_lib} >= $current_loop) {
 						# We haven't exceeded max_loops yet
 						my @keeper_copies;
 						for my $cp ( @$all_copies ) {

Modified: branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Storage/Publisher/actor.pm
===================================================================
--- branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Storage/Publisher/actor.pm	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Storage/Publisher/actor.pm	2010-10-18 13:46:56 UTC (rev 18371)
@@ -583,20 +583,21 @@
 sub penalized_barcodes {
 	my $self = shift;
 	my $client = shift;
-	my @ignore = @_;
 
 	my $c = actor::card->table;
 	my $p = actor::user_standing_penalty->table;
 
-	my $sql = "SELECT c.barcode FROM $c c JOIN $p p USING (usr)";
+	my $sql = <<"	SQL";
+		SELECT	DISTINCT c.barcode
+		  FROM	$c c
+			JOIN $p p USING (usr)
+			JOIN config.standing_penalty csp ON (csp.id = p.standing_penalty)
+		  WHERE	csp.block_list IS NOT NULL
+			AND p.set_date < CURRENT_DATE
+			AND (p.stop_date IS NULL OR p.stop_date > CURRENT_DATE);
+	SQL
 
-	if (@ignore) {
-		$sql .= ' WHERE penalty_type NOT IN ('. join(',', map { '?' } @ignore) . ')';
-	}
-
-	$sql .= ' GROUP BY c.barcode;';
-
-	my $list = actor::user->db_Main->selectcol_arrayref($sql, {}, @ignore);
+	my $list = actor::user->db_Main->selectcol_arrayref($sql);
 	for my $bc ( @$list ) {
 		$client->respond($bc);
 	}
@@ -608,11 +609,7 @@
 	stream		=> 1,
 	method		=> 'penalized_barcodes',
 	signature	=> <<'	NOTE',
-		Returns an array of barcodes that have penalties not listed
-		as a parameter.  Supply a list of any penalty types that should
-		not stop a patron from checking out materials.
-
-		@param ignore_list Penalty type to ignore
+		Returns an array of barcodes that have blocking penalties.
 		@return array of barcodes
 	NOTE
 );

Modified: branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Storage/Publisher/asset.pm
===================================================================
--- branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Storage/Publisher/asset.pm	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Storage/Publisher/asset.pm	2010-10-18 13:46:56 UTC (rev 18371)
@@ -799,51 +799,64 @@
 # XXX Since this is all we need in open-ils.storage for serial stuff ATM, just
 # XXX putting it here instead of creating a whole new file.
 sub issuance_ranged_tree {
-	my $self = shift;
-	my $client = shift;
-	my $iss = shift;
-	my $ou = shift;
-	my $depth = shift || 0;
+    my $self = shift;
+    my $client = shift;
+    my $iss = shift;
+    my $ou = shift;
+    my $depth = shift || 0;
 
-	my $ou_list =
-		actor::org_unit
-			->db_Main
-			->selectcol_arrayref(
-				'SELECT id FROM actor.org_unit_descendants(?,?)',
-				{},
-				$ou,
-				$depth
-			);
+    my $ou_list =
+        actor::org_unit
+            ->db_Main
+            ->selectcol_arrayref(
+                'SELECT id FROM actor.org_unit_descendants(?,?)',
+                {},
+                $ou,
+                $depth
+            );
 
-	return undef unless ($ou_list and @$ou_list);
+    return undef unless ($ou_list and @$ou_list);
 
-	$iss = serial::issuance->retrieve( $iss );
-	return undef unless ($iss);
+    $iss = serial::issuance->retrieve( $iss );
+    return undef unless ($iss);
 
-	my $issuance = $iss->to_fieldmapper;
-	$issuance->items([]);
+    my $issuance = $iss->to_fieldmapper;
+    $issuance->items([]);
 
-    for my $it ( $iss->items() ) {
-        my $item = $it->to_fieldmapper;
+    # Now, gather issuances on the same bib, with the same label and date_published ...
+    my @subs = map { $_->id } serial::subscription->search( record_entry => $iss->subscription->record_entry->id );
 
-    	next if ($it->unit->deleted);
-    	next unless (grep { $it->unit->circ_lib eq $_ } @$ou_list);
+    my @similar_iss = serial::issuance->search_where(
+        subscription => \@subs,
+        label => $iss->label,
+        date_published => $iss->date_published
+    );
 
-    	my $unit = $it->unit->to_fieldmapper;
- 		$unit->status( $it->unit->status->to_fieldmapper );
-    	$unit->location( $it->unit->location->to_fieldmapper );
-    	$item->unit( $unit );
+    # ... and add all /their/ items to the target issuance
+    for my $i ( @similar_iss ) {
+        for my $it ( $i->items() ) {
+    
+            next if ($it->unit->deleted);
+            next unless (grep { $it->unit->circ_lib eq $_ } @$ou_list);
+    
+            my $unit = $it->unit->to_fieldmapper;
+            $unit->status( $it->unit->status->to_fieldmapper );
+            $unit->location( $it->unit->location->to_fieldmapper );
 
-        push @{ $issuance->items }, $item;
-	}
+            my $item = $it->to_fieldmapper;
+            $item->unit( $unit );
+    
+            push @{ $issuance->items }, $item;
+        }
+    }
 
-	return $issuance;
+    return $issuance;
 }
 __PACKAGE__->register_method(
-	api_name	=> 'open-ils.storage.serial.issuance.ranged_tree',
-	method		=> 'issuance_ranged_tree',
-	argc		=> 1,
-	api_level	=> 1,
+    api_name    => 'open-ils.storage.serial.issuance.ranged_tree',
+    method      => 'issuance_ranged_tree',
+    argc        => 1,
+    api_level   => 1,
 );
 
 sub merge_record_assets {

Modified: branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Storage/Publisher/biblio.pm
===================================================================
--- branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Storage/Publisher/biblio.pm	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Storage/Publisher/biblio.pm	2010-10-18 13:46:56 UTC (rev 18371)
@@ -444,9 +444,16 @@
 	my $cl_table = asset::copy_location->table;
 	my $cs_table = config::copy_status->table;
 
+	# FIXME using oils_i18n_xlate here is exposing a hitherto unexposed
+	# implementation detail of json_query; doing it this way because
+	# json_query currently doesn't grok joining a function to tables
 	my $sql = <<"	SQL";
 
-		SELECT	cp.circ_lib, cn.label, cl.name, cp.status, count(cp.id)
+		SELECT	cp.circ_lib,
+				cn.label, 
+				oils_i18n_xlate('asset.copy_location', 'acpl', 'name', 'id', cl.id::TEXT, ?),
+				cp.status,
+				count(cp.id)
 		  FROM	$cp_table cp,
 		  	$cn_table cn,
 			$cl_table cl,
@@ -465,7 +472,8 @@
 	SQL
 
 	my $sth = biblio::record_entry->db_Main->prepare_cached($sql);
-	$sth->execute($ou, $depth, "$rec" );
+	my $ses_locale = $client->session ? $client->session->session_locale : 'en-US';
+	$sth->execute($ses_locale, $ou, $depth, "$rec" );
 
 	my %data = ();
 	for my $row (@{$sth->fetchall_arrayref}) {

Modified: branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Storage/Publisher/metabib.pm
===================================================================
--- branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Storage/Publisher/metabib.pm	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Storage/Publisher/metabib.pm	2010-10-18 13:46:56 UTC (rev 18371)
@@ -2359,7 +2359,7 @@
 
         my @locales = config::i18n_locale->search_where({ code => { '<>' => '' } });
         for my $locale ( @locales ) {
-            $locale_map{$locale->code} = $locale->marc_code;
+            $locale_map{lc($locale->code)} = $locale->marc_code;
         }
         $locale_map{COMPLETE} = 1;
 
@@ -2405,7 +2405,7 @@
     if (!defined($args{preferred_language})) {
 		my $ses_locale = $client->session ? $client->session->session_locale : $default_preferred_language;
         $args{preferred_language} =
-            $locale_map{ $ses_locale } || 'eng';
+            $locale_map{ lc($ses_locale) } || 'eng';
     }
 
     if (!defined($args{preferred_language_weight})) {
@@ -2817,7 +2817,7 @@
 
         my @locales = config::i18n_locale->search_where({ code => { '<>' => '' } });
         for my $locale ( @locales ) {
-            $locale_map{$locale->code} = $locale->marc_code;
+            $locale_map{lc($locale->code)} = $locale->marc_code;
         }
         $locale_map{COMPLETE} = 1;
 
@@ -2846,7 +2846,7 @@
         $parser->default_preferred_language( $args{preferred_language} );
         if (!$parser->default_preferred_language) {
 		    my $ses_locale = $client->session ? $client->session->session_locale : '';
-            $parser->default_preferred_language( $locale_map{ $ses_locale } );
+            $parser->default_preferred_language( $locale_map{ lc($ses_locale) } );
         }
         $parser->default_preferred_language(
             OpenSRF::Utils::SettingsClient->new->config_value(
@@ -3098,7 +3098,7 @@
 
         my @locales = config::i18n_locale->search_where({ code => { '<>' => '' } });
         for my $locale ( @locales ) {
-            $locale_map{$locale->code} = $locale->marc_code;
+            $locale_map{lc($locale->code)} = $locale->marc_code;
         }
         $locale_map{COMPLETE} = 1;
 

Modified: branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/SuperCat.pm
===================================================================
--- branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/SuperCat.pm	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/SuperCat.pm	2010-10-18 13:46:56 UTC (rev 18371)
@@ -951,8 +951,11 @@
 		my $before = $_storage->request(
 			"open-ils.cstore.json_query.atomic",
 			{ select	=> { afr => [qw/record value/] },
-			  from		=> 'afr',
-			  where		=> { tag => $tag, subfield => $subfield, value => { '<' => lc($value) } },
+			  from		=> { 'are', 'afr' },
+			  where		=> {
+				'+afr' => { tag => $tag, subfield => $subfield, value => { '<' => lc($value) } },
+				'+are' => { 'deleted' => 'f' }
+			  },
 			  order_by	=> { afr => { value => 'desc' } },
 			  limit		=> $before_limit,
 			  offset	=> abs($page) * $page_size - $before_offset,
@@ -965,8 +968,11 @@
 		my $after = $_storage->request(
 			"open-ils.cstore.json_query.atomic",
 			{ select	=> { afr => [qw/record value/] },
-			  from		=> 'afr',
-			  where		=> { tag => $tag, subfield => $subfield, value => { '>=' => lc($value) } }, 
+			  from		=> { 'are', 'afr' },
+			  where		=> {
+				'+afr' => { tag => $tag, subfield => $subfield, value => { '>=' => lc($value) } },
+				'+are' => { 'deleted' => 'f' }
+			  },
 			  order_by	=> { afr => { value => 'asc' } },
 			  limit		=> $after_limit,
 			  offset	=> abs($page) * $page_size - $after_offset,
@@ -1362,8 +1368,11 @@
 		my $before = $_storage->request(
 			"open-ils.cstore.json_query.atomic",
 			{ select	=> { afr => [qw/record value/] },
-			  from		=> 'afr',
-			  where		=> { tag => $tag, subfield => $subfield, value => { '<' => lc($value) } },
+			  from		=> { 'afr', 'are' },
+			  where		=> {
+				'+afr' => { tag => $tag, subfield => $subfield, value => { '<' => lc($value) } },
+				'+are' => { deleted => 'f' }
+			  },
 			  order_by	=> { afr => { value => 'desc' } },
 			  limit		=> $limit,
 			  offset	=> $offset
@@ -1376,8 +1385,11 @@
 		my $after = $_storage->request(
 			"open-ils.cstore.json_query.atomic",
 			{ select	=> { afr => [qw/record value/] },
-			  from		=> 'afr',
-			  where		=> { tag => $tag, subfield => $subfield, value => { '>=' => lc($value) } }, 
+			  from		=> { 'afr', 'are' },
+			  where		=> {
+				'+afr' => { tag => $tag, subfield => $subfield, value => { '>=' => lc($value) } },
+				'+are' => { deleted => 'f' }
+			  },
 			  order_by	=> { afr => { value => 'asc' } },
 			  limit		=> $limit,
 			  offset	=> $offset
@@ -2665,6 +2677,7 @@
 
     $xml .= 'id="tag:open-ils.org:asset-call_number/' . $self->obj->id . '" ';
     $xml .= 'lib="' . $self->escape( $self->obj->owning_lib->shortname ) . '" ';
+    $xml .= 'opac_visible="' . $self->obj->owning_lib->opac_visible . '" ';
     $xml .= 'label="' . $self->escape( $self->obj->label ) . '">';
     $xml .= "\n";
 
@@ -3091,13 +3104,13 @@
     $xml .= ">\n";
 
     $xml .= '        <status ident="' . $self->obj->status->id . '">' . $self->escape( $self->obj->status->name  ) . "</status>\n";
-    $xml .= '        <location ident="' . $self->obj->location->id . '">' . $self->escape( $self->obj->location->name  ) . "</location>\n";
-    $xml .= '        <circlib ident="' . $self->obj->circ_lib->id . '">' . $self->escape( $self->obj->circ_lib->name  ) . "</circlib>\n";
+    $xml .= '        <location ident="' . $self->obj->location->id . '" opac_visible="'.$self->obj->location->opac_visible.'">' . $self->escape( $self->obj->location->name  ) . "</location>\n";
+    $xml .= '        <circlib ident="' . $self->obj->circ_lib->id . '" opac_visible="'.$self->obj->circ_lib->opac_visible.'">' . $self->escape( $self->obj->circ_lib->name  ) . "</circlib>\n";
 
     $xml .= '        <circ_lib xmlns="http://open-ils.org/spec/actors/v1" ';
     $xml .= 'id="tag:open-ils.org:actor-org_unit/' . $self->obj->circ_lib->id . '" ';
     $xml .= 'shortname="'.$self->escape( $self->obj->circ_lib->shortname ) .'" ';
-    $xml .= 'name="'.$self->escape( $self->obj->circ_lib->name ) .'"/>';
+    $xml .= 'name="'.$self->escape( $self->obj->circ_lib->name ) .'" opac_visible="'.$self->obj->circ_lib->opac_visible.'"/>';
     $xml .= "\n";
 
 	$xml .= "        <copy_notes>\n";

Modified: branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Trigger/Reactor.pm
===================================================================
--- branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Trigger/Reactor.pm	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Trigger/Reactor.pm	2010-10-18 13:46:56 UTC (rev 18371)
@@ -109,7 +109,7 @@
             }
         }
         $primary and unshift @isbns, $primary;
-        $logger->error("get_li_isbns returning isbns: " . join(', ', @isbns));
+        $logger->debug("get_li_isbns returning isbns: " . join(', ', @isbns));
         return @isbns;
     },
 

Modified: branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Trigger/Validator/Acq/PurchaseOrderEDIRequired.pm
===================================================================
--- branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Trigger/Validator/Acq/PurchaseOrderEDIRequired.pm	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Trigger/Validator/Acq/PurchaseOrderEDIRequired.pm	2010-10-18 13:46:56 UTC (rev 18371)
@@ -16,8 +16,10 @@
             new_editor->retrieve_acq_provider($po->provider);
 
     return 1 if 
-        $po->state eq 'on-order' and 
-        $provider->edi_default   and 
+        ($po->state eq 'on-order' or
+         $po->state eq 'retry'      ) and 
+        $provider                     and 
+        $provider->edi_default        and 
         $U->is_true($provider->active);
 
     return 0;

Modified: branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Trigger/Validator.pm
===================================================================
--- branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Trigger/Validator.pm	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Trigger/Validator.pm	2010-10-18 13:46:56 UTC (rev 18371)
@@ -82,4 +82,13 @@
     return 0;
 }
 
+sub HoldIsCancelled {
+    my $self = shift;
+    my $env = shift;
+
+    my $hold = $env->{target};
+
+    return ($hold->cancel_time) ? 1 : 0;
+}
+
 1;

Modified: branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Vandelay.pm
===================================================================
--- branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Vandelay.pm	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application/Vandelay.pm	2010-10-18 13:46:56 UTC (rev 18371)
@@ -44,6 +44,7 @@
         x => 'holdings',
         y => 'holdings',
         z => 'auth',
+      ' ' => 'bib',
 );
 
 sub initialize {}
@@ -280,15 +281,6 @@
         $logger->info("processing record $count");
 
         try {
-            # Avoid an over-eager MARC::File::XML that may try to convert
-            # our record from MARC8 to UTF8 and break because the record
-            # is obviously already UTF8
-            my $ldr = $r->leader();
-            if (($marctype eq 'XML') && (substr($ldr, 9, 1) ne 'a')) {
-                $logger->warn("MARCXML record LDR/09 was not 'a'; record leader may be corrupt");
-                substr($ldr,9,1,'a');
-                $r->leader($ldr);
-            }
             (my $xml = $r->as_xml_record()) =~ s/\n//sog;
             $xml =~ s/^<\?xml.+\?\s*>//go;
             $xml =~ s/>\s+</></go;
@@ -614,6 +606,7 @@
     my $auto_overlay_1match = $$args{auto_overlay_1match};
     my $merge_profile = $$args{merge_profile};
     my $bib_source = $$args{bib_source};
+    my $report_all = $$args{report_all};
 
     my $overlay_func = 'vandelay.overlay_bib_record';
     my $auto_overlay_func = 'vandelay.auto_overlay_bib_record';
@@ -624,6 +617,13 @@
     my $update_queue_func = 'update_vandelay_bib_queue';
     my $rec_class = 'vqbr';
 
+    my %bib_sources;
+    my $editor = new_editor();
+    my $sources = $editor->search_config_bib_source({id => {'!=' => undef}});
+    foreach my $src (@$sources) {
+        $bib_sources{$src->id} = $src->source;
+    }
+
     if($type eq 'auth') {
         $overlay_func =~ s/bib/auth/o;
         $auto_overlay_func = s/bib/auth/o;
@@ -737,8 +737,7 @@
                 # No overlay / merge occurred.  Do a traditional record import by creating a new record
             
                 if($type eq 'bib') {
-                    $record = OpenILS::Application::Cat::BibCommon->biblio_record_xml_import($e, $rec->marc); #$rec->bib_source
-
+                    $record = OpenILS::Application::Cat::BibCommon->biblio_record_xml_import($e, $rec->marc, $bib_sources{$rec->bib_source});
                 } else {
 
                     $record = OpenILS::Application::Cat::AuthCommon->import_authority_record($e, $rec->marc); #$source);
@@ -767,7 +766,7 @@
             $conn->respond({total => $total, progress => ++$count, imported => $rec_id, err_event => $e->die_event});
         }
 
-        $conn->respond({total => $total, progress => $count, imported => $rec_id}) if (++$count % $step) == 0;
+        $conn->respond({total => $total, progress => $count, imported => $rec_id}) if (!$report_all and ++$count % $step) == 0;
     }
 
     # see if we need to mark any queues as complete

Modified: branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application.pm
===================================================================
--- branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application.pm	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Application.pm	2010-10-18 13:46:56 UTC (rev 18371)
@@ -4,8 +4,9 @@
 use base qw/OpenSRF::Application/;
 
 sub ils_version {
-    # version format is "x-y-z-p", for example "1-2-1-0" for Evergreen 1.2.1.0
-    return "1-5";
+    # version format is "x-y-z", for example "2-0-0" for Evergreen 2.0.0
+    # For branches, format is "x-y"
+    return "HEAD";
 }
 
 __PACKAGE__->register_method(

Modified: branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Const.pm
===================================================================
--- branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Const.pm	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Const.pm	2010-10-18 13:46:56 UTC (rev 18371)
@@ -96,6 +96,9 @@
 
 
 econst OILS_HOLD_TYPE_COPY        => 'C';
+econst OILS_HOLD_TYPE_FORCE       => 'F';
+econst OILS_HOLD_TYPE_RECALL      => 'R';
+econst OILS_HOLD_TYPE_ISSUANCE    => 'I';
 econst OILS_HOLD_TYPE_VOLUME      => 'V';
 econst OILS_HOLD_TYPE_TITLE       => 'T';
 econst OILS_HOLD_TYPE_METARECORD  => 'M';

Modified: branches/serials-integration/Open-ILS/src/perlmods/OpenILS/SIP/Item.pm
===================================================================
--- branches/serials-integration/Open-ILS/src/perlmods/OpenILS/SIP/Item.pm	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/src/perlmods/OpenILS/SIP/Item.pm	2010-10-18 13:46:56 UTC (rev 18371)
@@ -151,10 +151,11 @@
                     atc => [ 'dest' ]
                 }
             }
-        ]);
-        # warn "Item transit: " . Dumper($transit) . "\nItem transit->dest: " . Dumper($transit->dest);;
+        ])->[0];
+
         if ($transit) {
-            $self->{destination_loc} = $transit->[0]->dest->shortname;
+            $self->{transit} = $transit;
+            $self->{destination_loc} = $transit->dest->shortname;
         } else {
             syslog('LOG_WARNING', "OILS: Item('$item_id') status is In Transit, but no action.transit_copy found!");
         }
@@ -163,11 +164,12 @@
     syslog("LOG_DEBUG", "OILS: Item('$item_id'): found with title '%s'", $self->title_id);
 
     my $config = OpenILS::SIP->config();    # FIXME : will not always match!
+    my $legacy = $config->{implementation_config}->{legacy_script_support} || undef;
 
-    my $legacy = $config->{implementation_config}->{legacy_script_support} || undef;
     if( defined $legacy ) {
         $self->{legacy_script_support} = ($legacy =~ /t(rue)?/io) ? 1 : 0;
         syslog("LOG_DEBUG", "legacy_script_support is set in SIP config: " . $self->{legacy_script_support});
+
     } else {
         my $lss = OpenSRF::Utils::SettingsClient->new->config_value(
             apps         => 'open-ils.circ',
@@ -364,8 +366,54 @@
     return 0;
 }
 
-sub hold_pickup_date {  # TODO
+
+# Note: If the held item is in transit, this will be an approximation of shelf 
+# expire time, since the time is not set until the item is  checked in at the pickup location
+my %shelf_expire_setting_cache;
+sub hold_pickup_date {  
     my $self = shift;
+    my $copy = $self->{copy};
+
+    if( ($copy->status->id == OILS_COPY_STATUS_ON_HOLDS_SHELF) ||
+        ($self->{transit} and $self->{transit}->copy_status == OILS_COPY_STATUS_ON_HOLDS_SHELF) ) {
+
+        # item has been captured for a hold
+
+        my $e = OpenILS::SIP->editor();
+        my $hold = $e->search_action_hold_request([
+            {
+                current_copy        => $copy->id,
+                capture_time        => {'!=' => undef},
+                cancel_time         => undef,
+                fulfillment_time    => undef
+            },
+            {limit => 1}
+        ])->[0];
+        
+        if($hold) {
+            my $date = $hold->shelf_expire_time;
+
+            if(!$date) {
+                # hold has not hit the shelf.  create a best guess.
+
+                my $interval = $shelf_expire_setting_cache{$hold->pickup_lib} ||
+                    $U->ou_ancestor_setting_value(
+                        $hold->pickup_lib, 
+                        'circ.holds.default_shelf_expire_interval');
+
+                $shelf_expire_setting_cache{$hold->pickup_lib} = $interval;
+
+                if($interval) {
+                    my $seconds = OpenSRF::Utils->interval_to_seconds($interval);
+                    $date = DateTime->now->add(seconds => $seconds);
+                    $date = $date->strftime('%FT%T%z') if $date;
+                }
+            }
+
+            return OpenILS::SIP->format_date($date) if $date;
+        }
+    }
+
     return 0;
 }
 

Modified: branches/serials-integration/Open-ILS/src/perlmods/OpenILS/SIP/Patron.pm
===================================================================
--- branches/serials-integration/Open-ILS/src/perlmods/OpenILS/SIP/Patron.pm	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/src/perlmods/OpenILS/SIP/Patron.pm	2010-10-18 13:46:56 UTC (rev 18371)
@@ -107,8 +107,12 @@
 sub name {
     my $self = shift;
     my $u = $self->{user};
-    return OpenILS::SIP::clean_text($u->first_given_name . ' ' . 
-            $u->second_given_name . ' ' . $u->family_name);
+    return OpenILS::SIP::clean_text(
+        sprintf('%s %s %s', 
+            ($u->first_given_name || ''),
+            ($u->second_given_name || ''),
+            ($u->family_name || '')));
+   
 }
 
 sub home_library {
@@ -137,6 +141,11 @@
     return $return;
 }
 
+sub internal_id {
+    my $self = shift;
+    return $self->{user}->id;
+}
+
 sub address {
 	my $self = shift;
 	my $u    = $self->{user};
@@ -164,6 +173,14 @@
 
 sub ptype {
     my $self = shift;
+
+	my $use_code = OpenILS::SIP->get_option_value('patron_type_uses_code') || '';
+
+    # should we use the no_i18n version of patron profile name (as a 'code')?
+    return $self->{editor}->retrieve_permission_grp_tree(
+        [$self->{user}->profile->id, {no_i18n => 1}])->name
+        if $use_code =~ /true/io;
+
     return OpenILS::SIP::clean_text($self->{user}->profile->name);
 }
 
@@ -428,6 +445,8 @@
 			0, $self->{editor}, $self->{user}->id);;
 }
 
+
+
 sub overdue_items {
 	my ($self, $start, $end) = @_;
 
@@ -437,13 +456,12 @@
 
 	my @o;
 	syslog('LOG_DEBUG', "OILS: overdue_items() fleshing circs @overdues");
+
+	my $return_datatype = OpenILS::SIP->get_option_value('msg64_summary_datatype') || '';
 	
-	
-	my @return_datatype = grep { $_->{name} eq 'msg64_summary_datatype' } OpenILS::SIP::config()->{implementation_config}->{options}->{option};
-	
 	for my $circid (@overdues) {
 		next unless $circid;
-		if(@return_datatype and $return_datatype[0]->{value} eq 'barcode') {
+		if($return_datatype eq 'barcode') {
 			push( @o, __circ_to_barcode($self->{editor}, $circid));
 		} else {
 			push( @o, OpenILS::SIP::clean_text(__circ_to_title($self->{editor}, $circid)));
@@ -486,11 +504,11 @@
 	my @c;
 	syslog('LOG_DEBUG', "OILS: charged_items() fleshing circs @charges");
 
-	my @return_datatype = grep { $_->{name} eq 'msg64_summary_datatype' } OpenILS::SIP::config()->{implementation_config}->{options}->{option};
+	my $return_datatype = OpenILS::SIP->get_option_value('msg64_summary_datatype') || '';
 
 	for my $circid (@charges) {
 		next unless $circid;
-		if(@return_datatype and $return_datatype[0]->{value} eq 'barcode') {
+		if($return_datatype eq 'barcode') {
 			push( @c, __circ_to_barcode($self->{editor}, $circid));
 		} else {
 			push( @c, OpenILS::SIP::clean_text(__circ_to_title($self->{editor}, $circid)));

Modified: branches/serials-integration/Open-ILS/src/perlmods/OpenILS/SIP/Transaction/Checkin.pm
===================================================================
--- branches/serials-integration/Open-ILS/src/perlmods/OpenILS/SIP/Transaction/Checkin.pm	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/src/perlmods/OpenILS/SIP/Transaction/Checkin.pm	2010-10-18 13:46:56 UTC (rev 18371)
@@ -53,9 +53,10 @@
     return !$self->{item}->magnetic;
 }
 
+my %org_sn_cache;
 sub do_checkin {
     my $self = shift;
-    my ($inst_id, $trans_date, $return_date, $current_loc, $item_props) = @_; # most unused
+    my ($sip_handler, $inst_id, $trans_date, $return_date, $current_loc, $item_props) = @_; # most unused
 
     unless($self->{item}) {
         $self->ok(0);
@@ -64,55 +65,78 @@
 
     $inst_id ||= '';
 
+    # physical location defaults to ws ou of the logged in sip user,
+    # which currently defaults to home_ou, since ws's aren't used.
+    my $phys_location = $sip_handler->{login_session}->ws_ou;
+
+    my $args = {barcode => $self->{item}->id};
+
+    if($current_loc) { # SIP client specified a physical location
+
+        my $org_id = (defined $org_sn_cache{$current_loc}) ? 
+            $org_sn_cache{$current_loc} :
+            OpenILS::SIP->editor()->search_actor_org_unit({shortname => $current_loc}, {idlist => 1})->[0];
+
+        $org_sn_cache{$current_loc} = $org_id;
+
+        # if the caller specifies a physical location, use it as the checkin circ lib
+        $args->{circ_lib} = $phys_location = $org_id if defined $org_id;
+    }
+
     my $resp = $U->simplereq(
         'open-ils.circ',
         'open-ils.circ.checkin',
-        $self->{authtoken},
-        { barcode => $self->{item}->id }
+        $self->{authtoken}, $args
     );
 
     if ($debug) {
-        open (DUMP, ">/tmp/sip_do_checkin.dump");
-        print DUMP Dumper($resp);
-        close DUMP;
+        my $s = Dumper($resp);
+        $s =~ s/\n//mog;
+        syslog('LOG_INFO', "OILS: Checkin response: $s");
     }
 
+    # In oddball cases, we can receive an array of events.
+    # The first event received should be treated as the main result.
+    $resp = $$resp[0] if ref($resp) eq 'ARRAY';
+
     my $code = $U->event_code($resp);
-    my $txt  = $code ? $resp->{textcode} : '';
+    my $txt  = (defined $code) ? $resp->{textcode} : '';
 
+    syslog('LOG_INFO', "OILS: Checkin resulted in event: $txt, phys_location: $phys_location");
+
     $resp->{org} &&= OpenILS::SIP::shortname_from_id($resp->{org}); # Convert id to shortname
 
     $self->destination_loc($resp->{org}) if $resp->{org};
 
-    $debug and warn "Checkin textcode: $txt, org: " . ($resp->{org} || '');
+    if ($txt eq 'ROUTE_ITEM') {
+        # Note, this alert_type will be overridden below if this is a hold transit
+        $self->alert_type('04'); # send to other branch
 
-    if ($txt eq 'ROUTE_ITEM') {
-        # $self->destination_loc($resp->{org});   # org value already converted and added (above)
-        $self->alert_type('04');            # send to other branch
+    } elsif ($txt and $txt ne 'NO_CHANGE' and $txt ne 'SUCCESS') {
+        syslog('LOG_WARNING', "OILS: Checkin returned unexpected event $code : $txt");
+        $self->alert_type('00'); # unknown
     }
-    elsif ($txt and $txt ne 'NO_CHANGE' and $txt ne 'SUCCESS') {
-        syslog('LOG_WARNING', "OILS: Checkin returned unrecognized event $code : $txt");
-        # $self->ok(0);   # maybe still ok?
-        $self->alert_type('00');            # unknown
-    }
     
     my $payload = $resp->{payload} || {};
 
     # Two places to look for hold data.  These are more important and more definitive than above.
     if ($payload->{remote_hold}) {
-        $self->item->hold($payload->{remote_hold});     # actually only used for checkin at non-owning branch w/ hold at same branch
-    }
-    elsif ($payload->{hold}) {
+        # actually only used for checkin at non-owning branch w/ hold at same branch
+        $self->item->hold($payload->{remote_hold});     
+
+    } elsif ($payload->{hold}) {
         $self->item->hold($payload->{hold});
     }
 
     if ($self->item->hold) {
-        my $holder = OpenILS::SIP->find_patron('usr' => $self->item->hold->usr)
-            or warn "OpenILS::SIP->find_patron cannot find hold usr => '" . $self->item->hold->usr . "'";
+        my $holder = OpenILS::SIP->find_patron('usr' => $self->item->hold->usr) or
+            syslog('LOG_WARNING', "OpenILS::SIP->find_patron cannot find hold usr => '" . $self->item->hold->usr . "'");
+
         $self->item->hold_patron_bcode( $holder->id   );
         $self->item->hold_patron_name(  $holder->name );     # Item already had the holder ID, we really just needed the name
         $self->item->destination_loc( OpenILS::SIP::shortname_from_id($self->item->hold->pickup_lib) );   # must use pickup_lib as method
-        my $atype = ($self->item->destination_loc eq $inst_id)  ? '01' : '02';
+
+        my $atype = ($self->item->hold->pickup_lib == $phys_location) ? '01' : '02';
         $self->alert_type($atype);
     }
 
@@ -122,14 +146,13 @@
     my $copy = $resp->{payload}->{copy} || '';
 
     if ( $circ ) {
-        # $self->item->{patron} = OpenILS::SIP::patron_barcode_from_id($circ->usr);     # Item.pm already does this for us!
         $self->ok(1);
     } elsif ($txt eq 'NO_CHANGE' or $txt eq 'SUCCESS' or $txt eq 'ROUTE_ITEM') {
-        $self->ok(1);       # NO_CHANGE means it wasn't checked out anyway, no problem
+        $self->ok(1); # NO_CHANGE means it wasn't checked out anyway, no problem
     } else {
         $self->alert(1);
-        $self->alert_type('00') unless $self->alert_type;   # wasn't checked out, but *something* changed
-        # $self->ok(0);     # maybe still ok?
+        $self->alert_type('00') unless $self->alert_type; # wasn't checked out, but *something* changed
+        # $self->ok(0); # maybe still ok?
     }
 }
 

Modified: branches/serials-integration/Open-ILS/src/perlmods/OpenILS/SIP.pm
===================================================================
--- branches/serials-integration/Open-ILS/src/perlmods/OpenILS/SIP.pm	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/src/perlmods/OpenILS/SIP.pm	2010-10-18 13:46:56 UTC (rev 18371)
@@ -62,16 +62,26 @@
 	return $self;
 }
 
-sub verify_session {
-	my $self = shift;
+sub fetch_session {
+    my $self = shift;
+
 	my $ses = $U->simplereq( 
 		'open-ils.auth',
-		'open-ils.auth.session.retrieve',  $self->{authtoken} );
-	return 1 unless $U->event_code($ses);
-	syslog('LOG_INFO', "OILS: Logging back after session timeout as user ".$self->{login}->{id});
-	return $self->login( $self->{login}->{id}, $self->{login}->{password} );
+		'open-ils.auth.session.retrieve',  $self->{authtoken});
+
+    return undef if $U->event_code($ses); # auth timed out
+    return $self->{login_session} = $ses;
 }
 
+sub verify_session {
+	my $self = shift;
+
+    return 1 if $self->fetch_session;
+
+    syslog('LOG_INFO', "OILS: Logging back after session timeout as user ".$self->{login}->{id});
+    return $self->login( $self->{login}->{id}, $self->{login}->{password} );
+}
+
 sub editor {
 	return $editor = make_editor();
 }
@@ -80,7 +90,15 @@
 	return $config;
 }
 
+sub get_option_value {
+    my($self, $option) = @_;
+    my $ops = $config->{implementation_config}->{options}->{option};
+    $ops = [$ops] unless ref $ops eq 'ARRAY';
+    my @vals = grep { $_->{name} eq $option } @$ops;
+    return @vals ? $vals[0]->{value} : undef;
+}
 
+
 # Creates the global editor object
 my $cstore_init = 1; # call init on first use
 sub make_editor {
@@ -197,6 +215,9 @@
 
 	my $key = $response->{payload}->{authtoken};
 	syslog('LOG_INFO', "OILS: Login succeeded for $username : authkey = $key");
+
+    $self->fetch_session; # to cache the login
+
 	return $self->{authtoken} = $key;
 }
 
@@ -357,7 +378,7 @@
         return $xact;
     }
 
-	$xact->do_checkin( $inst_id, $trans_date, $return_date, $current_loc, $item_props );
+	$xact->do_checkin( $self, $inst_id, $trans_date, $return_date, $current_loc, $item_props );
 	
 	if ($xact->ok) {
         $xact->patron($self->find_patron($item->{patron}));

Modified: branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Utils/Cronscript.pm
===================================================================
--- branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Utils/Cronscript.pm	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Utils/Cronscript.pm	2010-10-18 13:46:56 UTC (rev 18371)
@@ -55,7 +55,7 @@
             'debug'         => 0,
             'verbose+'      => 0,
             'help'          => 0,
-            'internal_var'  => 'XYZ',
+          # 'internal_var'  => 'XYZ',
         },
     #   lockfile => undef,
     #   session => undef,

Copied: branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Utils/ISBN.pm (from rev 17886, trunk/Open-ILS/src/perlmods/OpenILS/Utils/ISBN.pm)
===================================================================
--- branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Utils/ISBN.pm	                        (rev 0)
+++ branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Utils/ISBN.pm	2010-10-18 13:46:56 UTC (rev 18371)
@@ -0,0 +1,96 @@
+package OpenILS::Utils::ISBN;
+
+# ---------------------------------------------------------------
+# Copyright (C) 2010 Equinox Software, Inc
+# Author: Joe Atzberger <jatzberger at esilibrary.com>
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# ---------------------------------------------------------------
+
+use strict;
+use warnings;
+
+use Business::ISBN;
+
+use base qw/Exporter/;
+our $VERSION = '0.01';
+our @EXPORT_OK = qw/isbn_upconvert/;
+
+# Jason Stephenson <jstephenson at mvlc.org> at Merrimack Valley Library Consortium
+# Dan Scott <dscott at laurentian.ca> at Laurentian University
+
+sub isbn_upconvert {
+    my $in     = @_ ? shift : return;
+    my $pretty = @_ ? shift : 0;
+    $in =~ s/\s*//g;
+    $in =~ s/-//g;
+    length($in) or return;
+    my $isbn = Business::ISBN->new($in) or return;
+    $isbn->fix_checksum() if $isbn->is_valid_checksum() == Business::ISBN::BAD_CHECKSUM;
+    $isbn->is_valid() or return;
+    return $pretty ? $isbn->as_isbn13->as_string : $isbn->as_isbn13->isbn;
+}
+
+1;
+__END__
+
+For example, if you have a file isbns.txt with these lines:
+
+1598884093
+ 1598884093
+ 15  988  840 93     
+0446357197
+  0 446 3 5  7 1 9        7
+  0 446 3 5  7 1 9        1
+0596526857
+0786222735
+0446360015
+0446350109
+0446314129
+0439139597
+0743294394
+159143047X
+1590203097
+075480965X
+0393048799
+0446831832
+0446310069
+1598883275
+0446313033
+0446360279
+
+And you run:
+    perl -pe 'use OpenILS::Utils::ISBN qw/isbn_upconvert/; $_ = isbn_upconvert($_) . "\n";' <isbns.txt
+
+You get this output:
+9781598884098
+9781598884098
+9781598884098
+9780446357197
+9780446357197
+9780446357197
+9780596526856
+9780786222735
+9780446360012
+9780446350105
+9780446314121
+9780439139595
+9780743294393
+9781591430476
+9781590203095
+9780754809654
+9780393048797
+9780446831833
+9780446310062
+9781598883275
+9780446313032
+9780446360272
+

Modified: branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Utils/MFHD.pm
===================================================================
--- branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Utils/MFHD.pm	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Utils/MFHD.pm	2010-10-18 13:46:56 UTC (rev 18371)
@@ -8,7 +8,7 @@
 
 # for inherited methods to work properly, we need to force a
 # MARC::Record version greater than 2.0.0
-use MARC::Record 2.0.1;
+use MARC::Record "2.0.1";
 use base 'MARC::Record';
 
 use OpenILS::Utils::MFHD::Caption;
@@ -19,6 +19,8 @@
     my $class = ref($proto) || $proto;
     my $self  = shift;
 
+    $self->{_strp_date} = new DateTime::Format::Strptime(pattern => '%F');
+
     $self->{_mfhd_CAPTIONS} = {};
     $self->{_mfhd_COMPRESSIBLE} = (substr($self->leader, 17, 1) =~ /[45]/);
 
@@ -250,6 +252,13 @@
       values %{$self->{_mfhd_HOLDINGS}->{$field}->{$capid}};
 }
 
+sub _holding_date {
+    my $self = shift;
+    my $holding = shift;
+
+    return $self->{_strp_date}->parse_datetime($holding->chron_to_date);
+}
+
 #
 # generate_predictions()
 # Accepts a hash ref of options initially defined as:
@@ -257,6 +266,8 @@
 # num_to_predict : the number of issues you wish to predict
 # OR
 # end_holding : holding field ref, keep predicting until you meet or exceed it
+# OR
+# end_date : keep predicting until you exceed this
 #
 # The basic method is to first convert to a single holding if compressed, then
 # increment the holding and save the resulting values to @predictions.
@@ -270,6 +281,7 @@
     my $base_holding   = $options->{base_holding};
     my $num_to_predict = $options->{num_to_predict};
     my $end_holding    = $options->{end_holding};
+    my $end_date       = $options->{end_date};
     my $max_to_predict = $options->{max_to_predict} || 10000; # fail-safe
 
     if (!defined($base_holding)) {
@@ -301,6 +313,18 @@
             }
             $next_holding = $curr_holding->increment->clone;
         }
+    } elsif (defined($end_date)) {
+        my $next_holding = $curr_holding->increment->clone;
+        my $num_predicted = 0;
+        while ($self->_holding_date($next_holding) <= $end_date) {
+            push(@predictions, $next_holding);
+            $num_predicted++;
+            if ($num_predicted >= $max_to_predict) {
+                carp("Maximum prediction count exceeded");
+                last;
+            }
+            $next_holding = $curr_holding->increment->clone;
+        }
     }
 
     return @predictions;

Modified: branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Utils/OfflineStore.pm
===================================================================
--- branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Utils/OfflineStore.pm	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Utils/OfflineStore.pm	2010-10-18 13:46:56 UTC (rev 18371)
@@ -1,6 +1,15 @@
 package OpenILS::Utils::OfflineStore;
 use strict; use warnings;
-use base 'Class::DBI';
+
+use UNIVERSAL::require;
+if ('Class::DBI::Frozen::301'->use) {
+	use parent 'Class::DBI::Frozen::301';
+} elsif ('Class::DBI'->use) {
+	use parent 'Class::DBI';
+} else {
+	die $@;
+}
+
 use DBI;
 use OpenSRF::Utils::Config;
 
@@ -40,7 +49,7 @@
 
 
 package OpenILS::Utils::OfflineStore::Session;
-use base 'OpenILS::Utils::OfflineStore';
+use parent 'OpenILS::Utils::OfflineStore';
 
 sub _create_table {
 	my $self = shift;
@@ -71,7 +80,7 @@
 
 
 package OpenILS::Utils::OfflineStore::Script;
-use base 'OpenILS::Utils::OfflineStore';
+use parent 'OpenILS::Utils::OfflineStore';
 
 sub _create_table {
 	my $self = shift;

Modified: branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Utils/RemoteAccount.pm
===================================================================
--- branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Utils/RemoteAccount.pm	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/src/perlmods/OpenILS/Utils/RemoteAccount.pm	2010-10-18 13:46:56 UTC (rev 18371)
@@ -24,7 +24,7 @@
 our %keyfiles = ();
 
 my %fields = (
-    accound_object  => undef,
+    account_object  => undef,
     remote_host     => undef,
     remote_user     => undef,
     remote_password => undef,
@@ -327,13 +327,14 @@
 # Checks if the filename part of a pathname has one or more glob characters
 # We split out the filename portion of the path
 # Detect glob or no glob.
-# return: regex for matching filenames
+# returns: directory, regex for matching filenames
 sub glob_parse {
     my $self = shift;
     my $path = shift or return;
     my ($vol, $dir, $file) = File::Spec->splitpath($path); # we don't care about attempted globs in mid-filepath
-    $file =~ /\*/ and return (File::Spec->catdir($vol, $dir), glob_to_regex($file));
-    $file =~ /\?/ and return (File::Spec->catdir($vol, $dir), glob_to_regex($file));
+    my $front = $vol ? File::Spec->catdir($vol, $dir) : $dir;
+    $file =~ /\*/ and return ($front, glob_to_regex($file));
+    $file =~ /\?/ and return ($front, glob_to_regex($file));
     $logger->debug("No glob detected in '$path'");
     return;
 }
@@ -481,18 +482,20 @@
         if ($regex) {
             my $count = scalar(@pool);
             @pool = grep {$_->{name} =~ /$regex/} @pool;
-            $logger->info("Glob regex($regex) matches " . scalar(@pool) . " of $count files"); 
-        }
+            $logger->info("SSH ls: Glob regex($regex) matches " . scalar(@pool) . " of $count files"); 
+        } # else { $logger->info("SSH ls: No Glob regex in '$target'.  Just a regular ls"); }
         push @list, @pool;
     }
     return @list;
 
 }
 
-sub _slash_path {    # not OO
+sub _slash_path {
     my $self = shift;
     my $dir  = shift || '.';
     my $file = shift || '';
+    my ($dirpath, $regex) = $self->glob_parse($dir);
+    $dir = $dirpath if $dirpath;
     return $dir . ($dir =~ /\/$/ ? '' : '/') . $file;
 }
 
@@ -552,23 +555,37 @@
     return $self->local_file;
 }
 
-sub ls_uftp {
+sub ls_uftp {   # returns full path like: dir/path/file.ext
     my $self = shift;
     my $ftp = $self->_uftp or return;
     my @list;
     foreach (@_) {
         my @part;
         my ($dirpath, $regex) = $self->glob_parse($_);
-        eval { @part = $ftp->ls($dirpath || $_) };
+        my $dirtarget = $dirpath || $_;
+        $dirtarget =~ s/\/+$//;
+        eval { @part = $ftp->ls($dirtarget) };      # this ls returns relative/path/filenames.  defer filename glob filtering for below.
         if ($@) {
             $logger->error($self->_error("ls from",  $self->remote_host, "failed with error: $@"));
             next;
         }
+        if ($dirtarget and $dirtarget ne '.' and $dirtarget ne './' and $ftp->is_dir($dirtarget)) {
+            foreach my $file (@part) {   # we ensure full(er) path
+                $file =~ /^$dirtarget\// and next;
+                $logger->debug("ls_uftp: prepending $dirtarget/ to $file");
+                $file = File::Spec->catdir($dirtarget, $file);
+            }
+        }
         if ($regex) {
             my $count = scalar(@part);
-            @part = grep {/$regex/} @part;
-            $logger->info("Glob regex($regex) matches " . scalar(@part) . " of $count files"); 
-        }
+            # @part = grep {my @a = split('/',$_); scalar(@a) ? /$regex/ : ($a[-1] =~ /$regex/)} @part;
+            my @bulk = @part;
+            @part = grep {
+                        my ($vol, $dir, $file) = File::Spec->splitpath($_);
+                        $file =~ /$regex/
+                    } @part;  
+            $logger->info("FTP ls: Glob regex($regex) matches " . scalar(@part) . " of $count files");
+        } #  else {$logger->info("FTP ls: No Glob regex in '$_'.  Just a regular ls");}
         push @list, @part;
     }
     return @list;
@@ -641,7 +658,7 @@
 	$name =~ s/.*://;   #   strip leading package stuff
 
 	unless (exists $self->{_permitted}->{$name}) {
-		croak "Cannot access '$name' field of class '$class'";
+		croak "AUTOLOAD error: Cannot access '$name' field of class '$class'";
 	}
 
 	if (@_) {

Modified: branches/serials-integration/Open-ILS/src/perlmods/OpenILS/WWW/AddedContent/ContentCafe.pm
===================================================================
--- branches/serials-integration/Open-ILS/src/perlmods/OpenILS/WWW/AddedContent/ContentCafe.pm	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/src/perlmods/OpenILS/WWW/AddedContent/ContentCafe.pm	2010-10-18 13:46:56 UTC (rev 18371)
@@ -61,7 +61,9 @@
     my $doc = XML::LibXML->new->parse_string($xml);
     $doc->documentElement->setNamespace('http://ContentCafe2.btol.com', 'cc');
     my $html = '';
-    foreach my $node ( $doc->findnodes('//cc:Toc') ) {
+    my @nodes = $doc->findnodes('//cc:Toc');
+    return 0 if (scalar(@nodes) < 1);
+    foreach my $node ( @nodes ) {
         $html .= $node->textContent . '</P></P>';
     }
     return $self->send_html($html);
@@ -87,7 +89,9 @@
     my $doc = XML::LibXML->new->parse_string($xml);
     $doc->documentElement->setNamespace('http://ContentCafe2.btol.com', 'cc');
     my $html = '';
-    foreach my $node ( $doc->findnodes('//cc:Biography') ) {
+    my @nodes = $doc->findnodes('//cc:Biography');
+    return 0 if (scalar(@nodes) < 1);
+    foreach my $node ( @nodes ) {
         $html .= '<P class="biography">' . $node->textContent . '</P>';
     }
     return $self->send_html($html);
@@ -114,7 +118,9 @@
     my $doc = XML::LibXML->new->parse_string($xml);
     $doc->documentElement->setNamespace('http://ContentCafe2.btol.com', 'cc');
     my $html = '';
-    foreach my $node ( $doc->findnodes('//cc:Excerpt') ) {
+    my @nodes = $doc->findnodes('//cc:Excerpt');
+    return 0 if (scalar(@nodes) < 1);
+    foreach my $node ( @nodes ) {
         $html .= $node->textContent;
     }
     return $self->send_html($html);
@@ -140,7 +146,9 @@
     my $doc = XML::LibXML->new->parse_string($xml);
     $doc->documentElement->setNamespace('http://ContentCafe2.btol.com', 'cc');
     my $html = '<ul>';
-    foreach my $node ( $doc->findnodes('//cc:ReviewItem') ) {
+    my @nodes = $doc->findnodes('//cc:ReviewItem');
+    return 0 if (scalar(@nodes) < 1);
+    foreach my $node ( @nodes ) {
         my @s_nodes = $node->findnodes('./cc:Supplier');
         my @p_nodes = $node->findnodes('./cc:Publication');
         my @i_nodes = $node->findnodes('./cc:Issue');
@@ -174,7 +182,9 @@
     my $doc = XML::LibXML->new->parse_string($xml);
     $doc->documentElement->setNamespace('http://ContentCafe2.btol.com', 'cc');
     my $html = '<ul>';
-    foreach my $node ( $doc->findnodes('//cc:AnnotationItem') ) {
+    my @nodes = $doc->findnodes('//cc:AnnotationItem');
+    return 0 if (scalar(@nodes) < 1);
+    foreach my $node ( @nodes ) {
         my @s_nodes = $node->findnodes('./cc:Supplier');
         my @a_nodes = $node->findnodes('./cc:Annotation');
         $html .= '<li><b>' . (scalar(@s_nodes) ? $s_nodes[0]->textContent : '') . '</b><br/>';

Modified: branches/serials-integration/Open-ILS/src/perlmods/OpenILS/WWW/Exporter.pm
===================================================================
--- branches/serials-integration/Open-ILS/src/perlmods/OpenILS/WWW/Exporter.pm	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/src/perlmods/OpenILS/WWW/Exporter.pm	2010-10-18 13:46:56 UTC (rev 18371)
@@ -114,11 +114,6 @@
 	my $tcn_v = 'tcn_value';
 	my $tcn_s = 'tcn_source';
 
-	if ($type eq 'authority') {
-		$tcn_v = 'arn_value';
-		$tcn_s = 'arn_source';
-	}
-
 	my $holdings = $cgi->param('holdings') if ($type eq 'biblio');
 	my $location = $cgi->param('location') || 'gaaagpl'; # just because...
 

Modified: branches/serials-integration/Open-ILS/src/perlmods/OpenILS/WWW/Method.pm
===================================================================
--- branches/serials-integration/Open-ILS/src/perlmods/OpenILS/WWW/Method.pm	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/src/perlmods/OpenILS/WWW/Method.pm	2010-10-18 13:46:56 UTC (rev 18371)
@@ -155,5 +155,7 @@
 	return 1;
 }
 
+# This module appears unfinshed and/or obsolete with many unconditional warns/dumps.
+# File is not referenced elsewhere in the codebase.  Candidate for deletion.
 
 1;

Modified: branches/serials-integration/Open-ILS/src/perlmods/OpenILS/WWW/Redirect.pm
===================================================================
--- branches/serials-integration/Open-ILS/src/perlmods/OpenILS/WWW/Redirect.pm	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/src/perlmods/OpenILS/WWW/Redirect.pm	2010-10-18 13:46:56 UTC (rev 18371)
@@ -56,13 +56,18 @@
 	my $apache_obj = shift;
 	my $cgi = CGI->new( $apache_obj );
 
+
+	my $skin = $apache_obj->dir_config('OILSRedirectSkin') || 'default';
+	my $depth = $apache_obj->dir_config('OILSRedirectDepth');
+	my $locale = $apache_obj->dir_config('OILSRedirectLocale') || 'en-US';
+
 	my $hostname = $cgi->server_name();
 	my $port		= $cgi->server_port();
 
 	my $proto = "http";
 	if($cgi->https) { $proto = "https"; }
 
-	my $url = "$proto://$hostname:$port/opac/en-US/skin/default/xml/index.xml";
+	my $url = "$proto://$hostname:$port/opac/$locale/skin/$skin/xml/index.xml";
 
 	my $path = $apache_obj->path_info();
 
@@ -77,7 +82,10 @@
             'open-ils.actor.org_unit.retrieve_by_shortname',
 			 $shortname)->gather(1);
 
-		if($org) { $url .= "?ol=" . $org->id; }
+		if($org) { 
+            $url .= "?ol=" . $org->id; 
+            $url .= "&d=$depth" if defined $depth;
+        }
 	}
 
 	print "Location: $url\n\n"; 

Modified: branches/serials-integration/Open-ILS/src/perlmods/OpenILS/WWW/SuperCat.pm
===================================================================
--- branches/serials-integration/Open-ILS/src/perlmods/OpenILS/WWW/SuperCat.pm	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/src/perlmods/OpenILS/WWW/SuperCat.pm	2010-10-18 13:46:56 UTC (rev 18371)
@@ -1334,7 +1334,6 @@
 	my $lib = uc(shift()) || '-';
 	my $depth = shift;
 	my $flesh = shift;
-	$flesh = 1 if (!defined($flesh));
 
 	my $paging = shift;
 
@@ -1348,7 +1347,7 @@
 
     my $tag_prefix = sprintf("tag:open-ils.org,$year-\%0.2d-\%0.2d", $month, $day);
 
-	my $flesh_feed = parse_feed_type($type);
+	my $flesh_feed = defined($flesh) ? $flesh : parse_feed_type($type);
 
 	$type =~ s/(-full|-uris)$//o;
 

Modified: branches/serials-integration/Open-ILS/src/perlmods/OpenILS/WWW/Web.pm
===================================================================
--- branches/serials-integration/Open-ILS/src/perlmods/OpenILS/WWW/Web.pm	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/src/perlmods/OpenILS/WWW/Web.pm	2010-10-18 13:46:56 UTC (rev 18371)
@@ -1,11 +1,12 @@
 package OpenILS::WWW::Web;
-use strict; use warnings;
+use strict;
+use warnings;
 
 use Apache2::Log;
 use Apache2::Const -compile => qw(OK REDIRECT :log);
-use APR::Const    -compile => qw(:error SUCCESS);
+use APR::Const     -compile => qw(:error SUCCESS);
 use Apache2::RequestRec ();
-use Apache2::RequestIO ();
+use Apache2::RequestIO  ();
 use Apache2::RequestUtil;
 
 #use CGI ();
@@ -14,81 +15,88 @@
 use OpenSRF::EX qw(:try);
 use OpenSRF::System;
 
-my $main_ttk = "opac/logic/page_router.ttk";
-my $error_ttk = "opac/pages/error.ttk";
-my $init_ttk = "opac/logic/page_init.ttk";
-my $bootstrap = "SYSCONFDIR/opensrf_core.xml";
+my $main_ttk       = "opac/logic/page_router.ttk";
+my $error_ttk      = "opac/pages/error.ttk";
+my $init_ttk       = "opac/logic/page_init.ttk";
+my $bootstrap      = "SYSCONFDIR/opensrf_core.xml";
 my $child_init_ttk = "opac/logic/child_init.ttk";
 
-my $includes = [];  # [  '/pines/cvs/ILS/Open-ILS/src/templates' ];
+my $includes = [];    # [  '/pines/cvs/ILS/Open-ILS/src/templates' ];
 
 sub import {
-	my( $self, $tdir ) = @_;
-	$includes = [ $tdir ];
+    my ( $self, $tdir ) = @_;
+    $includes = [$tdir];
 }
 
-
-
 my $plugin_base = 'OpenILS::Template::Plugin';
 
 sub handler {
 
-	my $apache = shift;
-	print "Content-type: text/html; charset=utf-8\n\n";
+    my $apache = shift;
+    print "Content-type: text/html; charset=utf-8\n\n";
 
-	_process_template(
-			apache		=> $apache,
-			template		=> $main_ttk,
-			pre_process	=> $init_ttk );
+    _process_template(
+        apache      => $apache,
+        template    => $main_ttk,
+        pre_process => $init_ttk
+    );
 
-	return Apache2::Const::OK;
+    return Apache2::Const::OK;
 }
 
 sub child_init_handler {
-	_process_template(  template => $child_init_ttk );
+    _process_template( template => $child_init_ttk );
 }
 
 sub _process_template {
 
-	my %params = @_;
-	my $ttk				= $params{template}		|| return undef;
-	my $apache			= $params{apache}			|| undef;
-	my $pre_process	= $params{pre_process}	|| undef;
-	my $param_hash		= $params{params}			|| {};
+    my %params      = @_;
+    my $ttk         = $params{template}    || return undef;
+    my $apache      = $params{apache}      || undef;
+    my $pre_process = $params{pre_process} || undef;
+    my $param_hash  = $params{params}      || {};
 
-	my $template;
+    my $template;
 
-	$template = Template->new( { 
-		OUTPUT			=> $apache, 
-		ABSOLUTE			=> 1, 
-		RELATIVE			=> 1,
-		PLUGIN_BASE		=> $plugin_base,
-		PRE_PROCESS		=> $pre_process,
-		INCLUDE_PATH	=> $includes, 
-		PRE_CHOMP		=> 1,
-		POST_CHOMP		=> 1,
-		} 
-	);
+    $template = Template->new(
+        {
+            OUTPUT       => $apache,
+            ABSOLUTE     => 1,
+            RELATIVE     => 1,
+            PLUGIN_BASE  => $plugin_base,
+            PRE_PROCESS  => $pre_process,
+            INCLUDE_PATH => $includes,
+            PRE_CHOMP    => 1,
+            POST_CHOMP   => 1,
+        }
+    );
 
-	try {
+    try {
 
-		if( ! $template->process( $ttk, $param_hash ) ) { 
-			warn  "Error Occured: " . $template->error();
-			my $err = $template->error();
-			$err =~ s/\n/\<br\/\>/g;
-			warn "Error processing template $ttk\n";	
-			my $string =  "<br><b>Unable to process template:<br/><br/> " . $err . "!!!</b>";
-			$template->process( $error_ttk , { error => $string } );
-		}
+        if ( !$template->process( $ttk, $param_hash ) ) {
+            warn "Error Occured: " . $template->error();
+            my $err = $template->error();
+            $err =~ s/\n/\<br\/\>/g;
+            warn "Error processing template $ttk\n";
+            my $string =
+                "<br><b>Unable to process template:<br/><br/> " 
+              . $err
+              . "!!!</b>";
+            $template->process( $error_ttk, { error => $string } );
+        }
 
-	} catch Error with {
-		my $e = shift;
-		warn "Error processing template $ttk:  $e - $@ \n";	
-		print "<center><br/><br/><b>Error<br/><br/> $e <br/><br/> $@ </b><br/></center>";
-		return;
-	};
+    }
+    catch Error with {
+        my $e = shift;
+        warn "Error processing template $ttk:  $e - $@ \n";
+        print "<center><br/><br/><b>Error<br/><br/> $e <br/><br/> $@ </b><br/></center>";
+        return;
+    };
 
 }
 
+# This module appears obsolete (probably superceded by EGWeb.pm
+# The template files it references do not exist in the codebase.
+# File is not referenced elsewhere in the codebase.  Candidate for deletion.
 
 1;

Modified: branches/serials-integration/Open-ILS/src/reporter/clark-kent.pl
===================================================================
--- branches/serials-integration/Open-ILS/src/reporter/clark-kent.pl	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/src/reporter/clark-kent.pl	2010-10-18 13:46:56 UTC (rev 18371)
@@ -50,50 +50,48 @@
 my $sc = OpenSRF::Utils::SettingsClient->new;
 
 $data_db{db_driver} = $sc->config_value( reporter => setup => database => 'driver' );
-$data_db{db_host} = $sc->config_value( reporter => setup => database => 'host' );
-$data_db{db_port} = $sc->config_value( reporter => setup => database => 'port' );
-$data_db{db_name} = $sc->config_value( reporter => setup => database => 'db' );
+$data_db{db_host}   = $sc->config_value( reporter => setup => database => 'host' );
+$data_db{db_port}   = $sc->config_value( reporter => setup => database => 'port' );
+$data_db{db_name}   = $sc->config_value( reporter => setup => database => 'db' );
 if (!$data_db{db_name}) {
     $data_db{db_name} = $sc->config_value( reporter => setup => database => 'name' );
     print STDERR "WARN: <database><name> is a deprecated setting for database name. For future compatibility, you should use <database><db> instead." if $data_db{db_name}; 
 }
-$data_db{db_user} = $sc->config_value( reporter => setup => database => 'user' );
-$data_db{db_pw} = $sc->config_value( reporter => setup => database => 'pw' );
+$data_db{db_user}   = $sc->config_value( reporter => setup => database => 'user' );
+$data_db{db_pw}     = $sc->config_value( reporter => setup => database => 'pw' );
 
 
 
 # Fetch the optional state database connection info
 $state_db{db_driver} = $sc->config_value( reporter => setup => state_store => 'driver' ) || $data_db{db_driver};
-$state_db{db_host} = $sc->config_value( reporter => setup => state_store => 'host' ) || $data_db{db_host};
-$state_db{db_port} = $sc->config_value( reporter => setup => state_store => 'port' ) || $data_db{db_port};
-$state_db{db_name} = $sc->config_value( reporter => setup => state_store => 'db' );
+$state_db{db_host}   = $sc->config_value( reporter => setup => state_store => 'host'   ) || $data_db{db_host};
+$state_db{db_port}   = $sc->config_value( reporter => setup => state_store => 'port'   ) || $data_db{db_port};
+$state_db{db_name}   = $sc->config_value( reporter => setup => state_store => 'db'     );
 if (!$state_db{db_name}) {
     $state_db{db_name} = $sc->config_value( reporter => setup => state_store => 'name' ) || $data_db{db_name};
 }
-$state_db{db_user} = $sc->config_value( reporter => setup => state_store => 'user' ) || $data_db{db_user};
-$state_db{db_pw} = $sc->config_value( reporter => setup => state_store => 'pw' ) || $data_db{db_pw};
+$state_db{db_user}   = $sc->config_value( reporter => setup => state_store => 'user'   ) || $data_db{db_user};
+$state_db{db_pw}     = $sc->config_value( reporter => setup => state_store => 'pw'     ) || $data_db{db_pw};
 
 
 die "Unable to retrieve database connection information from the settings server"
     unless ($state_db{db_driver} && $state_db{db_host} && $state_db{db_port} && $state_db{db_name} && $state_db{db_user} &&
         $data_db{db_driver} && $data_db{db_host} && $data_db{db_port} && $data_db{db_name} && $data_db{db_user});
 
-my $email_server = $sc->config_value( email_notify => 'smtp_server' );
-my $email_sender = $sc->config_value( email_notify => 'sender_address' );
+my $email_server     = $sc->config_value( email_notify => 'smtp_server' );
+my $email_sender     = $sc->config_value( email_notify => 'sender_address' );
 my $success_template = $sc->config_value( reporter => setup => files => 'success_template' );
-my $fail_template = $sc->config_value( reporter => setup => files => 'fail_template' );
+my $fail_template    = $sc->config_value( reporter => setup => files => 'fail_template' );
+my $output_base      = $sc->config_value( reporter => setup => files => 'output_base' );
+my $base_uri         = $sc->config_value( reporter => setup => 'base_uri' );
 
-my $output_base = $sc->config_value( reporter => setup => files => 'output_base' );
-
-my $base_uri = $sc->config_value( reporter => setup => 'base_uri' );
-
 my $state_dsn = "dbi:" . $state_db{db_driver} . ":dbname=" . $state_db{db_name} .';host=' . $state_db{db_host} . ';port=' . $state_db{db_port};
-my $data_dsn = "dbi:" . $data_db{db_driver} . ":dbname=" . $data_db{db_name} .';host=' . $data_db{db_host} . ';port=' . $data_db{db_port};
+my $data_dsn  = "dbi:" .  $data_db{db_driver} . ":dbname=" .  $data_db{db_name} .';host=' .  $data_db{db_host} . ';port=' .  $data_db{db_port};
 
 my ($dbh,$running,$sth, at reports,$run, $current_time);
 
 if ($daemon) {
-	open(F, ">$lockfile");
+	open(F, ">$lockfile") or die "Cannot write lockfile '$lockfile'";
 	print F $$;
 	close F;
 	daemonize("Clark Kent, waiting for trouble");
@@ -307,7 +305,7 @@
 			SELECT * FROM reporter.schedule WHERE id = ?;
 		SQL
 
-		$r->{start_time} = $new_r->{start_time};
+		$r->{start_time}    = $new_r->{start_time};
 		$r->{complete_time} = $new_r->{complete_time};
 
 		if ($r->{email}) {
@@ -332,7 +330,7 @@
 			SELECT * FROM reporter.schedule WHERE id = ?;
 		SQL
 
-		$r->{error_text} = $new_r->{error_text};
+		$r->{error_text}    = $new_r->{error_text};
 		$r->{complete_time} = $new_r->{complete_time};
 
 		if ($r->{email}) {
@@ -358,7 +356,7 @@
 
 sub send_success {
 	my $r = shift;
-	open F, $success_template;
+	open F, $success_template or die "Cannot read '$success_template'";
 	my $tmpl = join('',<F>);
 	close F;
 
@@ -382,7 +380,7 @@
 
 sub send_fail {
 	my $r = shift;
-	open F, $fail_template;
+	open F, $fail_template or die "Cannot read '$fail_template'";
 	my $tmpl = join('',<F>);
 	close F;
 
@@ -409,7 +407,7 @@
 
 	return unless ($csv);
 	
-	my $f = new FileHandle (">$file");
+	my $f = new FileHandle (">$file") or die "Cannot write to '$file'";
 
 	$csv->print($f, $r->{column_labels});
 	$csv->print($f, $_) for (@{$r->{data}});
@@ -437,7 +435,7 @@
 	my $file = shift;
 	my $r = shift;
 
-	my $index = new FileHandle (">$file");
+	my $index = new FileHandle (">$file") or die "Cannot write to '$file'";
 	
 	# index header
 	print $index <<"	HEADER";
@@ -459,6 +457,7 @@
 
 	my @links;
 
+    my $br4 = '<br/>' x 4;
 	# add a link to the raw output html
 	push @links, "<a href='report-data.html.raw.html'>Tabular Output</a>" if ($r->{html_format});
 
@@ -469,11 +468,11 @@
 	push @links, "<a href='report-data.csv'>CSV Output</a>" if ($r->{csv_format});
 
 	print $index join(' -- ', @links);
-	print $index "<br/><br/><br/><br/></center>";
+	print $index "$br4</center>";
 
 	if ($r->{html_format}) {
 		# create the raw output html file
-		my $raw = new FileHandle (">$file.raw.html");
+		my $raw = new FileHandle (">$file.raw.html") or die "Cannot write to '$file.raw.html'";
 		print $raw "<html><head><title>$$r{report}{name}</title>";
 
 		print $raw <<'		CSS';
@@ -501,25 +500,25 @@
 	if ($r->{chart_pie}) {
 		my $pics = draw_pie($r, $file);
 		for my $pic (@$pics) {
-			print $index "<img src='report-data.html.$pic->{file}' alt='$pic->{name}'/><br/><br/><br/><br/>";
+			print $index "<img src='report-data.html.$pic->{file}' alt='$pic->{name}'/>$br4";
 		}
 	}
 
-	print $index '<br/><br/><br/><br/>';
+	print $index $br4;
 	# Time for a bar chart
 	if ($r->{chart_bar}) {
 		my $pics = draw_bars($r, $file);
 		for my $pic (@$pics) {
-			print $index "<img src='report-data.html.$pic->{file}' alt='$pic->{name}'/><br/><br/><br/><br/>";
+			print $index "<img src='report-data.html.$pic->{file}' alt='$pic->{name}'/>$br4";
 		}
 	}
 
-	print $index '<br/><br/><br/><br/>';
+	print $index $br4;
 	# Time for a bar chart
 	if ($r->{chart_line}) {
 		my $pics = draw_lines($r, $file);
 		for my $pic (@$pics) {
-			print $index "<img src='report-data.html.$pic->{file}' alt='$pic->{name}'/><br/><br/><br/><br/>";
+			print $index "<img src='report-data.html.$pic->{file}' alt='$pic->{name}'/>$br4";
 		}
 	}
 
@@ -585,7 +584,7 @@
 
 			my $format = $pic->export_format;
 
-			open(IMG, ">$file.pie.$vcol.$sub_graph.$format");
+			open(IMG, ">$file.pie.$vcol.$sub_graph.$format") or die "Cannot write '$file.pie.$vcol.$sub_graph.$format'";
 			binmode IMG;
 
 			my $forgetit = 0;
@@ -709,7 +708,7 @@
 
 	my $format = $pic->export_format;
 
-	open(IMG, ">$file.bar.$format");
+	open(IMG, ">$file.bar.$format") or die "Cannot write '$file.bar.$format'";
 	binmode IMG;
 
 	try {
@@ -729,7 +728,7 @@
 }
 
 sub draw_lines {
-	my $r = shift;
+	my $r    = shift;
 	my $file = shift;
 	my $data = $r->{data};
 
@@ -815,7 +814,7 @@
 
 	my $format = $pic->export_format;
 
-	open(IMG, ">$file.line.$format");
+	open(IMG, ">$file.line.$format") or die "Cannot write '$file.line.$format'";
 	binmode IMG;
 
 	try {
@@ -836,10 +835,10 @@
 
 
 sub pivot_data {
-	my $blob = shift;
+	my $blob        = shift;
 	my $pivot_label = shift;
-	my $pivot_data = shift;
-	my $default = shift;
+	my $pivot_data  = shift;
+	my $default     = shift;
 	$default = 0 unless (defined $default);
 
 	my $data = $$blob{data};

Modified: branches/serials-integration/Open-ILS/src/sql/Pg/002.functions.config.sql
===================================================================
--- branches/serials-integration/Open-ILS/src/sql/Pg/002.functions.config.sql	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/src/sql/Pg/002.functions.config.sql	2010-10-18 13:46:56 UTC (rev 18371)
@@ -437,8 +437,6 @@
             NEW.marc,
             E'(</(?:[^:]*?:)?record>)',
             E'<datafield tag="901" ind1=" " ind2=" ">' ||
-                '<subfield code="a">' || NEW.arn_value || E'</subfield>' ||
-                '<subfield code="b">' || NEW.arn_source || E'</subfield>' ||
                 '<subfield code="c">' || NEW.id || E'</subfield>' ||
                 '<subfield code="t">' || TG_TABLE_SCHEMA || E'</subfield>' ||
              E'</datafield>\\1'

Modified: branches/serials-integration/Open-ILS/src/sql/Pg/002.schema.config.sql
===================================================================
--- branches/serials-integration/Open-ILS/src/sql/Pg/002.schema.config.sql	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/src/sql/Pg/002.schema.config.sql	2010-10-18 13:46:56 UTC (rev 18371)
@@ -52,11 +52,13 @@
     enabled BOOL    NOT NULL DEFAULT FALSE
 );
 INSERT INTO config.internal_flag (name) VALUES ('ingest.metarecord_mapping.skip_on_insert');
+INSERT INTO config.internal_flag (name) VALUES ('ingest.metarecord_mapping.skip_on_update');
 INSERT INTO config.internal_flag (name) VALUES ('ingest.reingest.force_on_same_marc');
 INSERT INTO config.internal_flag (name) VALUES ('ingest.disable_located_uri');
 INSERT INTO config.internal_flag (name) VALUES ('ingest.disable_metabib_full_rec');
 INSERT INTO config.internal_flag (name) VALUES ('ingest.disable_metabib_rec_descriptor');
 INSERT INTO config.internal_flag (name) VALUES ('ingest.disable_metabib_field_entry');
+INSERT INTO config.internal_flag (name) VALUES ('ingest.assume_inserts_only');
 
 CREATE TABLE config.global_flag (
     label   TEXT    NOT NULL
@@ -68,7 +70,7 @@
     install_date    TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW()
 );
 
-INSERT INTO config.upgrade_log (version) VALUES ('0375'); -- miker
+INSERT INTO config.upgrade_log (version) VALUES ('0412'); -- phasefx
 
 CREATE TABLE config.bib_source (
 	id		SERIAL	PRIMARY KEY,
@@ -647,6 +649,34 @@
 
 CREATE UNIQUE INDEX i18n_identity ON config.i18n_core (fq_field,identity_value,translation);
 
+CREATE OR REPLACE FUNCTION oils_i18n_update_apply(old_ident TEXT, new_ident TEXT, hint TEXT) RETURNS VOID AS $_$
+BEGIN
+
+    EXECUTE $$
+        UPDATE  config.i18n_core
+          SET   identity_value = $$ || quote_literal(new_ident) || $$ 
+          WHERE fq_field LIKE '$$ || hint || $$.%' 
+                AND identity_value = $$ || quote_literal(old_ident) || $$::TEXT;$$;
+
+    RETURN;
+
+END;
+$_$ LANGUAGE PLPGSQL;
+
+CREATE OR REPLACE FUNCTION oils_i18n_id_tracking(/* hint */) RETURNS TRIGGER AS $_$
+BEGIN
+    PERFORM oils_i18n_update_apply( OLD.id::TEXT, NEW.id::TEXT, TG_ARGV[0]::TEXT );
+    RETURN NEW;
+END;
+$_$ LANGUAGE PLPGSQL;
+
+CREATE OR REPLACE FUNCTION oils_i18n_code_tracking(/* hint */) RETURNS TRIGGER AS $_$
+BEGIN
+    PERFORM oils_i18n_update_apply( OLD.code::TEXT, NEW.code::TEXT, TG_ARGV[0]::TEXT );
+    RETURN NEW;
+END;
+$_$ LANGUAGE PLPGSQL;
+
 CREATE TABLE config.billing_type (
     id              SERIAL  PRIMARY KEY,
     name            TEXT    NOT NULL,

Modified: branches/serials-integration/Open-ILS/src/sql/Pg/005.schema.actors.sql
===================================================================
--- branches/serials-integration/Open-ILS/src/sql/Pg/005.schema.actors.sql	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/src/sql/Pg/005.schema.actors.sql	2010-10-18 13:46:56 UTC (rev 18371)
@@ -93,6 +93,7 @@
 $$;
 
 CREATE INDEX actor_usr_home_ou_idx ON actor.usr (home_ou);
+CREATE INDEX actor_usr_usrgroup_idx ON actor.usr (usrgroup);
 CREATE INDEX actor_usr_mailing_address_idx ON actor.usr (mailing_address);
 CREATE INDEX actor_usr_billing_address_idx ON actor.usr (billing_address);
 
@@ -315,6 +316,7 @@
 $$;
 
 CREATE INDEX actor_card_usr_idx ON actor.card (usr);
+CREATE INDEX actor_card_barcode_lower_idx ON actor.card (lower(barcode));
 
 CREATE TABLE actor.org_unit_type (
 	id		SERIAL	PRIMARY KEY,

Modified: branches/serials-integration/Open-ILS/src/sql/Pg/006.schema.permissions.sql
===================================================================
--- branches/serials-integration/Open-ILS/src/sql/Pg/006.schema.permissions.sql	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/src/sql/Pg/006.schema.permissions.sql	2010-10-18 13:46:56 UTC (rev 18371)
@@ -27,6 +27,9 @@
 	description	TEXT
 );
 CREATE INDEX perm_list_code_idx ON permission.perm_list (code);
+CREATE TRIGGER maintain_perm_i18n_tgr
+    AFTER UPDATE ON permission.perm_list
+    FOR EACH ROW EXECUTE PROCEDURE oils_i18n_id_tracking('ppl');
 
 CREATE TABLE permission.grp_tree (
 	id			SERIAL	PRIMARY KEY,
@@ -51,7 +54,7 @@
 CREATE TABLE permission.grp_perm_map (
 	id		SERIAL	PRIMARY KEY,
 	grp		INT	NOT NULL REFERENCES permission.grp_tree (id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED,
-	perm		INT	NOT NULL REFERENCES permission.perm_list (id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED,
+	perm		INT	NOT NULL REFERENCES permission.perm_list (id) ON UPDATE CASCADE ON DELETE RESTRICT DEFERRABLE INITIALLY DEFERRED,
 	depth		INT	NOT NULL,
 	grantable	BOOL	NOT NULL DEFAULT FALSE,
 		CONSTRAINT perm_grp_once UNIQUE (grp,perm)
@@ -60,7 +63,7 @@
 CREATE TABLE permission.usr_perm_map (
 	id		SERIAL	PRIMARY KEY,
 	usr		INT	NOT NULL REFERENCES actor.usr (id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED,
-	perm		INT	NOT NULL REFERENCES permission.perm_list (id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED,
+	perm		INT	NOT NULL REFERENCES permission.perm_list (id) ON UPDATE CASCADE ON DELETE RESTRICT DEFERRABLE INITIALLY DEFERRED,
 	depth		INT	NOT NULL,
 	grantable	BOOL	NOT NULL DEFAULT FALSE,
 		CONSTRAINT perm_usr_once UNIQUE (usr,perm)
@@ -69,7 +72,7 @@
 CREATE TABLE permission.usr_object_perm_map (
 	id		SERIAL	PRIMARY KEY,
 	usr		INT	NOT NULL REFERENCES actor.usr (id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED,
-	perm		INT	NOT NULL REFERENCES permission.perm_list (id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED,
+	perm		INT	NOT NULL REFERENCES permission.perm_list (id) ON UPDATE CASCADE ON DELETE RESTRICT DEFERRABLE INITIALLY DEFERRED,
     object_type TEXT NOT NULL,
     object_id   TEXT NOT NULL,
 	grantable	BOOL	NOT NULL DEFAULT FALSE,

Modified: branches/serials-integration/Open-ILS/src/sql/Pg/011.schema.authority.sql
===================================================================
--- branches/serials-integration/Open-ILS/src/sql/Pg/011.schema.authority.sql	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/src/sql/Pg/011.schema.authority.sql	2010-10-18 13:46:56 UTC (rev 18371)
@@ -24,8 +24,6 @@
 
 CREATE TABLE authority.record_entry (
 	id		BIGSERIAL	PRIMARY KEY,
-	arn_source	TEXT		NOT NULL DEFAULT 'AUTOGEN',
-	arn_value	TEXT		NOT NULL,
 	creator		INT		NOT NULL DEFAULT 1,
 	editor		INT		NOT NULL DEFAULT 1,
 	create_date	TIMESTAMP WITH TIME ZONE	NOT NULL DEFAULT now(),
@@ -39,7 +37,6 @@
 );
 CREATE INDEX authority_record_entry_creator_idx ON authority.record_entry ( creator );
 CREATE INDEX authority_record_entry_editor_idx ON authority.record_entry ( editor );
-CREATE UNIQUE INDEX authority_record_unique_tcn ON authority.record_entry (arn_source,arn_value) WHERE deleted = FALSE OR deleted IS FALSE;
 CREATE TRIGGER a_marcxml_is_well_formed BEFORE INSERT OR UPDATE ON authority.record_entry FOR EACH ROW EXECUTE PROCEDURE biblio.check_marcxml_well_formed();
 CREATE TRIGGER b_maintain_901 BEFORE INSERT OR UPDATE ON authority.record_entry FOR EACH ROW EXECUTE PROCEDURE maintain_901();
 CREATE TRIGGER c_maintain_control_numbers BEFORE INSERT OR UPDATE ON authority.record_entry FOR EACH ROW EXECUTE PROCEDURE maintain_control_numbers();

Modified: branches/serials-integration/Open-ILS/src/sql/Pg/020.schema.functions.sql
===================================================================
--- branches/serials-integration/Open-ILS/src/sql/Pg/020.schema.functions.sql	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/src/sql/Pg/020.schema.functions.sql	2010-10-18 13:46:56 UTC (rev 18371)
@@ -257,3 +257,91 @@
 */
 $$;
 
+-- Intended to be used in a unique index on authority.record_entry like so:
+-- CREATE UNIQUE INDEX unique_by_heading_and_thesaurus
+--   ON authority.record_entry (authority.normalize_heading(marc))
+--   WHERE deleted IS FALSE or deleted = FALSE;
+CREATE OR REPLACE FUNCTION authority.normalize_heading( TEXT ) RETURNS TEXT AS $func$
+    use strict;
+    use warnings;
+
+    use utf8;
+    use MARC::Record;
+    use MARC::File::XML (BinaryEncoding => 'UTF8');
+    use UUID::Tiny ':std';
+
+    my $xml = shift() or return undef;
+
+    my $r;
+
+    # Prevent errors in XML parsing from blowing out ungracefully
+    eval {
+        $r = MARC::Record->new_from_xml( $xml );
+        1;
+    } or do {
+       return 'BAD_MARCXML_' . create_uuid_as_string(UUID_MD5, $xml);
+    };
+
+    if (!$r) {
+       return 'BAD_MARCXML_' . create_uuid_as_string(UUID_MD5, $xml);
+    }
+
+    # From http://www.loc.gov/standards/sourcelist/subject.html
+    my $thes_code_map = {
+        a => 'lcsh',
+        b => 'lcshac',
+        c => 'mesh',
+        d => 'nal',
+        k => 'cash',
+        n => 'notapplicable',
+        r => 'aat',
+        s => 'sears',
+        v => 'rvm',
+    };
+
+    # Default to "No attempt to code" if the leader is horribly broken
+    my $fixed_field = $r->field('008');
+    my $thes_char = '|';
+    if ($fixed_field) { 
+        $thes_char = substr($fixed_field->data(), 11, 1) || '|';
+    }
+
+    my $thes_code = 'UNDEFINED';
+
+    if ($thes_char eq 'z') {
+        # Grab the 040 $f per http://www.loc.gov/marc/authority/ad040.html
+        $thes_code = $r->subfield('040', 'f') || 'UNDEFINED';
+    } elsif ($thes_code_map->{$thes_char}) {
+        $thes_code = $thes_code_map->{$thes_char};
+    }
+
+    my $auth_txt = '';
+    my $head = $r->field('1..');
+    if ($head) {
+        # Concatenate all of these subfields together, prefixed by their code
+        # to prevent collisions along the lines of "Fiction, North Carolina"
+        foreach my $sf ($head->subfields()) {
+            $auth_txt .= '‡' . $sf->[0] . ' ' . $sf->[1];
+        }
+    }
+    
+    # Perhaps better to parameterize the spi and pass as a parameter
+    $auth_txt =~ s/'//go;
+
+    if ($auth_txt) {
+        my $result = spi_exec_query("SELECT public.naco_normalize('$auth_txt') AS norm_text");
+        my $norm_txt = $result->{rows}[0]->{norm_text};
+        return $head->tag() . "_" . $thes_code . " " . $norm_txt;
+    }
+
+    return 'NOHEADING_' . $thes_code . ' ' . create_uuid_as_string(UUID_MD5, $xml);
+$func$ LANGUAGE 'plperlu' IMMUTABLE;
+
+COMMENT ON FUNCTION authority.normalize_heading( TEXT ) IS $$
+/**
+* Extract the authority heading, thesaurus, and NACO-normalized values
+* from an authority record. The primary purpose is to build a unique
+* index to defend against duplicated authority records from the same
+* thesaurus.
+*/
+$$;

Modified: branches/serials-integration/Open-ILS/src/sql/Pg/030.schema.metabib.sql
===================================================================
--- branches/serials-integration/Open-ILS/src/sql/Pg/030.schema.metabib.sql	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/src/sql/Pg/030.schema.metabib.sql	2010-10-18 13:46:56 UTC (rev 18371)
@@ -707,7 +707,10 @@
 
 CREATE OR REPLACE FUNCTION metabib.reingest_metabib_rec_descriptor( bib_id BIGINT ) RETURNS VOID AS $func$
 BEGIN
-    DELETE FROM metabib.rec_descriptor WHERE record = bib_id;
+    PERFORM * FROM config.internal_flag WHERE name = 'ingest.assume_inserts_only' AND enabled;
+    IF NOT FOUND THEN
+        DELETE FROM metabib.rec_descriptor WHERE record = bib_id;
+    END IF;
     INSERT INTO metabib.rec_descriptor (record, item_type, item_form, bib_level, control_type, enc_level, audience, lit_form, type_mat, cat_form, pub_status, item_lang, vr_format, date1, date2)
         SELECT  bib_id,
                 biblio.marc21_extract_fixed_field( bib_id, 'Type' ),
@@ -735,7 +738,10 @@
 
 CREATE OR REPLACE FUNCTION metabib.reingest_metabib_full_rec( bib_id BIGINT ) RETURNS VOID AS $func$
 BEGIN
-    DELETE FROM metabib.real_full_rec WHERE record = bib_id;
+    PERFORM * FROM config.internal_flag WHERE name = 'ingest.assume_inserts_only' AND enabled;
+    IF NOT FOUND THEN
+        DELETE FROM metabib.real_full_rec WHERE record = bib_id;
+    END IF;
     INSERT INTO metabib.real_full_rec (record, tag, ind1, ind2, subfield, value)
         SELECT record, tag, ind1, ind2, subfield, value FROM biblio.flatten_marc( bib_id );
 
@@ -748,13 +754,15 @@
     fclass          RECORD;
     ind_data        metabib.field_entry_template%ROWTYPE;
 BEGIN
-    FOR fclass IN SELECT * FROM config.metabib_class LOOP
-        -- RAISE NOTICE 'Emptying out %', fclass.name;
-        EXECUTE $$DELETE FROM metabib.$$ || fclass.name || $$_field_entry WHERE source = $$ || bib_id;
-    END LOOP;
+    PERFORM * FROM config.internal_flag WHERE name = 'ingest.assume_inserts_only' AND enabled;
+    IF NOT FOUND THEN
+        FOR fclass IN SELECT * FROM config.metabib_class LOOP
+            -- RAISE NOTICE 'Emptying out %', fclass.name;
+            EXECUTE $$DELETE FROM metabib.$$ || fclass.name || $$_field_entry WHERE source = $$ || bib_id;
+        END LOOP;
+        DELETE FROM metabib.facet_entry WHERE source = bib_id;
+    END IF;
 
-    DELETE FROM metabib.facet_entry WHERE source = bib_id;
-
     FOR ind_data IN SELECT * FROM biblio.extract_metabib_field_entry( bib_id ) LOOP
         IF ind_data.field < 0 THEN
             ind_data.field = -1 * ind_data.field;
@@ -964,7 +972,10 @@
             PERFORM metabib.remap_metarecord_for_bib( NEW.id, NEW.fingerprint );
         END IF;
     ELSE -- we're doing an update, and we're not deleted, remap
-        PERFORM metabib.remap_metarecord_for_bib( NEW.id, NEW.fingerprint );
+        PERFORM * FROM config.internal_flag WHERE name = 'ingest.metarecord_mapping.skip_on_update' AND enabled;
+        IF NOT FOUND THEN
+            PERFORM metabib.remap_metarecord_for_bib( NEW.id, NEW.fingerprint );
+        END IF;
     END IF;
 
     RETURN NEW;

Modified: branches/serials-integration/Open-ILS/src/sql/Pg/040.schema.asset.sql
===================================================================
--- branches/serials-integration/Open-ILS/src/sql/Pg/040.schema.asset.sql	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/src/sql/Pg/040.schema.asset.sql	2010-10-18 13:46:56 UTC (rev 18371)
@@ -29,6 +29,8 @@
 	hold_verify	BOOL	NOT NULL DEFAULT FALSE,
 	opac_visible	BOOL	NOT NULL DEFAULT TRUE,
 	circulate	BOOL	NOT NULL DEFAULT TRUE,
+	label_prefix	TEXT,
+	label_suffix	TEXT,
 	CONSTRAINT acl_name_once_per_lib UNIQUE (name, owning_lib)
 );
 
@@ -158,6 +160,7 @@
 	value		TEXT				NOT NULL
 );
 CREATE INDEX asset_copy_note_creator_idx ON asset.copy_note ( creator );
+CREATE INDEX asset_copy_note_owning_copy_idx ON asset.copy_note ( owning_copy );
 
 CREATE TABLE asset.uri (
     id  SERIAL  PRIMARY KEY,

Copied: branches/serials-integration/Open-ILS/src/sql/Pg/1.6.1-2.0-upgrade-db.sql (from rev 17886, trunk/Open-ILS/src/sql/Pg/1.6.1-2.0-upgrade-db.sql)
===================================================================
--- branches/serials-integration/Open-ILS/src/sql/Pg/1.6.1-2.0-upgrade-db.sql	                        (rev 0)
+++ branches/serials-integration/Open-ILS/src/sql/Pg/1.6.1-2.0-upgrade-db.sql	2010-10-18 13:46:56 UTC (rev 18371)
@@ -0,0 +1,18106 @@
+BEGIN;
+
+-- Highest-numbered individual upgrade script
+-- incorporated herein:
+
+INSERT INTO config.upgrade_log (version) VALUES ('0403');
+
+-- Begin by upgrading permission.perm_list.  This is fairly complicated.
+
+-- Add ON UPDATE CASCADE to some foreign keys so that, when we renumber the
+-- permissions, the dependents will follow and stay in sync:
+
+ALTER TABLE permission.grp_perm_map DROP CONSTRAINT grp_perm_map_perm_fkey;
+ALTER TABLE permission.grp_perm_map ADD CONSTRAINT grp_perm_map_perm_fkey FOREIGN KEY (perm)
+    REFERENCES permission.perm_list (id) ON UPDATE CASCADE ON DELETE RESTRICT DEFERRABLE INITIALLY DEFERRED;
+
+ALTER TABLE permission.usr_perm_map DROP CONSTRAINT usr_perm_map_perm_fkey;
+ALTER TABLE permission.usr_perm_map ADD CONSTRAINT usr_perm_map_perm_fkey FOREIGN KEY (perm)
+    REFERENCES permission.perm_list (id) ON UPDATE CASCADE ON DELETE RESTRICT DEFERRABLE INITIALLY DEFERRED;
+
+ALTER TABLE permission.usr_object_perm_map DROP CONSTRAINT usr_object_perm_map_perm_fkey;
+ALTER TABLE permission.usr_object_perm_map ADD CONSTRAINT usr_object_perm_map_perm_fkey FOREIGN KEY (perm)
+    REFERENCES permission.perm_list (id) ON UPDATE CASCADE ON DELETE RESTRICT DEFERRABLE INITIALLY DEFERRED;
+
+UPDATE permission.perm_list
+    SET code = 'UPDATE_ORG_UNIT_SETTING.credit.payments.allow'
+    WHERE code = 'UPDATE_ORG_UNIT_SETTING.global.credit.allow';
+
+-- The following UPDATES were originally in an individual upgrade script, but should
+-- no longer be necessary now that the foreign key has an ON UPDATE CASCADE clause.
+-- We retain the UPDATES here, commented out, as historical relics.
+
+-- UPDATE permission.grp_perm_map SET perm = perm + 1000 WHERE perm NOT IN ( SELECT id FROM permission.perm_list );
+-- UPDATE permission.usr_perm_map SET perm = perm + 1000 WHERE perm NOT IN ( SELECT id FROM permission.perm_list );
+
+-- Spelling correction
+UPDATE permission.perm_list SET code = 'ADMIN_RECURRING_FINE_RULE' WHERE code = 'ADMIN_RECURING_FINE_RULE';
+
+-- Now we engage in a Great Renumbering of the permissions in permission.perm_list,
+-- in order to clean up accumulated cruft.
+
+-- The first step is to establish some triggers so that, when we change the id of a permission,
+-- the associated translations are updated accordingly.
+
+CREATE OR REPLACE FUNCTION oils_i18n_update_apply(old_ident TEXT, new_ident TEXT, hint TEXT) RETURNS VOID AS $_$
+BEGIN
+
+    EXECUTE $$
+        UPDATE  config.i18n_core
+          SET   identity_value = $$ || quote_literal( new_ident ) || $$ 
+          WHERE fq_field LIKE '$$ || hint || $$.%' 
+                AND identity_value = $$ || quote_literal( old_ident ) || $$;$$;
+
+    RETURN;
+
+END;
+$_$ LANGUAGE PLPGSQL;
+
+CREATE OR REPLACE FUNCTION oils_i18n_id_tracking(/* hint */) RETURNS TRIGGER AS $_$
+BEGIN
+    PERFORM oils_i18n_update_apply( OLD.id::TEXT, NEW.id::TEXT, TG_ARGV[0]::TEXT );
+    RETURN NEW;
+END;
+$_$ LANGUAGE PLPGSQL;
+
+CREATE OR REPLACE FUNCTION oils_i18n_code_tracking(/* hint */) RETURNS TRIGGER AS $_$
+BEGIN
+    PERFORM oils_i18n_update_apply( OLD.code::TEXT, NEW.code::TEXT, TG_ARGV[0]::TEXT );
+    RETURN NEW;
+END;
+$_$ LANGUAGE PLPGSQL;
+
+
+CREATE TRIGGER maintain_perm_i18n_tgr
+    AFTER UPDATE ON permission.perm_list
+    FOR EACH ROW EXECUTE PROCEDURE oils_i18n_id_tracking('ppl');
+
+-- Next, create a new table as a convenience for sloshing data back and forth,
+-- and for recording which permission went where.  It looks just like
+-- permission.perm_list, but with two extra columns: one for the old id, and one to
+-- distinguish between predefined permissions and non-predefined permissions.
+
+-- This table is, in effect, a temporary table, because we can drop it once the
+-- upgrade is complete.  It is not technically temporary as far as PostgreSQL is
+-- concerned, because we don't want it to disappear at the end of the session.
+-- We keep it around so that we have a map showing the old id and the new id for
+-- each permission.  However there is no IDL entry for it, nor is it defined
+-- in the base sql files.
+
+CREATE TABLE permission.temp_perm (
+	id          INT        PRIMARY KEY,
+	code        TEXT       UNIQUE,
+	description TEXT,
+	old_id      INT,
+	predefined  BOOL       NOT NULL DEFAULT TRUE
+);
+
+-- Populate the temp table with a definitive set of predefined permissions,
+-- hard-coding the ids.
+
+-- The first set of permissions is derived from the database, as loaded in a
+-- loaded 1.6.1 database, plus a few changes previously applied in this upgrade
+-- script.  The second set is derived from the IDL -- permissions that are referenced
+-- in <permacrud> elements but not defined in the database.
+
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( -1, 'EVERYTHING',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 1, 'OPAC_LOGIN',
+     'Allow a user to log in to the OPAC' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 2, 'STAFF_LOGIN',
+     'Allow a user to log in to the staff client' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 3, 'MR_HOLDS',
+     'Allow a user to create a metarecord holds' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 4, 'TITLE_HOLDS',
+     'Allow a user to place a hold at the title level' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 5, 'VOLUME_HOLDS',
+     'Allow a user to place a volume level hold' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 6, 'COPY_HOLDS',
+     'Allow a user to place a hold on a specific copy' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 7, 'REQUEST_HOLDS',
+     'Allow a user to create holds for another user (if true, we still check to make sure they have permission to make the type of hold they are requesting, for example, COPY_HOLDS)' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 8, 'REQUEST_HOLDS_OVERRIDE',
+     '* no longer applicable' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 9, 'VIEW_HOLD',
+     'Allow a user to view another user''s holds' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 10, 'DELETE_HOLDS',
+     '* no longer applicable' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 11, 'UPDATE_HOLD',
+     'Allow a user to update another user''s hold' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 12, 'RENEW_CIRC',
+     'Allow a user to renew items' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 13, 'VIEW_USER_FINES_SUMMARY',
+     'Allow a user to view bill details' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 14, 'VIEW_USER_TRANSACTIONS',
+     'Allow a user to see another user''s grocery or circulation transactions in the Bills Interface; duplicate of VIEW_TRANSACTION' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 15, 'UPDATE_MARC',
+     'Allow a user to edit a MARC record' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 16, 'CREATE_MARC',
+     'Allow a user to create new MARC records' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 17, 'IMPORT_MARC',
+     'Allow a user to import a MARC record via the Z39.50 interface' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 18, 'CREATE_VOLUME',
+     'Allow a user to create a volume' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 19, 'UPDATE_VOLUME',
+     'Allow a user to edit volumes - needed for merging records. This is a duplicate of VOLUME_UPDATE; user must have both permissions at appropriate level to merge records.' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 20, 'DELETE_VOLUME',
+     'Allow a user to delete a volume' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 21, 'CREATE_COPY',
+     'Allow a user to create a new copy object' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 22, 'UPDATE_COPY',
+     'Allow a user to edit a copy' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 23, 'DELETE_COPY',
+     'Allow a user to delete a copy' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 24, 'RENEW_HOLD_OVERRIDE',
+     'Allow a user to continue to renew an item even if it is required for a hold' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 25, 'CREATE_USER',
+     'Allow a user to create another user' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 26, 'UPDATE_USER',
+     'Allow a user to edit a user''s record' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 27, 'DELETE_USER',
+     'Allow a user to mark a user as deleted' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 28, 'VIEW_USER',
+     'Allow a user to view another user''s Patron Record' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 29, 'COPY_CHECKIN',
+     'Allow a user to check in a copy' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 30, 'CREATE_TRANSIT',
+     'Allow a user to place an item in transit' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 31, 'VIEW_PERMISSION',
+     'Allow a user to view user permissions within the user permissions editor' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 32, 'CHECKIN_BYPASS_HOLD_FULFILL',
+     '* no longer applicable' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 33, 'CREATE_PAYMENT',
+     'Allow a user to record payments in the Billing Interface' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 34, 'SET_CIRC_LOST',
+     'Allow a user to mark an item as ''lost''' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 35, 'SET_CIRC_MISSING',
+     'Allow a user to mark an item as ''missing''' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 36, 'SET_CIRC_CLAIMS_RETURNED',
+     'Allow a user to mark an item as ''claims returned''' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 37, 'CREATE_TRANSACTION',
+     'Allow a user to create a new billable transaction' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 38, 'VIEW_TRANSACTION',
+     'Allow a user may view another user''s transactions' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 39, 'CREATE_BILL',
+     'Allow a user to create a new bill on a transaction' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 40, 'VIEW_CONTAINER',
+     'Allow a user to view another user''s containers (buckets)' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 41, 'CREATE_CONTAINER',
+     'Allow a user to create a new container for another user' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 42, 'UPDATE_ORG_UNIT',
+     'Allow a user to change the settings for an organization unit' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 43, 'VIEW_CIRCULATIONS',
+     'Allow a user to see what another user has checked out' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 44, 'DELETE_CONTAINER',
+     'Allow a user to delete another user''s container' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 45, 'CREATE_CONTAINER_ITEM',
+     'Allow a user to create a container item for another user' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 46, 'CREATE_USER_GROUP_LINK',
+     'Allow a user to add other users to permission groups' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 47, 'REMOVE_USER_GROUP_LINK',
+     'Allow a user to remove other users from permission groups' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 48, 'VIEW_PERM_GROUPS',
+     'Allow a user to view other users'' permission groups' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 49, 'VIEW_PERMIT_CHECKOUT',
+     'Allow a user to determine whether another user can check out an item' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 50, 'UPDATE_BATCH_COPY',
+     'Allow a user to edit copies in batch' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 51, 'CREATE_PATRON_STAT_CAT',
+     'User may create a new patron statistical category' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 52, 'CREATE_COPY_STAT_CAT',
+     'User may create a copy statistical category' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 53, 'CREATE_PATRON_STAT_CAT_ENTRY',
+     'User may create an entry in a patron statistical category' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 54, 'CREATE_COPY_STAT_CAT_ENTRY',
+     'User may create an entry in a copy statistical category' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 55, 'UPDATE_PATRON_STAT_CAT',
+     'User may update a patron statistical category' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 56, 'UPDATE_COPY_STAT_CAT',
+     'User may update a copy statistical category' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 57, 'UPDATE_PATRON_STAT_CAT_ENTRY',
+     'User may update an entry in a patron statistical category' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 58, 'UPDATE_COPY_STAT_CAT_ENTRY',
+     'User may update an entry in a copy statistical category' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 59, 'CREATE_PATRON_STAT_CAT_ENTRY_MAP',
+     'User may link another user to an entry in a statistical category' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 60, 'CREATE_COPY_STAT_CAT_ENTRY_MAP',
+     'User may link a copy to an entry in a statistical category' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 61, 'DELETE_PATRON_STAT_CAT',
+     'User may delete a patron statistical category' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 62, 'DELETE_COPY_STAT_CAT',
+     'User may delete a copy statistical category' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 63, 'DELETE_PATRON_STAT_CAT_ENTRY',
+     'User may delete an entry from a patron statistical category' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 64, 'DELETE_COPY_STAT_CAT_ENTRY',
+     'User may delete an entry from a copy statistical category' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 65, 'DELETE_PATRON_STAT_CAT_ENTRY_MAP',
+     'User may delete a patron statistical category entry map' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 66, 'DELETE_COPY_STAT_CAT_ENTRY_MAP',
+     'User may delete a copy statistical category entry map' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 67, 'CREATE_NON_CAT_TYPE',
+     'Allow a user to create a new non-cataloged item type' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 68, 'UPDATE_NON_CAT_TYPE',
+     'Allow a user to update a non-cataloged item type' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 69, 'CREATE_IN_HOUSE_USE',
+     'Allow a user to create a new in-house-use ' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 70, 'COPY_CHECKOUT',
+     'Allow a user to check out a copy' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 71, 'CREATE_COPY_LOCATION',
+     'Allow a user to create a new copy location' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 72, 'UPDATE_COPY_LOCATION',
+     'Allow a user to update a copy location' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 73, 'DELETE_COPY_LOCATION',
+     'Allow a user to delete a copy location' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 74, 'CREATE_COPY_TRANSIT',
+     'Allow a user to create a transit_copy object for transiting a copy' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 75, 'COPY_TRANSIT_RECEIVE',
+     'Allow a user to close out a transit on a copy' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 76, 'VIEW_HOLD_PERMIT',
+     'Allow a user to see if another user has permission to place a hold on a given copy' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 77, 'VIEW_COPY_CHECKOUT_HISTORY',
+     'Allow a user to view which users have checked out a given copy' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 78, 'REMOTE_Z3950_QUERY',
+     'Allow a user to perform Z39.50 queries against remote servers' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 79, 'REGISTER_WORKSTATION',
+     'Allow a user to register a new workstation' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 80, 'VIEW_COPY_NOTES',
+     'Allow a user to view all notes attached to a copy' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 81, 'VIEW_VOLUME_NOTES',
+     'Allow a user to view all notes attached to a volume' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 82, 'VIEW_TITLE_NOTES',
+     'Allow a user to view all notes attached to a title' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 83, 'CREATE_COPY_NOTE',
+     'Allow a user to create a new copy note' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 84, 'CREATE_VOLUME_NOTE',
+     'Allow a user to create a new volume note' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 85, 'CREATE_TITLE_NOTE',
+     'Allow a user to create a new title note' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 86, 'DELETE_COPY_NOTE',
+     'Allow a user to delete another user''s copy notes' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 87, 'DELETE_VOLUME_NOTE',
+     'Allow a user to delete another user''s volume note' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 88, 'DELETE_TITLE_NOTE',
+     'Allow a user to delete another user''s title note' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 89, 'UPDATE_CONTAINER',
+     'Allow a user to update another user''s container' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 90, 'CREATE_MY_CONTAINER',
+     'Allow a user to create a container for themselves' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 91, 'VIEW_HOLD_NOTIFICATION',
+     'Allow a user to view notifications attached to a hold' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 92, 'CREATE_HOLD_NOTIFICATION',
+     'Allow a user to create new hold notifications' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 93, 'UPDATE_ORG_SETTING',
+     'Allow a user to update an organization unit setting' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 94, 'OFFLINE_UPLOAD',
+     'Allow a user to upload an offline script' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 95, 'OFFLINE_VIEW',
+     'Allow a user to view uploaded offline script information' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 96, 'OFFLINE_EXECUTE',
+     'Allow a user to execute an offline script batch' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 97, 'CIRC_OVERRIDE_DUE_DATE',
+     'Allow a user to change the due date on an item to any date' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 98, 'CIRC_PERMIT_OVERRIDE',
+     'Allow a user to bypass the circulation permit call for check out' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 99, 'COPY_IS_REFERENCE.override',
+     'Allow a user to override the copy_is_reference event' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 100, 'VOID_BILLING',
+     'Allow a user to void a bill' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 101, 'CIRC_CLAIMS_RETURNED.override',
+     'Allow a user to check in or check out an item that has a status of ''claims returned''' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 102, 'COPY_BAD_STATUS.override',
+     'Allow a user to check out an item in a non-circulatable status' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 103, 'COPY_ALERT_MESSAGE.override',
+     'Allow a user to check in/out an item that has an alert message' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 104, 'COPY_STATUS_LOST.override',
+     'Allow a user to remove the lost status from a copy' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 105, 'COPY_STATUS_MISSING.override',
+     'Allow a user to change the missing status on a copy' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 106, 'ABORT_TRANSIT',
+     'Allow a user to abort a copy transit if the user is at the transit destination or source' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 107, 'ABORT_REMOTE_TRANSIT',
+     'Allow a user to abort a copy transit if the user is not at the transit source or dest' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 108, 'VIEW_ZIP_DATA',
+     'Allow a user to query the ZIP code data method' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 109, 'CANCEL_HOLDS',
+     'Allow a user to cancel holds' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 110, 'CREATE_DUPLICATE_HOLDS',
+     'Allow a user to create duplicate holds (two or more holds on the same title)' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 111, 'actor.org_unit.closed_date.delete',
+     'Allow a user to remove a closed date interval for a given location' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 112, 'actor.org_unit.closed_date.update',
+     'Allow a user to update a closed date interval for a given location' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 113, 'actor.org_unit.closed_date.create',
+     'Allow a user to create a new closed date for a location' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 114, 'DELETE_NON_CAT_TYPE',
+     'Allow a user to delete a non cataloged type' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 115, 'money.collections_tracker.create',
+     'Allow a user to put someone into collections' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 116, 'money.collections_tracker.delete',
+     'Allow a user to remove someone from collections' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 117, 'BAR_PATRON',
+     'Allow a user to bar a patron' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 118, 'UNBAR_PATRON',
+     'Allow a user to un-bar a patron' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 119, 'DELETE_WORKSTATION',
+     'Allow a user to remove an existing workstation so a new one can replace it' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 120, 'group_application.user',
+     'Allow a user to add/remove users to/from the "User" group' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 121, 'group_application.user.patron',
+     'Allow a user to add/remove users to/from the "Patron" group' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 122, 'group_application.user.staff',
+     'Allow a user to add/remove users to/from the "Staff" group' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 123, 'group_application.user.staff.circ',
+     'Allow a user to add/remove users to/from the "Circulator" group' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 124, 'group_application.user.staff.cat',
+     'Allow a user to add/remove users to/from the "Cataloger" group' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 125, 'group_application.user.staff.admin.global_admin',
+     'Allow a user to add/remove users to/from the "GlobalAdmin" group' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 126, 'group_application.user.staff.admin.local_admin',
+     'Allow a user to add/remove users to/from the "LocalAdmin" group' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 127, 'group_application.user.staff.admin.lib_manager',
+     'Allow a user to add/remove users to/from the "LibraryManager" group' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 128, 'group_application.user.staff.cat.cat1',
+     'Allow a user to add/remove users to/from the "Cat1" group' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 129, 'group_application.user.staff.supercat',
+     'Allow a user to add/remove users to/from the "Supercat" group' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 130, 'group_application.user.sip_client',
+     'Allow a user to add/remove users to/from the "SIP-Client" group' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 131, 'group_application.user.vendor',
+     'Allow a user to add/remove users to/from the "Vendor" group' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 132, 'ITEM_AGE_PROTECTED.override',
+     'Allow a user to place a hold on an age-protected item' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 133, 'MAX_RENEWALS_REACHED.override',
+     'Allow a user to renew an item past the maximum renewal count' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 134, 'PATRON_EXCEEDS_CHECKOUT_COUNT.override',
+     'Allow staff to override checkout count failure' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 135, 'PATRON_EXCEEDS_OVERDUE_COUNT.override',
+     'Allow staff to override overdue count failure' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 136, 'PATRON_EXCEEDS_FINES.override',
+     'Allow staff to override fine amount checkout failure' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 137, 'CIRC_EXCEEDS_COPY_RANGE.override',
+     'Allow staff to override circulation copy range failure' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 138, 'ITEM_ON_HOLDS_SHELF.override',
+     'Allow staff to override item on holds shelf failure' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 139, 'COPY_NOT_AVAILABLE.override',
+     'Allow staff to force checkout of Missing/Lost type items' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 140, 'HOLD_EXISTS.override',
+     'Allow a user to place multiple holds on a single title' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 141, 'RUN_REPORTS',
+     'Allow a user to run reports' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 142, 'SHARE_REPORT_FOLDER',
+     'Allow a user to share report his own folders' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 143, 'VIEW_REPORT_OUTPUT',
+     'Allow a user to view report output' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 144, 'COPY_CIRC_NOT_ALLOWED.override',
+     'Allow a user to checkout an item that is marked as non-circ' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 145, 'DELETE_CONTAINER_ITEM',
+     'Allow a user to delete an item out of another user''s container' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 146, 'ASSIGN_WORK_ORG_UNIT',
+     'Allow a staff member to define where another staff member has their permissions' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 147, 'CREATE_FUNDING_SOURCE',
+     'Allow a user to create a new funding source' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 148, 'DELETE_FUNDING_SOURCE',
+     'Allow a user to delete a funding source' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 149, 'VIEW_FUNDING_SOURCE',
+     'Allow a user to view a funding source' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 150, 'UPDATE_FUNDING_SOURCE',
+     'Allow a user to update a funding source' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 151, 'CREATE_FUND',
+     'Allow a user to create a new fund' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 152, 'DELETE_FUND',
+     'Allow a user to delete a fund' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 153, 'VIEW_FUND',
+     'Allow a user to view a fund' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 154, 'UPDATE_FUND',
+     'Allow a user to update a fund' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 155, 'CREATE_FUND_ALLOCATION',
+     'Allow a user to create a new fund allocation' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 156, 'DELETE_FUND_ALLOCATION',
+     'Allow a user to delete a fund allocation' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 157, 'VIEW_FUND_ALLOCATION',
+     'Allow a user to view a fund allocation' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 158, 'UPDATE_FUND_ALLOCATION',
+     'Allow a user to update a fund allocation' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 159, 'GENERAL_ACQ',
+     'Lowest level permission required to access the ACQ interface' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 160, 'CREATE_PROVIDER',
+     'Allow a user to create a new provider' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 161, 'DELETE_PROVIDER',
+     'Allow a user to delate a provider' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 162, 'VIEW_PROVIDER',
+     'Allow a user to view a provider' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 163, 'UPDATE_PROVIDER',
+     'Allow a user to update a provider' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 164, 'ADMIN_FUNDING_SOURCE',
+     'Allow a user to create/view/update/delete a funding source' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 165, 'ADMIN_FUND',
+     '(Deprecated) Allow a user to create/view/update/delete a fund' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 166, 'MANAGE_FUNDING_SOURCE',
+     'Allow a user to view/credit/debit a funding source' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 167, 'MANAGE_FUND',
+     'Allow a user to view/credit/debit a fund' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 168, 'CREATE_PICKLIST',
+     'Allows a user to create a picklist' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 169, 'ADMIN_PROVIDER',
+     'Allow a user to create/view/update/delete a provider' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 170, 'MANAGE_PROVIDER',
+     'Allow a user to view and purchase from a provider' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 171, 'VIEW_PICKLIST',
+     'Allow a user to view another users picklist' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 172, 'DELETE_RECORD',
+     'Allow a staff member to directly remove a bibliographic record' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 173, 'ADMIN_CURRENCY_TYPE',
+     'Allow a user to create/view/update/delete a currency_type' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 174, 'MARK_BAD_DEBT',
+     'Allow a user to mark a transaction as bad (unrecoverable) debt' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 175, 'VIEW_BILLING_TYPE',
+     'Allow a user to view billing types' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 176, 'MARK_ITEM_AVAILABLE',
+     'Allow a user to mark an item status as ''available''' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 177, 'MARK_ITEM_CHECKED_OUT',
+     'Allow a user to mark an item status as ''checked out''' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 178, 'MARK_ITEM_BINDERY',
+     'Allow a user to mark an item status as ''bindery''' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 179, 'MARK_ITEM_LOST',
+     'Allow a user to mark an item status as ''lost''' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 180, 'MARK_ITEM_MISSING',
+     'Allow a user to mark an item status as ''missing''' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 181, 'MARK_ITEM_IN_PROCESS',
+     'Allow a user to mark an item status as ''in process''' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 182, 'MARK_ITEM_IN_TRANSIT',
+     'Allow a user to mark an item status as ''in transit''' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 183, 'MARK_ITEM_RESHELVING',
+     'Allow a user to mark an item status as ''reshelving''' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 184, 'MARK_ITEM_ON_HOLDS_SHELF',
+     'Allow a user to mark an item status as ''on holds shelf''' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 185, 'MARK_ITEM_ON_ORDER',
+     'Allow a user to mark an item status as ''on order''' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 186, 'MARK_ITEM_ILL',
+     'Allow a user to mark an item status as ''inter-library loan''' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 187, 'group_application.user.staff.acq',
+     'Allows a user to add/remove/edit users in the "ACQ" group' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 188, 'CREATE_PURCHASE_ORDER',
+     'Allows a user to create a purchase order' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 189, 'VIEW_PURCHASE_ORDER',
+     'Allows a user to view a purchase order' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 190, 'IMPORT_ACQ_LINEITEM_BIB_RECORD',
+     'Allows a user to import a bib record from the acq staging area (on-order record) into the ILS bib data set' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 191, 'RECEIVE_PURCHASE_ORDER',
+     'Allows a user to mark a purchase order, lineitem, or individual copy as received' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 192, 'VIEW_ORG_SETTINGS',
+     'Allows a user to view all org settings at the specified level' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 193, 'CREATE_MFHD_RECORD',
+     'Allows a user to create a new MFHD record' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 194, 'UPDATE_MFHD_RECORD',
+     'Allows a user to update an MFHD record' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 195, 'DELETE_MFHD_RECORD',
+     'Allows a user to delete an MFHD record' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 196, 'ADMIN_ACQ_FUND',
+     'Allow a user to create/view/update/delete a fund' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 197, 'group_application.user.staff.acq_admin',
+     'Allows a user to add/remove/edit users in the "Acquisitions Administrators" group' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 198, 'SET_CIRC_CLAIMS_RETURNED.override',
+     'Allows staff to override the max claims returned value for a patron' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 199, 'UPDATE_PATRON_CLAIM_RETURN_COUNT',
+     'Allows staff to manually change a patron''s claims returned count' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 200, 'UPDATE_BILL_NOTE',
+     'Allows staff to edit the note for a bill on a transaction' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 201, 'UPDATE_PAYMENT_NOTE',
+     'Allows staff to edit the note for a payment on a transaction' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 202, 'UPDATE_PATRON_CLAIM_NEVER_CHECKED_OUT_COUNT',
+     'Allows staff to manually change a patron''s claims never checkout out count' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 203, 'ADMIN_COPY_LOCATION_ORDER',
+     'Allow a user to create/view/update/delete a copy location order' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 204, 'ASSIGN_GROUP_PERM',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 205, 'CREATE_AUDIENCE',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 206, 'CREATE_BIB_LEVEL',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 207, 'CREATE_CIRC_DURATION',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 208, 'CREATE_CIRC_MOD',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 209, 'CREATE_COPY_STATUS',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 210, 'CREATE_HOURS_OF_OPERATION',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 211, 'CREATE_ITEM_FORM',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 212, 'CREATE_ITEM_TYPE',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 213, 'CREATE_LANGUAGE',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 214, 'CREATE_LASSO',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 215, 'CREATE_LASSO_MAP',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 216, 'CREATE_LIT_FORM',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 217, 'CREATE_METABIB_FIELD',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 218, 'CREATE_NET_ACCESS_LEVEL',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 219, 'CREATE_ORG_ADDRESS',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 220, 'CREATE_ORG_TYPE',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 221, 'CREATE_ORG_UNIT',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 222, 'CREATE_ORG_UNIT_CLOSING',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 223, 'CREATE_PERM',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 224, 'CREATE_RELEVANCE_ADJUSTMENT',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 225, 'CREATE_SURVEY',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 226, 'CREATE_VR_FORMAT',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 227, 'CREATE_XML_TRANSFORM',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 228, 'DELETE_AUDIENCE',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 229, 'DELETE_BIB_LEVEL',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 230, 'DELETE_CIRC_DURATION',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 231, 'DELETE_CIRC_MOD',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 232, 'DELETE_COPY_STATUS',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 233, 'DELETE_HOURS_OF_OPERATION',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 234, 'DELETE_ITEM_FORM',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 235, 'DELETE_ITEM_TYPE',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 236, 'DELETE_LANGUAGE',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 237, 'DELETE_LASSO',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 238, 'DELETE_LASSO_MAP',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 239, 'DELETE_LIT_FORM',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 240, 'DELETE_METABIB_FIELD',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 241, 'DELETE_NET_ACCESS_LEVEL',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 242, 'DELETE_ORG_ADDRESS',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 243, 'DELETE_ORG_TYPE',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 244, 'DELETE_ORG_UNIT',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 245, 'DELETE_ORG_UNIT_CLOSING',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 246, 'DELETE_PERM',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 247, 'DELETE_RELEVANCE_ADJUSTMENT',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 248, 'DELETE_SURVEY',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 249, 'DELETE_TRANSIT',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 250, 'DELETE_VR_FORMAT',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 251, 'DELETE_XML_TRANSFORM',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 252, 'REMOVE_GROUP_PERM',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 253, 'TRANSIT_COPY',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 254, 'UPDATE_AUDIENCE',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 255, 'UPDATE_BIB_LEVEL',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 256, 'UPDATE_CIRC_DURATION',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 257, 'UPDATE_CIRC_MOD',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 258, 'UPDATE_COPY_NOTE',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 259, 'UPDATE_COPY_STATUS',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 260, 'UPDATE_GROUP_PERM',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 261, 'UPDATE_HOURS_OF_OPERATION',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 262, 'UPDATE_ITEM_FORM',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 263, 'UPDATE_ITEM_TYPE',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 264, 'UPDATE_LANGUAGE',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 265, 'UPDATE_LASSO',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 266, 'UPDATE_LASSO_MAP',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 267, 'UPDATE_LIT_FORM',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 268, 'UPDATE_METABIB_FIELD',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 269, 'UPDATE_NET_ACCESS_LEVEL',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 270, 'UPDATE_ORG_ADDRESS',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 271, 'UPDATE_ORG_TYPE',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 272, 'UPDATE_ORG_UNIT_CLOSING',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 273, 'UPDATE_PERM',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 274, 'UPDATE_RELEVANCE_ADJUSTMENT',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 275, 'UPDATE_SURVEY',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 276, 'UPDATE_TRANSIT',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 277, 'UPDATE_VOLUME_NOTE',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 278, 'UPDATE_VR_FORMAT',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 279, 'UPDATE_XML_TRANSFORM',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 280, 'MERGE_BIB_RECORDS',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 281, 'UPDATE_PICKUP_LIB_FROM_HOLDS_SHELF',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 282, 'CREATE_ACQ_FUNDING_SOURCE',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 283, 'CREATE_AUTHORITY_IMPORT_IMPORT_FIELD_DEF',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 284, 'CREATE_AUTHORITY_IMPORT_QUEUE',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 285, 'CREATE_AUTHORITY_RECORD_NOTE',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 286, 'CREATE_BIB_IMPORT_FIELD_DEF',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 287, 'CREATE_BIB_IMPORT_QUEUE',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 288, 'CREATE_LOCALE',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 289, 'CREATE_MARC_CODE',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 290, 'CREATE_TRANSLATION',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 291, 'DELETE_ACQ_FUNDING_SOURCE',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 292, 'DELETE_AUTHORITY_IMPORT_IMPORT_FIELD_DEF',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 293, 'DELETE_AUTHORITY_IMPORT_QUEUE',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 294, 'DELETE_AUTHORITY_RECORD_NOTE',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 295, 'DELETE_BIB_IMPORT_IMPORT_FIELD_DEF',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 296, 'DELETE_BIB_IMPORT_QUEUE',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 297, 'DELETE_LOCALE',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 298, 'DELETE_MARC_CODE',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 299, 'DELETE_TRANSLATION',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 300, 'UPDATE_ACQ_FUNDING_SOURCE',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 301, 'UPDATE_AUTHORITY_IMPORT_IMPORT_FIELD_DEF',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 302, 'UPDATE_AUTHORITY_IMPORT_QUEUE',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 303, 'UPDATE_AUTHORITY_RECORD_NOTE',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 304, 'UPDATE_BIB_IMPORT_IMPORT_FIELD_DEF',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 305, 'UPDATE_BIB_IMPORT_QUEUE',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 306, 'UPDATE_LOCALE',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 307, 'UPDATE_MARC_CODE',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 308, 'UPDATE_TRANSLATION',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 309, 'VIEW_ACQ_FUNDING_SOURCE',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 310, 'VIEW_AUTHORITY_RECORD_NOTES',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 311, 'CREATE_IMPORT_ITEM',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 312, 'CREATE_IMPORT_ITEM_ATTR_DEF',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 313, 'CREATE_IMPORT_TRASH_FIELD',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 314, 'DELETE_IMPORT_ITEM',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 315, 'DELETE_IMPORT_ITEM_ATTR_DEF',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 316, 'DELETE_IMPORT_TRASH_FIELD',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 317, 'UPDATE_IMPORT_ITEM',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 318, 'UPDATE_IMPORT_ITEM_ATTR_DEF',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 319, 'UPDATE_IMPORT_TRASH_FIELD',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 320, 'UPDATE_ORG_UNIT_SETTING_ALL',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 321, 'UPDATE_ORG_UNIT_SETTING.circ.lost_materials_processing_fee',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 322, 'UPDATE_ORG_UNIT_SETTING.cat.default_item_price',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 323, 'UPDATE_ORG_UNIT_SETTING.auth.opac_timeout',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 324, 'UPDATE_ORG_UNIT_SETTING.auth.staff_timeout',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 325, 'UPDATE_ORG_UNIT_SETTING.org.bounced_emails',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 326, 'UPDATE_ORG_UNIT_SETTING.circ.hold_expire_alert_interval',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 327, 'UPDATE_ORG_UNIT_SETTING.circ.hold_expire_interval',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 328, 'UPDATE_ORG_UNIT_SETTING.credit.payments.allow',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 329, 'UPDATE_ORG_UNIT_SETTING.circ.void_overdue_on_lost',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 330, 'UPDATE_ORG_UNIT_SETTING.circ.hold_stalling.soft',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 331, 'UPDATE_ORG_UNIT_SETTING.circ.hold_boundary.hard',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 332, 'UPDATE_ORG_UNIT_SETTING.circ.hold_boundary.soft',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 333, 'UPDATE_ORG_UNIT_SETTING.opac.barcode_regex',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 334, 'UPDATE_ORG_UNIT_SETTING.global.password_regex',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 335, 'UPDATE_ORG_UNIT_SETTING.circ.item_checkout_history.max',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 336, 'UPDATE_ORG_UNIT_SETTING.circ.reshelving_complete.interval',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 337, 'UPDATE_ORG_UNIT_SETTING.circ.selfcheck.patron_login_timeout',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 338, 'UPDATE_ORG_UNIT_SETTING.circ.selfcheck.alert_on_checkout_event',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 339, 'UPDATE_ORG_UNIT_SETTING.circ.selfcheck.require_patron_password',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 340, 'UPDATE_ORG_UNIT_SETTING.global.juvenile_age_threshold',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 341, 'UPDATE_ORG_UNIT_SETTING.cat.bib.keep_on_empty',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 342, 'UPDATE_ORG_UNIT_SETTING.cat.bib.alert_on_empty',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 343, 'UPDATE_ORG_UNIT_SETTING.patron.password.use_phone',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 344, 'HOLD_ITEM_CHECKED_OUT.override',
+     'Allows a user to place a hold on an item that they already have checked out' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 345, 'ADMIN_ACQ_CANCEL_CAUSE',
+     'Allow a user to create/update/delete reasons for order cancellations' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 346, 'ACQ_XFER_MANUAL_DFUND_AMOUNT',
+     'Allow a user to transfer different amounts of money out of one fund and into another' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 347, 'OVERRIDE_HOLD_HAS_LOCAL_COPY',
+     'Allow a user to override the circ.holds.hold_has_copy_at.block setting' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 348, 'UPDATE_PICKUP_LIB_FROM_TRANSIT',
+     'Allow a user to change the pickup and transit destination for a captured hold item already in transit' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 349, 'COPY_NEEDED_FOR_HOLD.override',
+     'Allow a user to force renewal of an item that could fulfill a hold request' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 350, 'MERGE_AUTH_RECORDS',
+     'Allow a user to merge authority records together' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 351, 'ALLOW_ALT_TCN',
+     'Allows staff to import a record using an alternate TCN to avoid conflicts' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 352, 'ADMIN_TRIGGER_EVENT_DEF',
+     'Allow a user to administer trigger event definitions' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 353, 'ADMIN_TRIGGER_CLEANUP',
+     'Allow a user to create, delete, and update trigger cleanup entries' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 354, 'CREATE_TRIGGER_CLEANUP',
+     'Allow a user to create trigger cleanup entries' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 355, 'DELETE_TRIGGER_CLEANUP',
+     'Allow a user to delete trigger cleanup entries' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 356, 'UPDATE_TRIGGER_CLEANUP',
+     'Allow a user to update trigger cleanup entries' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 357, 'CREATE_TRIGGER_EVENT_DEF',
+     'Allow a user to create trigger event definitions' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 358, 'DELETE_TRIGGER_EVENT_DEF',
+     'Allow a user to delete trigger event definitions' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 359, 'UPDATE_TRIGGER_EVENT_DEF',
+     'Allow a user to update trigger event definitions' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 360, 'VIEW_TRIGGER_EVENT_DEF',
+     'Allow a user to view trigger event definitions' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 361, 'ADMIN_TRIGGER_HOOK',
+     'Allow a user to create, update, and delete trigger hooks' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 362, 'CREATE_TRIGGER_HOOK',
+     'Allow a user to create trigger hooks' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 363, 'DELETE_TRIGGER_HOOK',
+     'Allow a user to delete trigger hooks' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 364, 'UPDATE_TRIGGER_HOOK',
+     'Allow a user to update trigger hooks' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 365, 'ADMIN_TRIGGER_REACTOR',
+     'Allow a user to create, update, and delete trigger reactors' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 366, 'CREATE_TRIGGER_REACTOR',
+     'Allow a user to create trigger reactors' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 367, 'DELETE_TRIGGER_REACTOR',
+     'Allow a user to delete trigger reactors' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 368, 'UPDATE_TRIGGER_REACTOR',
+     'Allow a user to update trigger reactors' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 369, 'ADMIN_TRIGGER_TEMPLATE_OUTPUT',
+     'Allow a user to delete trigger template output' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 370, 'DELETE_TRIGGER_TEMPLATE_OUTPUT',
+     'Allow a user to delete trigger template output' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 371, 'ADMIN_TRIGGER_VALIDATOR',
+     'Allow a user to create, update, and delete trigger validators' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 372, 'CREATE_TRIGGER_VALIDATOR',
+     'Allow a user to create trigger validators' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 373, 'DELETE_TRIGGER_VALIDATOR',
+     'Allow a user to delete trigger validators' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 374, 'UPDATE_TRIGGER_VALIDATOR',
+     'Allow a user to update trigger validators' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 375, 'HOLD_LOCAL_AVAIL_OVERRIDE',
+     'Allow a user to place a hold despite the availability of a local copy' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 376, 'ADMIN_BOOKING_RESOURCE',
+     'Enables the user to create/update/delete booking resources' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 377, 'ADMIN_BOOKING_RESOURCE_TYPE',
+     'Enables the user to create/update/delete booking resource types' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 378, 'ADMIN_BOOKING_RESOURCE_ATTR',
+     'Enables the user to create/update/delete booking resource attributes' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 379, 'ADMIN_BOOKING_RESOURCE_ATTR_MAP',
+     'Enables the user to create/update/delete booking resource attribute maps' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 380, 'ADMIN_BOOKING_RESOURCE_ATTR_VALUE',
+     'Enables the user to create/update/delete booking resource attribute values' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 381, 'ADMIN_BOOKING_RESERVATION',
+     'Enables the user to create/update/delete booking reservations' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 382, 'ADMIN_BOOKING_RESERVATION_ATTR_VALUE_MAP',
+     'Enables the user to create/update/delete booking reservation attribute value maps' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 383, 'RETRIEVE_RESERVATION_PULL_LIST',
+     'Allows a user to retrieve a booking reservation pull list' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 384, 'CAPTURE_RESERVATION',
+     'Allows a user to capture booking reservations' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 385, 'UPDATE_RECORD',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 386, 'UPDATE_ORG_UNIT_SETTING.circ.block_renews_for_holds',
+     '' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 387, 'MERGE_USERS',
+     'Allows user records to be merged' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 388, 'ISSUANCE_HOLDS',
+     'Allow a user to place holds on serials issuances' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 389, 'VIEW_CREDIT_CARD_PROCESSING',
+     'View org unit settings related to credit card processing' );
+INSERT INTO permission.temp_perm ( id, code, description ) VALUES ( 390, 'ADMIN_CREDIT_CARD_PROCESSING',
+     'Update org unit settings related to credit card processing' );
+
+-- Now for the permissions from the IDL.  We don't have descriptions for them.
+
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 391, 'ADMIN_ACQ_CLAIM' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 392, 'ADMIN_ACQ_CLAIM_EVENT_TYPE' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 393, 'ADMIN_ACQ_CLAIM_TYPE' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 394, 'ADMIN_ACQ_DISTRIB_FORMULA' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 395, 'ADMIN_ACQ_FISCAL_YEAR' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 396, 'ADMIN_ACQ_FUND_ALLOCATION_PERCENT' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 397, 'ADMIN_ACQ_FUND_TAG' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 398, 'ADMIN_ACQ_LINEITEM_ALERT_TEXT' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 399, 'ADMIN_AGE_PROTECT_RULE' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 400, 'ADMIN_ASSET_COPY_TEMPLATE' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 401, 'ADMIN_BOOKING_RESERVATION_ATTR_MAP' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 402, 'ADMIN_CIRC_MATRIX_MATCHPOINT' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 403, 'ADMIN_CIRC_MOD' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 404, 'ADMIN_CLAIM_POLICY' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 405, 'ADMIN_CONFIG_REMOTE_ACCOUNT' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 406, 'ADMIN_FIELD_DOC' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 407, 'ADMIN_GLOBAL_FLAG' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 408, 'ADMIN_GROUP_PENALTY_THRESHOLD' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 409, 'ADMIN_HOLD_CANCEL_CAUSE' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 410, 'ADMIN_HOLD_MATRIX_MATCHPOINT' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 411, 'ADMIN_IDENT_TYPE' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 412, 'ADMIN_IMPORT_ITEM_ATTR_DEF' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 413, 'ADMIN_INDEX_NORMALIZER' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 414, 'ADMIN_INVOICE' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 415, 'ADMIN_INVOICE_METHOD' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 416, 'ADMIN_INVOICE_PAYMENT_METHOD' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 417, 'ADMIN_LINEITEM_MARC_ATTR_DEF' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 418, 'ADMIN_MARC_CODE' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 419, 'ADMIN_MAX_FINE_RULE' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 420, 'ADMIN_MERGE_PROFILE' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 421, 'ADMIN_ORG_UNIT_SETTING_TYPE' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 422, 'ADMIN_RECURRING_FINE_RULE' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 423, 'ADMIN_SERIAL_SUBSCRIPTION' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 424, 'ADMIN_STANDING_PENALTY' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 425, 'ADMIN_SURVEY' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 426, 'ADMIN_USER_REQUEST_TYPE' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 427, 'ADMIN_USER_SETTING_GROUP' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 428, 'ADMIN_USER_SETTING_TYPE' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 429, 'ADMIN_Z3950_SOURCE' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 430, 'CREATE_BIB_BTYPE' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 431, 'CREATE_BIBLIO_FINGERPRINT' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 432, 'CREATE_BIB_SOURCE' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 433, 'CREATE_BILLING_TYPE' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 434, 'CREATE_CN_BTYPE' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 435, 'CREATE_COPY_BTYPE' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 436, 'CREATE_INVOICE' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 437, 'CREATE_INVOICE_ITEM_TYPE' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 438, 'CREATE_INVOICE_METHOD' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 439, 'CREATE_MERGE_PROFILE' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 440, 'CREATE_METABIB_CLASS' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 441, 'CREATE_METABIB_SEARCH_ALIAS' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 442, 'CREATE_USER_BTYPE' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 443, 'DELETE_BIB_BTYPE' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 444, 'DELETE_BIBLIO_FINGERPRINT' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 445, 'DELETE_BIB_SOURCE' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 446, 'DELETE_BILLING_TYPE' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 447, 'DELETE_CN_BTYPE' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 448, 'DELETE_COPY_BTYPE' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 449, 'DELETE_INVOICE_ITEM_TYPE' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 450, 'DELETE_INVOICE_METHOD' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 451, 'DELETE_MERGE_PROFILE' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 452, 'DELETE_METABIB_CLASS' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 453, 'DELETE_METABIB_SEARCH_ALIAS' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 454, 'DELETE_USER_BTYPE' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 455, 'MANAGE_CLAIM' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 456, 'UPDATE_BIB_BTYPE' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 457, 'UPDATE_BIBLIO_FINGERPRINT' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 458, 'UPDATE_BIB_SOURCE' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 459, 'UPDATE_BILLING_TYPE' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 460, 'UPDATE_CN_BTYPE' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 461, 'UPDATE_COPY_BTYPE' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 462, 'UPDATE_INVOICE_ITEM_TYPE' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 463, 'UPDATE_INVOICE_METHOD' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 464, 'UPDATE_MERGE_PROFILE' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 465, 'UPDATE_METABIB_CLASS' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 466, 'UPDATE_METABIB_SEARCH_ALIAS' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 467, 'UPDATE_USER_BTYPE' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 468, 'user_request.create' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 469, 'user_request.delete' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 470, 'user_request.update' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 471, 'user_request.view' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 472, 'VIEW_ACQ_FUND_ALLOCATION_PERCENT' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 473, 'VIEW_CIRC_MATRIX_MATCHPOINT' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 474, 'VIEW_CLAIM' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 475, 'VIEW_GROUP_PENALTY_THRESHOLD' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 476, 'VIEW_HOLD_MATRIX_MATCHPOINT' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 477, 'VIEW_INVOICE' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 478, 'VIEW_MERGE_PROFILE' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 479, 'VIEW_SERIAL_SUBSCRIPTION' );
+INSERT INTO permission.temp_perm ( id, code ) VALUES ( 480, 'VIEW_STANDING_PENALTY' );
+
+-- For every permission in the temp_perm table that has a matching
+-- permission in the real table: record the original id.
+
+UPDATE permission.temp_perm AS tp
+SET old_id =
+	(
+		SELECT id
+		FROM permission.perm_list AS ppl
+		WHERE ppl.code = tp.code
+	)
+WHERE code IN ( SELECT code FROM permission.perm_list );
+
+-- Start juggling ids.
+
+-- If any permissions have negative ids (with the special exception of -1),
+-- we need to move them into the positive range in order to avoid duplicate
+-- key problems (since we are going to use the negative range as a temporary
+-- staging area).
+
+-- First, move any predefined permissions that have negative ids (again with
+-- the special exception of -1).  Temporarily give them positive ids based on
+-- the sequence.
+
+UPDATE permission.perm_list
+SET id = NEXTVAL('permission.perm_list_id_seq'::regclass)
+WHERE id < -1
+  AND code IN (SELECT code FROM permission.temp_perm);
+
+-- Identify any non-predefined permissions whose ids are either negative
+-- or within the range (0-1000) reserved for predefined permissions.
+-- Assign them ids above 1000, based on the sequence.  Record the new
+-- ids in the temp_perm table.
+
+INSERT INTO permission.temp_perm ( id, code, description, old_id, predefined )
+(
+	SELECT NEXTVAL('permission.perm_list_id_seq'::regclass),
+		code, description, id, false
+	FROM permission.perm_list
+	WHERE  ( id < -1 OR id BETWEEN 0 AND 1000 )
+	AND code NOT IN (SELECT code FROM permission.temp_perm)
+);
+
+-- Now update the ids of those non-predefined permissions, using the
+-- values assigned in the previous step.
+
+UPDATE permission.perm_list AS ppl
+SET id = (
+		SELECT id
+		FROM permission.temp_perm AS tp
+		WHERE tp.code = ppl.code
+	)
+WHERE id IN ( SELECT old_id FROM permission.temp_perm WHERE NOT predefined );
+
+-- Now the negative ids have been eliminated, except for -1.  Move all the
+-- predefined permissions temporarily into the negative range.
+
+UPDATE permission.perm_list
+SET id = -1 - id
+WHERE id <> -1
+AND code IN ( SELECT code from permission.temp_perm WHERE predefined );
+
+-- Apply the final ids to the existing predefined permissions.
+
+UPDATE permission.perm_list AS ppl
+SET id =
+	(
+		SELECT id
+		FROM permission.temp_perm AS tp
+		WHERE tp.code = ppl.code
+	)
+WHERE
+	id <> -1
+	AND ppl.code IN
+	(
+		SELECT code from permission.temp_perm
+		WHERE predefined
+		AND old_id IS NOT NULL
+	);
+
+-- If there are any predefined permissions that don't exist yet in
+-- permission.perm_list, insert them now.
+
+INSERT INTO permission.perm_list ( id, code, description )
+(
+	SELECT id, code, description
+	FROM permission.temp_perm
+	WHERE old_id IS NULL
+);
+
+-- Reset the sequence to the lowest feasible value.  This may or may not
+-- accomplish anything, but it will do no harm.
+
+SELECT SETVAL('permission.perm_list_id_seq'::TEXT, GREATEST( 
+	(SELECT MAX(id) FROM permission.perm_list), 1000 ));
+
+-- If any permission lacks a description, use the code as a description.
+-- It's better than nothing.
+
+UPDATE permission.perm_list
+SET description = code
+WHERE description IS NULL
+   OR description = '';
+
+-- Thus endeth the Great Renumbering.
+
+-- Having massaged the permissions, massage the way they are assigned, by inserting
+-- rows into permission.grp_perm_map.  Some of these permissions may have already
+-- been assigned, so we insert the rows only if they aren't already there.
+
+-- for backwards compat, give everyone the permission
+INSERT INTO permission.grp_perm_map (grp, perm, depth, grantable)
+    SELECT 1, id, 0, false FROM permission.perm_list AS perm
+	WHERE code = 'HOLD_ITEM_CHECKED_OUT.override'
+		AND NOT EXISTS (
+			SELECT 1
+			FROM permission.grp_perm_map AS map
+			WHERE
+				grp = 1
+				AND map.perm = perm.id
+		);
+
+-- Add trigger administration permissions to the Local System Administrator group.
+INSERT INTO permission.grp_perm_map (grp, perm, depth, grantable)
+    SELECT 10, id, 1, false FROM permission.perm_list AS perm
+    WHERE (
+		perm.code LIKE 'ADMIN_TRIGGER%'
+        OR perm.code LIKE 'CREATE_TRIGGER%'
+        OR perm.code LIKE 'DELETE_TRIGGER%'
+        OR perm.code LIKE 'UPDATE_TRIGGER%'
+	) AND NOT EXISTS (
+		SELECT 1
+		FROM permission.grp_perm_map AS map
+		WHERE
+			grp = 10
+			AND map.perm = perm.id
+	);
+
+-- View trigger permissions are required at a consortial level for initial setup
+-- (as before, only if the row doesn't already exist)
+INSERT INTO permission.grp_perm_map (grp, perm, depth, grantable)
+    SELECT 10, id, 0, false FROM permission.perm_list AS perm
+	WHERE code LIKE 'VIEW_TRIGGER%'
+		AND NOT EXISTS (
+			SELECT 1
+			FROM permission.grp_perm_map AS map
+			WHERE
+				grp = 10
+				AND map.perm = perm.id
+		);
+
+-- Permission for merging auth records may already be defined,
+-- so add it only if it isn't there.
+INSERT INTO permission.grp_perm_map (grp, perm, depth, grantable)
+    SELECT 4, id, 1, false FROM permission.perm_list AS perm
+	WHERE code = 'MERGE_AUTH_RECORDS'
+		AND NOT EXISTS (
+			SELECT 1
+			FROM permission.grp_perm_map AS map
+			WHERE
+				grp = 4
+				AND map.perm = perm.id
+		);
+
+-- Create a reference table as parent to both
+-- config.org_unit_setting_type and config_usr_setting_type
+
+CREATE TABLE config.settings_group (
+    name    TEXT PRIMARY KEY,
+    label   TEXT UNIQUE NOT NULL -- I18N
+);
+
+-- org_unit setting types
+CREATE TABLE config.org_unit_setting_type (
+    name            TEXT    PRIMARY KEY,
+    label           TEXT    UNIQUE NOT NULL,
+    grp             TEXT    REFERENCES config.settings_group (name),
+    description     TEXT,
+    datatype        TEXT    NOT NULL DEFAULT 'string',
+    fm_class        TEXT,
+    view_perm       INT,
+    update_perm     INT,
+    --
+    -- define valid datatypes
+    --
+    CONSTRAINT coust_valid_datatype CHECK ( datatype IN
+    ( 'bool', 'integer', 'float', 'currency', 'interval',
+      'date', 'string', 'object', 'array', 'link' ) ),
+    --
+    -- fm_class is meaningful only for 'link' datatype
+    --
+    CONSTRAINT coust_no_empty_link CHECK
+    ( ( datatype =  'link' AND fm_class IS NOT NULL ) OR
+      ( datatype <> 'link' AND fm_class IS NULL ) ),
+	CONSTRAINT view_perm_fkey FOREIGN KEY (view_perm) REFERENCES permission.perm_list (id)
+		ON UPDATE CASCADE
+		ON DELETE RESTRICT
+		DEFERRABLE INITIALLY DEFERRED,
+	CONSTRAINT update_perm_fkey FOREIGN KEY (update_perm) REFERENCES permission.perm_list (id)
+		ON UPDATE CASCADE
+		DEFERRABLE INITIALLY DEFERRED
+);
+
+CREATE TABLE config.usr_setting_type (
+
+    name TEXT PRIMARY KEY,
+    opac_visible BOOL NOT NULL DEFAULT FALSE,
+    label TEXT UNIQUE NOT NULL,
+    description TEXT,
+    grp             TEXT    REFERENCES config.settings_group (name),
+    datatype TEXT NOT NULL DEFAULT 'string',
+    fm_class TEXT,
+
+    --
+    -- define valid datatypes
+    --
+    CONSTRAINT coust_valid_datatype CHECK ( datatype IN
+    ( 'bool', 'integer', 'float', 'currency', 'interval',
+        'date', 'string', 'object', 'array', 'link' ) ),
+
+    --
+    -- fm_class is meaningful only for 'link' datatype
+    --
+    CONSTRAINT coust_no_empty_link CHECK
+    ( ( datatype = 'link' AND fm_class IS NOT NULL ) OR
+        ( datatype <> 'link' AND fm_class IS NULL ) )
+
+);
+
+--------------------------------------
+-- Seed data for org_unit_setting_type
+--------------------------------------
+
+INSERT into config.org_unit_setting_type
+( name, label, description, datatype ) VALUES
+
+( 'auth.opac_timeout',
+  'OPAC Inactivity Timeout (in seconds)',
+  null,
+  'integer' ),
+
+( 'auth.staff_timeout',
+  'Staff Login Inactivity Timeout (in seconds)',
+  null,
+  'integer' ),
+
+( 'circ.lost_materials_processing_fee',
+  'Lost Materials Processing Fee',
+  null,
+  'currency' ),
+
+( 'cat.default_item_price',
+  'Default Item Price',
+  null,
+  'currency' ),
+
+( 'org.bounced_emails',
+  'Sending email address for patron notices',
+  null,
+  'string' ),
+
+( 'circ.hold_expire_alert_interval',
+  'Holds: Expire Alert Interval',
+  'Amount of time before a hold expires at which point the patron should be alerted',
+  'interval' ),
+
+( 'circ.hold_expire_interval',
+  'Holds: Expire Interval',
+  'Amount of time after a hold is placed before the hold expires.  Example "100 days"',
+  'interval' ),
+
+( 'credit.payments.allow',
+  'Allow Credit Card Payments',
+  'If enabled, patrons will be able to pay fines accrued at this location via credit card',
+  'bool' ),
+
+( 'global.default_locale',
+  'Global Default Locale',
+  null,
+  'string' ),
+
+( 'circ.void_overdue_on_lost',
+  'Void overdue fines when items are marked lost',
+  null,
+  'bool' ),
+
+( 'circ.hold_stalling.soft',
+  'Holds: Soft stalling interval',
+  'How long to wait before allowing remote items to be opportunistically captured for a hold.  Example "5 days"',
+  'interval' ),
+
+( 'circ.hold_stalling_hard',
+  'Holds: Hard stalling interval',
+  '',
+  'interval' ),
+
+( 'circ.hold_boundary.hard',
+  'Holds: Hard boundary',
+  null,
+  'integer' ),
+
+( 'circ.hold_boundary.soft',
+  'Holds: Soft boundary',
+  null,
+  'integer' ),
+
+( 'opac.barcode_regex',
+  'Patron barcode format',
+  'Regular expression defining the patron barcode format',
+  'string' ),
+
+( 'global.password_regex',
+  'Password format',
+  'Regular expression defining the password format',
+  'string' ),
+
+( 'circ.item_checkout_history.max',
+  'Maximum previous checkouts displayed',
+  'This is the maximum number of previous circulations the staff client will display when investigating item details',
+  'integer' ),
+
+( 'circ.reshelving_complete.interval',
+  'Change reshelving status interval',
+  'Amount of time to wait before changing an item from "reshelving" status to "available".  Examples: "1 day", "6 hours"',
+  'interval' ),
+
+( 'circ.holds.default_estimated_wait_interval',
+  'Holds: Default Estimated Wait',
+  'When predicting the amount of time a patron will be waiting for a hold to be fulfilled, this is the default estimated length of time to assume an item will be checked out.',
+  'interval' ),
+
+( 'circ.holds.min_estimated_wait_interval',
+  'Holds: Minimum Estimated Wait',
+  'When predicting the amount of time a patron will be waiting for a hold to be fulfilled, this is the minimum estimated length of time to assume an item will be checked out.',
+  'interval' ),
+
+( 'circ.selfcheck.patron_login_timeout',
+  'Selfcheck: Patron Login Timeout (in seconds)',
+  'Number of seconds of inactivity before the patron is logged out of the selfcheck interface',
+  'integer' ),
+
+( 'circ.selfcheck.alert.popup',
+  'Selfcheck: Pop-up alert for errors',
+  'If true, checkout/renewal errors will cause a pop-up window in addition to the on-screen message',
+  'bool' ),
+
+( 'circ.selfcheck.require_patron_password',
+  'Selfcheck: Require patron password',
+  'If true, patrons will be required to enter their password in addition to their username/barcode to log into the selfcheck interface',
+  'bool' ),
+
+( 'global.juvenile_age_threshold',
+  'Juvenile Age Threshold',
+  'The age at which a user is no long considered a juvenile.  For example, "18 years".',
+  'interval' ),
+
+( 'cat.bib.keep_on_empty',
+  'Retain empty bib records',
+  'Retain a bib record even when all attached copies are deleted',
+  'bool' ),
+
+( 'cat.bib.alert_on_empty',
+  'Alert on empty bib records',
+  'Alert staff when the last copy for a record is being deleted',
+  'bool' ),
+
+( 'patron.password.use_phone',
+  'Patron: password from phone #',
+  'Use the last 4 digits of the patrons phone number as the default password when creating new users',
+  'bool' ),
+
+( 'circ.charge_on_damaged',
+  'Charge item price when marked damaged',
+  'Charge item price when marked damaged',
+  'bool' ),
+
+( 'circ.charge_lost_on_zero',
+  'Charge lost on zero',
+  '',
+  'bool' ),
+
+( 'circ.damaged_item_processing_fee',
+  'Charge processing fee for damaged items',
+  'Charge processing fee for damaged items',
+  'currency' ),
+
+( 'circ.void_lost_on_checkin',
+  'Circ: Void lost item billing when returned',
+  'Void lost item billing when returned',
+  'bool' ),
+
+( 'circ.max_accept_return_of_lost',
+  'Circ: Void lost max interval',
+  'Items that have been lost this long will not result in voided billings when returned.  E.g. ''6 months''',
+  'interval' ),
+
+( 'circ.void_lost_proc_fee_on_checkin',
+  'Circ: Void processing fee on lost item return',
+  'Void processing fee when lost item returned',
+  'bool' ),
+
+( 'circ.restore_overdue_on_lost_return',
+  'Circ: Restore overdues on lost item return',
+  'Restore overdue fines on lost item return',
+  'bool' ),
+
+( 'circ.lost_immediately_available',
+  'Circ: Lost items usable on checkin',
+  'Lost items are usable on checkin instead of going ''home'' first',
+  'bool' ),
+
+( 'circ.holds_fifo',
+  'Holds: FIFO',
+  'Force holds to a more strict First-In, First-Out capture',
+  'bool' ),
+
+( 'opac.allow_pending_address',
+  'OPAC: Allow pending addresses',
+  'If enabled, patrons can create and edit existing addresses.  Addresses are kept in a pending state until staff approves the changes',
+  'bool' ),
+
+( 'ui.circ.show_billing_tab_on_bills',
+  'Show billing tab first when bills are present',
+  'If enabled and a patron has outstanding bills and the alert page is not required, show the billing tab by default, instead of the checkout tab, when a patron is loaded',
+  'bool' ),
+
+( 'ui.general.idle_timeout',
+    'GUI: Idle timeout',
+    'If you want staff client windows to be minimized after a certain amount of system idle time, set this to the number of seconds of idle time that you want to allow before minimizing (requires staff client restart).',
+    'integer' ),
+
+( 'ui.circ.in_house_use.entry_cap',
+  'GUI: Record In-House Use: Maximum # of uses allowed per entry.',
+  'The # of uses entry in the Record In-House Use interface may not exceed the value of this setting.',
+  'integer' ),
+
+( 'ui.circ.in_house_use.entry_warn',
+  'GUI: Record In-House Use: # of uses threshold for Are You Sure? dialog.',
+  'In the Record In-House Use interface, a submission attempt will warn if the # of uses field exceeds the value of this setting.',
+  'integer' ),
+
+( 'acq.default_circ_modifier',
+  'Default circulation modifier',
+  null,
+  'string' ),
+
+( 'acq.tmp_barcode_prefix',
+  'Temporary barcode prefix',
+  null,
+  'string' ),
+
+( 'acq.tmp_callnumber_prefix',
+  'Temporary call number prefix',
+  null,
+  'string' ),
+
+( 'ui.circ.patron_summary.horizontal',
+  'Patron circulation summary is horizontal',
+  null,
+  'bool' ),
+
+( 'ui.staff.require_initials',
+  oils_i18n_gettext('ui.staff.require_initials', 'GUI: Require staff initials for entry/edit of item/patron/penalty notes/messages.', 'coust', 'label'),
+  oils_i18n_gettext('ui.staff.require_initials', 'Appends staff initials and edit date into note content.', 'coust', 'description'),
+  'bool' ),
+
+( 'ui.general.button_bar',
+  'Button bar',
+  null,
+  'bool' ),
+
+( 'circ.hold_shelf_status_delay',
+  'Hold Shelf Status Delay',
+  'The purpose is to provide an interval of time after an item goes into the on-holds-shelf status before it appears to patrons that it is actually on the holds shelf.  This gives staff time to process the item before it shows as ready-for-pickup.',
+  'interval' ),
+
+( 'circ.patron_invalid_address_apply_penalty',
+  'Invalid patron address penalty',
+  'When set, if a patron address is set to invalid, a penalty is applied.',
+  'bool' ),
+
+( 'circ.checkout_fills_related_hold',
+  'Checkout Fills Related Hold',
+  'When a patron checks out an item and they have no holds that directly target the item, the system will attempt to find a hold for the patron that could be fulfilled by the checked out item and fulfills it',
+  'bool'),
+
+( 'circ.selfcheck.auto_override_checkout_events',
+  'Selfcheck override events list',
+  'List of checkout/renewal events that the selfcheck interface should automatically override instead instead of alerting and stopping the transaction',
+  'array' ),
+
+( 'circ.staff_client.do_not_auto_attempt_print',
+  'Disable Automatic Print Attempt Type List',
+  'Disable automatic print attempts from staff client interfaces for the receipt types in this list.  Possible values: "Checkout", "Bill Pay", "Hold Slip", "Transit Slip", and "Hold/Transit Slip".  This is different from the Auto-Print checkbox in the pertinent interfaces in that it disables automatic print attempts altogether, rather than encouraging silent printing by suppressing the print dialog.  The Auto-Print checkbox in these interfaces have no effect on the behavior for this setting.  In the case of the Hold, Transit, and Hold/Transit slips, this also suppresses the alert dialogs that precede the print dialog (the ones that offer Print and Do Not Print as options).',
+  'array' ),
+
+( 'ui.patron.default_inet_access_level',
+  'Default level of patrons'' internet access',
+  null,
+  'integer' ),
+
+( 'circ.max_patron_claim_return_count',
+    'Max Patron Claims Returned Count',
+    'When this count is exceeded, a staff override is required to mark the item as claims returned',
+    'integer' ),
+
+( 'circ.obscure_dob',
+    'Obscure the Date of Birth field',
+    'When true, the Date of Birth column in patron lists will default to Not Visible, and in the Patron Summary sidebar the value will display as <Hidden> unless the field label is clicked.',
+    'bool' ),
+
+( 'circ.auto_hide_patron_summary',
+    'GUI: Toggle off the patron summary sidebar after first view.',
+    'When true, the patron summary sidebar will collapse after a new patron sub-interface is selected.',
+    'bool' ),
+
+( 'credit.processor.default',
+    'Credit card processing: Name default credit processor',
+    'This can be "AuthorizeNet", "PayPal" (for the Website Payment Pro API), or "PayflowPro".',
+    'string' ),
+
+( 'credit.processor.authorizenet.enabled',
+    'Credit card processing: AuthorizeNet enabled',
+    '',
+    'bool' ),
+
+( 'credit.processor.authorizenet.login',
+    'Credit card processing: AuthorizeNet login',
+    '',
+    'string' ),
+
+( 'credit.processor.authorizenet.password',
+    'Credit card processing: AuthorizeNet password',
+    '',
+    'string' ),
+
+( 'credit.processor.authorizenet.server',
+    'Credit card processing: AuthorizeNet server',
+    'Required if using a developer/test account with AuthorizeNet',
+    'string' ),
+
+( 'credit.processor.authorizenet.testmode',
+    'Credit card processing: AuthorizeNet test mode',
+    '',
+    'bool' ),
+
+( 'credit.processor.paypal.enabled',
+    'Credit card processing: PayPal enabled',
+    '',
+    'bool' ),
+( 'credit.processor.paypal.login',
+    'Credit card processing: PayPal login',
+    '',
+    'string' ),
+( 'credit.processor.paypal.password',
+    'Credit card processing: PayPal password',
+    '',
+    'string' ),
+( 'credit.processor.paypal.signature',
+    'Credit card processing: PayPal signature',
+    '',
+    'string' ),
+( 'credit.processor.paypal.testmode',
+    'Credit card processing: PayPal test mode',
+    '',
+    'bool' ),
+
+( 'ui.admin.work_log.max_entries',
+    oils_i18n_gettext('ui.admin.work_log.max_entries', 'GUI: Work Log: Maximum Actions Logged', 'coust', 'label'),
+    oils_i18n_gettext('ui.admin.work_log.max_entries', 'Maximum entries for "Most Recent Staff Actions" section of the Work Log interface.', 'coust', 'description'),
+  'interval' ),
+
+( 'ui.admin.patron_log.max_entries',
+    oils_i18n_gettext('ui.admin.patron_log.max_entries', 'GUI: Work Log: Maximum Patrons Logged', 'coust', 'label'),
+    oils_i18n_gettext('ui.admin.patron_log.max_entries', 'Maximum entries for "Most Recently Affected Patrons..." section of the Work Log interface.', 'coust', 'description'),
+  'interval' ),
+
+( 'lib.courier_code',
+    oils_i18n_gettext('lib.courier_code', 'Courier Code', 'coust', 'label'),
+    oils_i18n_gettext('lib.courier_code', 'Courier Code for the library.  Available in transit slip templates as the %courier_code% macro.', 'coust', 'description'),
+    'string'),
+
+( 'circ.block_renews_for_holds',
+    oils_i18n_gettext('circ.block_renews_for_holds', 'Holds: Block Renewal of Items Needed for Holds', 'coust', 'label'),
+    oils_i18n_gettext('circ.block_renews_for_holds', 'When an item could fulfill a hold, do not allow the current patron to renew', 'coust', 'description'),
+    'bool' ),
+
+( 'circ.password_reset_request_per_user_limit',
+    oils_i18n_gettext('circ.password_reset_request_per_user_limit', 'Circulation: Maximum concurrently active self-serve password reset requests per user', 'coust', 'label'),
+    oils_i18n_gettext('circ.password_reset_request_per_user_limit', 'When a user has more than this number of concurrently active self-serve password reset requests for their account, prevent the user from creating any new self-serve password reset requests until the number of active requests for the user drops back below this number.', 'coust', 'description'),
+    'string'),
+
+( 'circ.password_reset_request_time_to_live',
+    oils_i18n_gettext('circ.password_reset_request_time_to_live', 'Circulation: Self-serve password reset request time-to-live', 'coust', 'label'),
+    oils_i18n_gettext('circ.password_reset_request_time_to_live', 'Length of time (in seconds) a self-serve password reset request should remain active.', 'coust', 'description'),
+    'string'),
+
+( 'circ.password_reset_request_throttle',
+    oils_i18n_gettext('circ.password_reset_request_throttle', 'Circulation: Maximum concurrently active self-serve password reset requests', 'coust', 'label'),
+    oils_i18n_gettext('circ.password_reset_request_throttle', 'Prevent the creation of new self-serve password reset requests until the number of active requests drops back below this number.', 'coust', 'description'),
+    'string')
+;
+
+INSERT INTO config.org_unit_setting_type ( name, label, description, datatype ) VALUES (
+        'ui.circ.suppress_checkin_popups',
+        oils_i18n_gettext(
+            'ui.circ.suppress_checkin_popups', 
+            'Circ: Suppress popup-dialogs during check-in.', 
+            'coust', 
+            'label'),
+        oils_i18n_gettext(
+            'ui.circ.suppress_checkin_popups', 
+            'Circ: Suppress popup-dialogs during check-in.', 
+            'coust', 
+            'description'),
+        'bool'
+);
+
+INSERT INTO config.org_unit_setting_type ( name, label, description, datatype ) VALUES (
+        'format.date',
+        oils_i18n_gettext(
+            'format.date',
+            'GUI: Format Dates with this pattern.', 
+            'coust', 
+            'label'),
+        oils_i18n_gettext(
+            'format.date',
+            'GUI: Format Dates with this pattern (examples: "yyyy-MM-dd" for "2010-04-26", "MMM d, yyyy" for "Apr 26, 2010")', 
+            'coust', 
+            'description'),
+        'string'
+), (
+        'format.time',
+        oils_i18n_gettext(
+            'format.time',
+            'GUI: Format Times with this pattern.', 
+            'coust', 
+            'label'),
+        oils_i18n_gettext(
+            'format.time',
+            'GUI: Format Times with this pattern (examples: "h:m:s.SSS a z" for "2:07:20.666 PM Eastern Daylight Time", "HH:mm" for "14:07")', 
+            'coust', 
+            'description'),
+        'string'
+);
+
+INSERT INTO config.org_unit_setting_type ( name, label, description, datatype ) VALUES (
+        'cat.bib.delete_on_no_copy_via_acq_lineitem_cancel',
+        oils_i18n_gettext(
+            'cat.bib.delete_on_no_copy_via_acq_lineitem_cancel',
+            'CAT: Delete bib if all copies are deleted via Acquisitions lineitem cancellation.', 
+            'coust', 
+            'label'),
+        oils_i18n_gettext(
+            'cat.bib.delete_on_no_copy_via_acq_lineitem_cancel',
+            'CAT: Delete bib if all copies are deleted via Acquisitions lineitem cancellation.', 
+            'coust', 
+            'description'),
+        'bool'
+);
+
+INSERT INTO config.org_unit_setting_type ( name, label, description, datatype ) VALUES (
+        'url.remote_column_settings',
+        oils_i18n_gettext(
+            'url.remote_column_settings',
+            'GUI: URL for remote directory containing list column settings.', 
+            'coust', 
+            'label'),
+        oils_i18n_gettext(
+            'url.remote_column_settings',
+            'GUI: URL for remote directory containing list column settings.  The format and naming convention for the files found in this directory match those in the local settings directory for a given workstation.  An administrator could create the desired settings locally and then copy all the tree_columns_for_* files to the remote directory.', 
+            'coust', 
+            'description'),
+        'string'
+);
+
+INSERT INTO config.org_unit_setting_type ( name, label, description, datatype ) VALUES (
+        'gui.disable_local_save_columns',
+        oils_i18n_gettext(
+            'gui.disable_local_save_columns',
+            'GUI: Disable the ability to save list column configurations locally.', 
+            'coust', 
+            'label'),
+        oils_i18n_gettext(
+            'gui.disable_local_save_columns',
+            'GUI: Disable the ability to save list column configurations locally.  If set, columns may still be manipulated, however, the changes do not persist.  Also, existing local configurations are ignored if this setting is true.', 
+            'coust', 
+            'description'),
+        'bool'
+);
+
+INSERT INTO config.org_unit_setting_type ( name, label, description, datatype ) VALUES (
+        'circ.password_reset_request_requires_matching_email',
+        oils_i18n_gettext(
+            'circ.password_reset_request_requires_matching_email',
+            'Circulation: Require matching email address for password reset requests', 
+            'coust', 
+            'label'),
+        oils_i18n_gettext(
+            'circ.password_reset_request_requires_matching_email',
+            'Circulation: Require matching email address for password reset requests', 
+            'coust', 
+            'description'),
+        'bool'
+);
+
+INSERT INTO config.org_unit_setting_type ( name, label, description, datatype ) VALUES (
+        'circ.holds.expired_patron_block',
+        oils_i18n_gettext(
+            'circ.holds.expired_patron_block',
+            'Circulation: Block hold request if hold recipient privileges have expired', 
+            'coust', 
+            'label'),
+        oils_i18n_gettext(
+            'circ.holds.expired_patron_block',
+            'Circulation: Block hold request if hold recipient privileges have expired', 
+            'coust', 
+            'description'),
+        'bool'
+);
+
+INSERT INTO config.org_unit_setting_type
+    (name, label, description, datatype) VALUES (
+        'circ.booking_reservation.default_elbow_room',
+        oils_i18n_gettext(
+            'circ.booking_reservation.default_elbow_room',
+            'Booking: Elbow room',
+            'coust',
+            'label'
+        ),
+        oils_i18n_gettext(
+            'circ.booking_reservation.default_elbow_room',
+            'Elbow room specifies how far in the future you must make a reservation on an item if that item will have to transit to reach its pickup location.  It secondarily defines how soon a reservation on a given item must start before the check-in process will opportunistically capture it for the reservation shelf.',
+            'coust',
+            'label'
+        ),
+        'interval'
+    );
+
+-- Org_unit_setting_type(s) that need an fm_class:
+INSERT into config.org_unit_setting_type
+( name, label, description, datatype, fm_class ) VALUES
+( 'acq.default_copy_location',
+  'Default copy location',
+  null,
+  'link',
+  'acpl' );
+
+INSERT INTO config.org_unit_setting_type (name, label, description, datatype) VALUES (
+    'circ.holds.org_unit_target_weight',
+    'Holds: Org Unit Target Weight',
+    'Org Units can be organized into hold target groups based on a weight.  Potential copies from org units with the same weight are chosen at random.',
+    'integer'
+);
+
+INSERT INTO config.org_unit_setting_type (name, label, description, datatype) VALUES (
+    'circ.holds.target_holds_by_org_unit_weight',
+    'Holds: Use weight-based hold targeting',
+    'Use library weight based hold targeting',
+    'bool'
+);
+
+INSERT INTO config.org_unit_setting_type (name, label, description, datatype) VALUES (
+    'circ.holds.max_org_unit_target_loops',
+    'Holds: Maximum library target attempts',
+    'When this value is set and greater than 0, the system will only attempt to find a copy at each possible branch the configured number of times',
+    'integer'
+);
+
+
+-- Org setting for overriding the circ lib of a precat copy
+INSERT INTO config.org_unit_setting_type (name, label, description, datatype) VALUES (
+    'circ.pre_cat_copy_circ_lib',
+    'Pre-cat Item Circ Lib',
+    'Override the default circ lib of "here" with a pre-configured circ lib for pre-cat items.  The value should be the "shortname" (aka policy name) of the org unit',
+    'string'
+);
+
+-- Circ auto-renew interval setting
+INSERT INTO config.org_unit_setting_type (name, label, description, datatype) VALUES (
+    'circ.checkout_auto_renew_age',
+    'Checkout auto renew age',
+    'When an item has been checked out for at least this amount of time, an attempt to check out the item to the patron that it is already checked out to will simply renew the circulation',
+    'interval'
+);
+
+-- Setting for behind the desk hold pickups
+INSERT INTO config.org_unit_setting_type (name, label, description, datatype) VALUES (
+    'circ.holds.behind_desk_pickup_supported',
+    'Holds: Behind Desk Pickup Supported',
+    'If a branch supports both a public holds shelf and behind-the-desk pickups, set this value to true.  This gives the patron the option to enable behind-the-desk pickups for their holds',
+    'bool'
+);
+
+INSERT INTO config.org_unit_setting_type ( name, label, description, datatype ) VALUES (
+        'acq.holds.allow_holds_from_purchase_request',
+        oils_i18n_gettext(
+            'acq.holds.allow_holds_from_purchase_request', 
+            'Allows patrons to create automatic holds from purchase requests.', 
+            'coust', 
+            'label'),
+        oils_i18n_gettext(
+            'acq.holds.allow_holds_from_purchase_request', 
+            'Allows patrons to create automatic holds from purchase requests.', 
+            'coust', 
+            'description'),
+        'bool'
+);
+
+INSERT INTO config.org_unit_setting_type (name, label, description, datatype) VALUES (
+    'circ.holds.target_skip_me',
+    'Skip For Hold Targeting',
+    'When true, don''t target any copies at this org unit for holds',
+    'bool'
+);
+
+-- claims returned mark item missing 
+INSERT INTO
+    config.org_unit_setting_type ( name, label, description, datatype )
+    VALUES (
+        'circ.claim_return.mark_missing',
+        'Claim Return: Mark copy as missing', 
+        'When a circ is marked as claims-returned, also mark the copy as missing',
+        'bool'
+    );
+
+-- claims never checked out mark item missing 
+INSERT INTO
+    config.org_unit_setting_type ( name, label, description, datatype )
+    VALUES (
+        'circ.claim_never_checked_out.mark_missing',
+        'Claim Never Checked Out: Mark copy as missing', 
+        'When a circ is marked as claims-never-checked-out, mark the copy as missing',
+        'bool'
+    );
+
+-- mark damaged void overdue setting
+INSERT INTO
+    config.org_unit_setting_type ( name, label, description, datatype )
+    VALUES (
+        'circ.damaged.void_ovedue',
+        'Mark item damaged voids overdues',
+        'When an item is marked damaged, overdue fines on the most recent circulation are voided.',
+        'bool'
+    );
+
+-- hold cancel display limits
+INSERT INTO config.org_unit_setting_type ( name, label, description, datatype )
+    VALUES (
+        'circ.holds.canceled.display_count',
+        'Holds: Canceled holds display count',
+        'How many canceled holds to show in patron holds interfaces',
+        'integer'
+    );
+
+INSERT INTO config.org_unit_setting_type ( name, label, description, datatype )
+    VALUES (
+        'circ.holds.canceled.display_age',
+        'Holds: Canceled holds display age',
+        'Show all canceled holds that were canceled within this amount of time',
+        'interval'
+    );
+
+INSERT INTO config.org_unit_setting_type ( name, label, description, datatype )
+    VALUES (
+        'circ.holds.uncancel.reset_request_time',
+        'Holds: Reset request time on un-cancel',
+        'When a hold is uncanceled, reset the request time to push it to the end of the queue',
+        'bool'
+    );
+
+INSERT INTO config.org_unit_setting_type (name, label, description, datatype)
+    VALUES (
+        'circ.holds.default_shelf_expire_interval',
+        'Default hold shelf expire interval',
+        '',
+        'interval'
+);
+
+INSERT INTO config.org_unit_setting_type (name, label, description, datatype, fm_class)
+    VALUES (
+        'circ.claim_return.copy_status', 
+        'Claim Return Copy Status', 
+        'Claims returned copies are put into this status.  Default is to leave the copy in the Checked Out status',
+        'link', 
+        'ccs' 
+    );
+
+INSERT INTO config.org_unit_setting_type ( name, label, description, datatype ) 
+    VALUES ( 
+        'circ.max_fine.cap_at_price',
+        oils_i18n_gettext('circ.max_fine.cap_at_price', 'Circ: Cap Max Fine at Item Price', 'coust', 'label'),
+        oils_i18n_gettext('circ.max_fine.cap_at_price', 'This prevents the system from charging more than the item price in overdue fines', 'coust', 'description'),
+        'bool' 
+    );
+
+INSERT INTO config.org_unit_setting_type ( name, label, description, datatype, fm_class ) 
+    VALUES ( 
+        'circ.holds.clear_shelf.copy_status',
+        oils_i18n_gettext('circ.holds.clear_shelf.copy_status', 'Holds: Clear shelf copy status', 'coust', 'label'),
+        oils_i18n_gettext('circ.holds.clear_shelf.copy_status', 'Any copies that have not been put into reshelving, in-transit, or on-holds-shelf (for a new hold) during the clear shelf process will be put into this status.  This is basically a purgatory status for copies waiting to be pulled from the shelf and processed by hand', 'coust', 'description'),
+        'link',
+        'ccs'
+    );
+
+INSERT INTO config.org_unit_setting_type ( name, label, description, datatype )
+    VALUES ( 
+        'circ.selfcheck.workstation_required',
+        oils_i18n_gettext('circ.selfcheck.workstation_required', 'Selfcheck: Workstation Required', 'coust', 'label'),
+        oils_i18n_gettext('circ.selfcheck.workstation_required', 'All selfcheck stations must use a workstation', 'coust', 'description'),
+        'bool'
+    ), (
+        'circ.selfcheck.patron_password_required',
+        oils_i18n_gettext('circ.selfcheck.patron_password_required', 'Selfcheck: Require Patron Password', 'coust', 'label'),
+        oils_i18n_gettext('circ.selfcheck.patron_password_required', 'Patron must log in with barcode and password at selfcheck station', 'coust', 'description'),
+        'bool'
+    );
+
+INSERT INTO config.org_unit_setting_type ( name, label, description, datatype )
+    VALUES ( 
+        'circ.selfcheck.alert.sound',
+        oils_i18n_gettext('circ.selfcheck.alert.sound', 'Selfcheck: Audio Alerts', 'coust', 'label'),
+        oils_i18n_gettext('circ.selfcheck.alert.sound', 'Use audio alerts for selfcheck events', 'coust', 'description'),
+        'bool'
+    );
+
+INSERT INTO
+    config.org_unit_setting_type (name, label, description, datatype)
+    VALUES (
+        'notice.telephony.callfile_lines',
+        'Telephony: Arbitrary line(s) to include in each notice callfile',
+        $$
+        This overrides lines from opensrf.xml.
+        Line(s) must be valid for your target server and platform
+        (e.g. Asterisk 1.4).
+        $$,
+        'string'
+    );
+
+INSERT INTO config.org_unit_setting_type ( name, label, description, datatype )
+    VALUES ( 
+        'circ.offline.username_allowed',
+        oils_i18n_gettext('circ.offline.username_allowed', 'Offline: Patron Usernames Allowed', 'coust', 'label'),
+        oils_i18n_gettext('circ.offline.username_allowed', 'During offline circulations, allow patrons to identify themselves with usernames in addition to barcode.  For this setting to work, a barcode format must also be defined', 'coust', 'description'),
+        'bool'
+    );
+
+INSERT INTO config.org_unit_setting_type ( name, label, description, datatype )
+VALUES (
+    'acq.fund.balance_limit.warn',
+    oils_i18n_gettext('acq.fund.balance_limit.warn', 'Fund Spending Limit for Warning', 'coust', 'label'),
+    oils_i18n_gettext('acq.fund.balance_limit.warn', 'When the amount remaining in the fund, including spent money and encumbrances, goes below this percentage, attempts to spend from the fund will result in a warning to the staff.', 'coust', 'descripton'),
+    'integer'
+);
+
+INSERT INTO config.org_unit_setting_type ( name, label, description, datatype )
+VALUES (
+    'acq.fund.balance_limit.block',
+    oils_i18n_gettext('acq.fund.balance_limit.block', 'Fund Spending Limit for Block', 'coust', 'label'),
+    oils_i18n_gettext('acq.fund.balance_limit.block', 'When the amount remaining in the fund, including spent money and encumbrances, goes below this percentage, attempts to spend from the fund will be blocked.', 'coust', 'description'),
+    'integer'
+);
+
+INSERT INTO config.org_unit_setting_type ( name, label, description, datatype )
+    VALUES (
+        'circ.holds.hold_has_copy_at.alert',
+        oils_i18n_gettext('circ.holds.hold_has_copy_at.alert', 'Holds: Has Local Copy Alert', 'coust', 'label'),
+        oils_i18n_gettext('circ.holds.hold_has_copy_at.alert', 'If there is an available copy at the requesting library that could fulfill a hold during hold placement time, alert the patron', 'coust', 'description'),
+        'bool'
+    ),(
+        'circ.holds.hold_has_copy_at.block',
+        oils_i18n_gettext('circ.holds.hold_has_copy_at.block', 'Holds: Has Local Copy Block', 'coust', 'label'),
+        oils_i18n_gettext('circ.holds.hold_has_copy_at.block', 'If there is an available copy at the requesting library that could fulfill a hold during hold placement time, do not allow the hold to be placed', 'coust', 'description'),
+        'bool'
+    );
+
+INSERT INTO config.org_unit_setting_type ( name, label, description, datatype )
+VALUES (
+    'auth.persistent_login_interval',
+    oils_i18n_gettext('auth.persistent_login_interval', 'Persistent Login Duration', 'coust', 'label'),
+    oils_i18n_gettext('auth.persistent_login_interval', 'How long a persistent login lasts.  E.g. ''2 weeks''', 'coust', 'description'),
+    'interval'
+);
+
+INSERT INTO config.org_unit_setting_type ( name, label, description, datatype ) VALUES (
+        'cat.marc_control_number_identifier',
+        oils_i18n_gettext(
+            'cat.marc_control_number_identifier', 
+            'Cat: Defines the control number identifier used in 003 and 035 fields.', 
+            'coust', 
+            'label'),
+        oils_i18n_gettext(
+            'cat.marc_control_number_identifier', 
+            'Cat: Defines the control number identifier used in 003 and 035 fields.', 
+            'coust', 
+            'description'),
+        'string'
+);
+
+INSERT INTO config.org_unit_setting_type (name, label, description, datatype) 
+    VALUES (
+        'circ.selfcheck.block_checkout_on_copy_status',
+        oils_i18n_gettext(
+            'circ.selfcheck.block_checkout_on_copy_status',
+            'Selfcheck: Block copy checkout status',
+            'coust',
+            'label'
+        ),
+        oils_i18n_gettext(
+            'circ.selfcheck.block_checkout_on_copy_status',
+            'List of copy status IDs that will block checkout even if the generic COPY_NOT_AVAILABLE event is overridden',
+            'coust',
+            'description'
+        ),
+        'array'
+    );
+
+INSERT INTO config.org_unit_setting_type ( name, label, description, datatype, fm_class )
+VALUES (
+    'serial.prev_issuance_copy_location',
+    oils_i18n_gettext(
+        'serial.prev_issuance_copy_location',
+        'Serials: Previous Issuance Copy Location',
+        'coust',
+        'label'
+    ),
+    oils_i18n_gettext(
+        'serial.prev_issuance_copy_location',
+        'When a serial issuance is received, copies (units) of the previous issuance will be automatically moved into the configured shelving location',
+        'coust',
+        'descripton'
+        ),
+    'link',
+    'acpl'
+);
+
+INSERT INTO config.org_unit_setting_type ( name, label, description, datatype, fm_class )
+VALUES (
+    'cat.default_classification_scheme',
+    oils_i18n_gettext(
+        'cat.default_classification_scheme',
+        'Cataloging: Default Classification Scheme',
+        'coust',
+        'label'
+    ),
+    oils_i18n_gettext(
+        'cat.default_classification_scheme',
+        'Defines the default classification scheme for new call numbers: 1 = Generic; 2 = Dewey; 3 = LC',
+        'coust',
+        'descripton'
+        ),
+    'link',
+    'acnc'
+);
+
+INSERT INTO config.org_unit_setting_type ( name, label, description, datatype ) VALUES (
+        'opac.org_unit_hiding.depth',
+        oils_i18n_gettext(
+            'opac.org_unit_hiding.depth',
+            'OPAC: Org Unit Hiding Depth', 
+            'coust', 
+            'label'),
+        oils_i18n_gettext(
+            'opac.org_unit_hiding.depth',
+            'This will hide certain org units in the public OPAC if the Original Location (url param "ol") for the OPAC inherits this setting.  This setting specifies an org unit depth, that together with the OPAC Original Location determines which section of the Org Hierarchy should be visible in the OPAC.  For example, a stock Evergreen installation will have a 3-tier hierarchy (Consortium/System/Branch), where System has a depth of 1 and Branch has a depth of 2.  If this setting contains a depth of 1 in such an installation, then every library in the System in which the Original Location belongs will be visible, and everything else will be hidden.  A depth of 0 will effectively make every org visible.  The embedded OPAC in the staff client ignores this setting.', 
+            'coust', 
+            'description'),
+        'integer'
+);
+
+INSERT INTO config.org_unit_setting_type (name, label, description, datatype)
+    VALUES 
+        ('circ.holds.alert_if_local_avail',
+         'Holds: Local available alert',
+         'If local copy is available, alert the person making the hold',
+         'bool'),
+
+        ('circ.holds.deny_if_local_avail',
+         'Holds: Local available block',
+         'If local copy is available, deny the creation of the hold',
+         'bool')
+    ;
+
+INSERT INTO config.org_unit_setting_type ( name, label, description, datatype )
+    VALUES ( 
+        'circ.holds.clear_shelf.no_capture_holds',
+        oils_i18n_gettext('circ.holds.clear_shelf.no_capture_holds', 'Holds: Bypass hold capture during clear shelf process', 'coust', 'label'),
+        oils_i18n_gettext('circ.holds.clear_shelf.no_capture_holds', 'During the clear shelf process, avoid capturing new holds on cleared items.', 'coust', 'description'),
+        'bool'
+    );
+
+INSERT INTO config.org_unit_setting_type (name, label, description, datatype) VALUES (
+    'circ.booking_reservation.stop_circ',
+    'Disallow circulation of items when they are on booking reserve and that reserve overlaps with the checkout period',
+    'When true, items on booking reserve during the proposed checkout period will not be allowed to circulate unless overridden with the COPY_RESERVED.override permission.',
+    'bool'
+);
+
+---------------------------------
+-- Seed data for usr_setting_type
+----------------------------------
+
+INSERT INTO config.usr_setting_type (name,opac_visible,label,description,datatype)
+    VALUES ('opac.default_font', TRUE, 'OPAC Font Size', 'OPAC Font Size', 'string');
+
+INSERT INTO config.usr_setting_type (name,opac_visible,label,description,datatype)
+    VALUES ('opac.default_search_depth', TRUE, 'OPAC Search Depth', 'OPAC Search Depth', 'integer');
+
+INSERT INTO config.usr_setting_type (name,opac_visible,label,description,datatype)
+    VALUES ('opac.default_search_location', TRUE, 'OPAC Search Location', 'OPAC Search Location', 'integer');
+
+INSERT INTO config.usr_setting_type (name,opac_visible,label,description,datatype)
+    VALUES ('opac.hits_per_page', TRUE, 'Hits per Page', 'Hits per Page', 'string');
+
+INSERT INTO config.usr_setting_type (name,opac_visible,label,description,datatype)
+    VALUES ('opac.hold_notify', TRUE, 'Hold Notification Format', 'Hold Notification Format', 'string');
+
+INSERT INTO config.usr_setting_type (name,opac_visible,label,description,datatype)
+    VALUES ('staff_client.catalog.record_view.default', TRUE, 'Default Record View', 'Default Record View', 'string');
+
+INSERT INTO config.usr_setting_type (name,opac_visible,label,description,datatype)
+    VALUES ('staff_client.copy_editor.templates', TRUE, 'Copy Editor Template', 'Copy Editor Template', 'object');
+
+INSERT INTO config.usr_setting_type (name,opac_visible,label,description,datatype)
+    VALUES ('circ.holds_behind_desk', FALSE, 'Hold is behind Circ Desk', 'Hold is behind Circ Desk', 'bool');
+
+INSERT INTO config.usr_setting_type (name,opac_visible,label,description,datatype)
+    VALUES (
+        'history.circ.retention_age',
+        TRUE,
+        oils_i18n_gettext('history.circ.retention_age','Historical Circulation Retention Age','cust','label'),
+        oils_i18n_gettext('history.circ.retention_age','Historical Circulation Retention Age','cust','description'),
+        'interval'
+    ),(
+        'history.circ.retention_start',
+        FALSE,
+        oils_i18n_gettext('history.circ.retention_start','Historical Circulation Retention Start Date','cust','label'),
+        oils_i18n_gettext('history.circ.retention_start','Historical Circulation Retention Start Date','cust','description'),
+        'date'
+    );
+
+INSERT INTO config.usr_setting_type (name,opac_visible,label,description,datatype)
+    VALUES (
+        'history.hold.retention_age',
+        TRUE,
+        oils_i18n_gettext('history.hold.retention_age','Historical Hold Retention Age','cust','label'),
+        oils_i18n_gettext('history.hold.retention_age','Historical Hold Retention Age','cust','description'),
+        'interval'
+    ),(
+        'history.hold.retention_start',
+        TRUE,
+        oils_i18n_gettext('history.hold.retention_start','Historical Hold Retention Start Date','cust','label'),
+        oils_i18n_gettext('history.hold.retention_start','Historical Hold Retention Start Date','cust','description'),
+        'interval'
+    ),(
+        'history.hold.retention_count',
+        TRUE,
+        oils_i18n_gettext('history.hold.retention_count','Historical Hold Retention Count','cust','label'),
+        oils_i18n_gettext('history.hold.retention_count','Historical Hold Retention Count','cust','description'),
+        'integer'
+    );
+
+INSERT INTO config.usr_setting_type (name, opac_visible, label, description, datatype)
+    VALUES (
+        'opac.default_sort',
+        TRUE,
+        oils_i18n_gettext(
+            'opac.default_sort',
+            'OPAC Default Search Sort',
+            'cust',
+            'label'
+        ),
+        oils_i18n_gettext(
+            'opac.default_sort',
+            'OPAC Default Search Sort',
+            'cust',
+            'description'
+        ),
+        'string'
+    );
+
+INSERT INTO config.org_unit_setting_type ( name, label, description, datatype, fm_class ) VALUES (
+        'circ.missing_pieces.copy_status',
+        oils_i18n_gettext(
+            'circ.missing_pieces.copy_status',
+            'Circulation: Item Status for Missing Pieces',
+            'coust',
+            'label'),
+        oils_i18n_gettext(
+            'circ.missing_pieces.copy_status',
+            'This is the Item Status to use for items that have been marked or scanned as having Missing Pieces.  In the absence of this setting, the Damaged status is used.',
+            'coust',
+            'description'),
+        'link',
+        'ccs'
+);
+
+INSERT INTO config.org_unit_setting_type ( name, label, description, datatype ) VALUES (
+        'circ.do_not_tally_claims_returned',
+        oils_i18n_gettext(
+            'circ.do_not_tally_claims_returned',
+            'Circulation: Do not include outstanding Claims Returned circulations in lump sum tallies in Patron Display.',
+            'coust',
+            'label'),
+        oils_i18n_gettext(
+            'circ.do_not_tally_claims_returned',
+            'In the Patron Display interface, the number of total active circulations for a given patron is presented in the Summary sidebar and underneath the Items Out navigation button.  This setting will prevent Claims Returned circulations from counting toward these tallies.',
+            'coust',
+            'description'),
+        'bool'
+);
+
+INSERT INTO config.org_unit_setting_type (name, label, description, datatype)
+    VALUES
+        ('cat.label.font.size',
+            oils_i18n_gettext('cat.label.font.size',
+                'Cataloging: Spine and pocket label font size', 'coust', 'label'),
+            oils_i18n_gettext('cat.label.font.size',
+                'Set the default font size for spine and pocket labels', 'coust', 'description'),
+            'integer'
+        )
+        ,('cat.label.font.family',
+            oils_i18n_gettext('cat.label.font.family',
+                'Cataloging: Spine and pocket label font family', 'coust', 'label'),
+            oils_i18n_gettext('cat.label.font.family',
+                'Set the preferred font family for spine and pocket labels. You can specify a list of fonts, separated by commas, in order of preference; the system will use the first font it finds with a matching name. For example, "Arial, Helvetica, serif".',
+                'coust', 'description'),
+            'string'
+        )
+        ,('cat.spine.line.width',
+            oils_i18n_gettext('cat.spine.line.width',
+                'Cataloging: Spine label line width', 'coust', 'label'),
+            oils_i18n_gettext('cat.spine.line.width',
+                'Set the default line width for spine labels in number of characters. This specifies the boundary at which lines must be wrapped.',
+                'coust', 'description'),
+            'integer'
+        )
+        ,('cat.spine.line.height',
+            oils_i18n_gettext('cat.spine.line.height',
+                'Cataloging: Spine label maximum lines', 'coust', 'label'),
+            oils_i18n_gettext('cat.spine.line.height',
+                'Set the default maximum number of lines for spine labels.',
+                'coust', 'description'),
+            'integer'
+        )
+        ,('cat.spine.line.margin',
+            oils_i18n_gettext('cat.spine.line.margin',
+                'Cataloging: Spine label left margin', 'coust', 'label'),
+            oils_i18n_gettext('cat.spine.line.margin',
+                'Set the left margin for spine labels in number of characters.',
+                'coust', 'description'),
+            'integer'
+        )
+;
+
+INSERT INTO config.org_unit_setting_type (name, label, description, datatype)
+    VALUES
+        ('cat.label.font.weight',
+            oils_i18n_gettext('cat.label.font.weight',
+                'Cataloging: Spine and pocket label font weight', 'coust', 'label'),
+            oils_i18n_gettext('cat.label.font.weight',
+                'Set the preferred font weight for spine and pocket labels. You can specify "normal", "bold", "bolder", or "lighter".',
+                'coust', 'description'),
+            'string'
+        )
+;
+
+INSERT INTO config.org_unit_setting_type ( name, label, description, datatype ) VALUES (
+        'circ.patron_edit.clone.copy_address',
+        oils_i18n_gettext(
+            'circ.patron_edit.clone.copy_address',
+            'Patron Registration: Cloned patrons get address copy',
+            'coust',
+            'label'
+        ),
+        oils_i18n_gettext(
+            'circ.patron_edit.clone.copy_address',
+            'In the Patron editor, copy addresses from the cloned user instead of linking directly to the address',
+            'coust',
+            'description'
+        ),
+        'bool'
+);
+
+INSERT INTO config.org_unit_setting_type ( name, label, description, datatype, fm_class ) VALUES (
+        'ui.patron.default_ident_type',
+        oils_i18n_gettext(
+            'ui.patron.default_ident_type',
+            'GUI: Default Ident Type for Patron Registration',
+            'coust',
+            'label'),
+        oils_i18n_gettext(
+            'ui.patron.default_ident_type',
+            'This is the default Ident Type for new users in the patron editor.',
+            'coust',
+            'description'),
+        'link',
+        'cit'
+);
+
+INSERT INTO config.org_unit_setting_type ( name, label, description, datatype ) VALUES (
+        'ui.patron.default_country',
+        oils_i18n_gettext(
+            'ui.patron.default_country',
+            'GUI: Default Country for New Addresses in Patron Editor',
+            'coust',
+            'label'),
+        oils_i18n_gettext(
+            'ui.patron.default_country',
+            'This is the default Country for new addresses in the patron editor.',
+            'coust',
+            'description'),
+        'string'
+);
+
+INSERT INTO config.org_unit_setting_type ( name, label, description, datatype ) VALUES (
+        'ui.patron.registration.require_address',
+        oils_i18n_gettext(
+            'ui.patron.registration.require_address',
+            'GUI: Require at least one address for Patron Registration',
+            'coust',
+            'label'),
+        oils_i18n_gettext(
+            'ui.patron.registration.require_address',
+            'Enforces a requirement for having at least one address for a patron during registration.',
+            'coust',
+            'description'),
+        'bool'
+);
+
+INSERT INTO config.org_unit_setting_type (
+    name, label, description, datatype
+) VALUES
+    ('credit.processor.payflowpro.enabled',
+        'Credit card processing: Enable PayflowPro payments',
+        'This is NOT the same thing as the settings labeled with just "PayPal."',
+        'bool'
+    ),
+    ('credit.processor.payflowpro.login',
+        'Credit card processing: PayflowPro login/merchant ID',
+        'Often the same thing as the PayPal manager login',
+        'string'
+    ),
+    ('credit.processor.payflowpro.password',
+        'Credit card processing: PayflowPro password',
+        'PayflowPro password',
+        'string'
+    ),
+    ('credit.processor.payflowpro.testmode',
+        'Credit card processing: PayflowPro test mode',
+        'Do not really process transactions, but stay in test mode - uses pilot-payflowpro.paypal.com instead of the usual host',
+        'bool'
+    ),
+    ('credit.processor.payflowpro.vendor',
+        'Credit card processing: PayflowPro vendor',
+        'Often the same thing as the login',
+        'string'
+    ),
+    ('credit.processor.payflowpro.partner',
+        'Credit card processing: PayflowPro partner',
+        'Often "PayPal" or "VeriSign", sometimes others',
+        'string'
+    );
+
+-- Patch the name of an old selfcheck setting
+UPDATE actor.org_unit_setting
+    SET name = 'circ.selfcheck.alert.popup'
+    WHERE name = 'circ.selfcheck.alert_on_checkout_event';
+
+-- Rename certain existing org_unit settings, if present,
+-- and make sure their values are JSON
+UPDATE actor.org_unit_setting SET
+    name = 'circ.holds.default_estimated_wait_interval',
+    --
+    -- The value column should be JSON.  The old value should be a number,
+    -- but it may or may not be quoted.  The following CASE behaves
+    -- differently depending on whether value is quoted.  It is simplistic,
+    -- and will be defeated by leading or trailing white space, or various
+    -- malformations.
+    --
+    value = CASE WHEN SUBSTR( value, 1, 1 ) = '"'
+                THEN '"' || SUBSTR( value, 2, LENGTH(value) - 2 ) || ' days"'
+                ELSE '"' || value || ' days"'
+            END
+WHERE name = 'circ.hold_estimate_wait_interval';
+
+-- Create types for existing org unit settings
+-- not otherwise accounted for
+
+INSERT INTO config.org_unit_setting_type(
+ name,
+ label,
+ description
+)
+SELECT DISTINCT
+	name,
+	name,
+	'FIXME'
+FROM
+	actor.org_unit_setting
+WHERE
+	name NOT IN (
+		SELECT name
+		FROM config.org_unit_setting_type
+	);
+
+-- Add foreign key to org_unit_setting
+
+ALTER TABLE actor.org_unit_setting
+	ADD FOREIGN KEY (name) REFERENCES config.org_unit_setting_type (name)
+		DEFERRABLE INITIALLY DEFERRED;
+
+-- Create types for existing user settings
+-- not otherwise accounted for
+
+INSERT INTO config.usr_setting_type (
+	name,
+	label,
+	description
+)
+SELECT DISTINCT
+	name,
+	name,
+	'FIXME'
+FROM
+	actor.usr_setting
+WHERE
+	name NOT IN (
+		SELECT name
+		FROM config.usr_setting_type
+	);
+
+-- Add foreign key to user_setting_type
+
+ALTER TABLE actor.usr_setting
+	ADD FOREIGN KEY (name) REFERENCES config.usr_setting_type (name)
+		ON DELETE CASCADE ON UPDATE CASCADE
+		DEFERRABLE INITIALLY DEFERRED;
+
+INSERT INTO actor.org_unit_setting (org_unit, name, value) VALUES
+    (1, 'cat.spine.line.margin', 0)
+    ,(1, 'cat.spine.line.height', 9)
+    ,(1, 'cat.spine.line.width', 8)
+    ,(1, 'cat.label.font.family', '"monospace"')
+    ,(1, 'cat.label.font.size', 10)
+    ,(1, 'cat.label.font.weight', '"normal"')
+;
+
+ALTER TABLE action_trigger.event_definition ADD COLUMN granularity TEXT;
+ALTER TABLE action_trigger.event ADD COLUMN async_output BIGINT REFERENCES action_trigger.event_output (id);
+ALTER TABLE action_trigger.event_definition ADD COLUMN usr_field TEXT;
+ALTER TABLE action_trigger.event_definition ADD COLUMN opt_in_setting TEXT REFERENCES config.usr_setting_type (name) DEFERRABLE INITIALLY DEFERRED;
+
+CREATE OR REPLACE FUNCTION is_json( TEXT ) RETURNS BOOL AS $f$
+    use JSON::XS;
+    my $json = shift();
+    eval { JSON::XS->new->allow_nonref->decode( $json ) };
+    return $@ ? 0 : 1;
+$f$ LANGUAGE PLPERLU;
+
+ALTER TABLE action_trigger.event ADD COLUMN user_data TEXT CHECK (user_data IS NULL OR is_json( user_data ));
+
+INSERT INTO action_trigger.hook (key,core_type,description) VALUES (
+    'hold_request.cancel.expire_no_target',
+    'ahr',
+    'A hold is cancelled because no copies were found'
+);
+
+INSERT INTO action_trigger.hook (key,core_type,description) VALUES (
+    'hold_request.cancel.expire_holds_shelf',
+    'ahr',
+    'A hold is cancelled because it was on the holds shelf too long'
+);
+
+INSERT INTO action_trigger.hook (key,core_type,description) VALUES (
+    'hold_request.cancel.staff',
+    'ahr',
+    'A hold is cancelled because it was cancelled by staff'
+);
+
+INSERT INTO action_trigger.hook (key,core_type,description) VALUES (
+    'hold_request.cancel.patron',
+    'ahr',
+    'A hold is cancelled by the patron'
+);
+
+-- Fix typos in descriptions
+UPDATE action_trigger.hook SET description = 'A hold is successfully placed' WHERE key = 'hold_request.success';
+UPDATE action_trigger.hook SET description = 'A hold is attempted but not successfully placed' WHERE key = 'hold_request.failure';
+
+-- Add a hook for renewals
+INSERT INTO action_trigger.hook (key,core_type,description) VALUES ('renewal','circ','Item renewed to user');
+
+INSERT INTO action_trigger.validator (module,description) VALUES ('MaxPassiveDelayAge','Check that the event is not too far past the delay_field time -- requires a max_delay_age interval parameter');
+
+-- Sample Pre-due Notice --
+
+INSERT INTO action_trigger.event_definition (id, active, owner, name, hook, validator, reactor, delay, delay_field, group_field, template) 
+    VALUES (6, 'f', 1, '3 Day Courtesy Notice', 'checkout.due', 'CircIsOpen', 'SendEmail', '-3 days', 'due_date', 'usr', 
+$$
+[%- USE date -%]
+[%- user = target.0.usr -%]
+To: [%- params.recipient_email || user.email %]
+From: [%- params.sender_email || default_sender %]
+Subject: Courtesy Notice
+
+Dear [% user.family_name %], [% user.first_given_name %]
+As a reminder, the following items are due in 3 days.
+
+[% FOR circ IN target %]
+    Title: [% circ.target_copy.call_number.record.simple_record.title %] 
+    Barcode: [% circ.target_copy.barcode %] 
+    Due: [% date.format(helpers.format_date(circ.due_date), '%Y-%m-%d') %]
+    Item Cost: [% helpers.get_copy_price(circ.target_copy) %]
+    Library: [% circ.circ_lib.name %]
+    Library Phone: [% circ.circ_lib.phone %]
+[% END %]
+
+$$);
+
+INSERT INTO action_trigger.environment (event_def, path) VALUES 
+    (6, 'target_copy.call_number.record.simple_record'),
+    (6, 'usr'),
+    (6, 'circ_lib.billing_address');
+
+INSERT INTO action_trigger.event_params (event_def, param, value) VALUES
+    (6, 'max_delay_age', '"1 day"');
+
+-- also add the max delay age to the default overdue notice event def
+INSERT INTO action_trigger.event_params (event_def, param, value) VALUES
+    (1, 'max_delay_age', '"1 day"');
+  
+INSERT INTO action_trigger.validator (module,description) VALUES ('MinPassiveTargetAge','Check that the target is old enough to be used by this event -- requires a min_target_age interval parameter, and accepts an optional target_age_field to specify what time to use for offsetting');
+
+INSERT INTO action_trigger.reactor (module,description) VALUES ('ApplyPatronPenalty','Applies the configured penalty to a patron.  Required named environment variables are "user", which refers to the user object, and "context_org", which refers to the org_unit object that acts as the focus for the penalty.');
+
+INSERT INTO action_trigger.hook (
+        key,
+        core_type,
+        description,
+        passive
+    ) VALUES (
+        'hold_request.shelf_expires_soon',
+        'ahr',
+        'A hold on the shelf will expire there soon.',
+        TRUE
+    );
+
+INSERT INTO action_trigger.event_definition (
+        id,
+        active,
+        owner,
+        name,
+        hook,
+        validator,
+        reactor,
+        delay,
+        delay_field,
+        group_field,
+        template
+    ) VALUES (
+        7,
+        FALSE,
+        1,
+        'Hold Expires from Shelf Soon',
+        'hold_request.shelf_expires_soon',
+        'HoldIsAvailable',
+        'SendEmail',
+        '- 1 DAY',
+        'shelf_expire_time',
+        'usr',
+$$
+[%- USE date -%]
+[%- user = target.0.usr -%]
+To: [%- params.recipient_email || user.email %]
+From: [%- params.sender_email || default_sender %]
+Subject: Hold Available Notification
+
+Dear [% user.family_name %], [% user.first_given_name %]
+You requested holds on the following item(s), which are available for
+pickup, but these holds will soon expire.
+
+[% FOR hold IN target %]
+    [%- data = helpers.get_copy_bib_basics(hold.current_copy.id) -%]
+    Title: [% data.title %]
+    Author: [% data.author %]
+    Library: [% hold.pickup_lib.name %]
+[% END %]
+$$
+    );
+
+INSERT INTO action_trigger.environment (
+        event_def,
+        path
+    ) VALUES
+    ( 7, 'current_copy'),
+    ( 7, 'pickup_lib.billing_address'),
+    ( 7, 'usr');
+
+INSERT INTO action_trigger.hook (
+        key,
+        core_type,
+        description,
+        passive
+    ) VALUES (
+        'hold_request.long_wait',
+        'ahr',
+        'A patron has been waiting on a hold to be fulfilled for a long time.',
+        TRUE
+    );
+
+INSERT INTO action_trigger.event_definition (
+        id,
+        active,
+        owner,
+        name,
+        hook,
+        validator,
+        reactor,
+        delay,
+        delay_field,
+        group_field,
+        template
+    ) VALUES (
+        9,
+        FALSE,
+        1,
+        'Hold waiting for pickup for long time',
+        'hold_request.long_wait',
+        'NOOP_True',
+        'SendEmail',
+        '6 MONTHS',
+        'request_time',
+        'usr',
+$$
+[%- USE date -%]
+[%- user = target.0.usr -%]
+To: [%- params.recipient_email || user.email %]
+From: [%- params.sender_email || default_sender %]
+Subject: Long Wait Hold Notification
+
+Dear [% user.family_name %], [% user.first_given_name %]
+
+You requested hold(s) on the following item(s), but unfortunately
+we have not been able to fulfill your request after a considerable
+length of time.  If you would still like to receive these items,
+no action is required.
+
+[% FOR hold IN target %]
+    Title: [% hold.bib_rec.bib_record.simple_record.title %]
+    Author: [% hold.bib_rec.bib_record.simple_record.author %]
+[% END %]
+$$
+);
+
+INSERT INTO action_trigger.environment (
+        event_def,
+        path
+    ) VALUES
+    (9, 'pickup_lib'),
+    (9, 'usr'),
+    (9, 'bib_rec.bib_record.simple_record');
+
+INSERT INTO action_trigger.hook (key, core_type, description, passive) 
+    VALUES (
+        'format.selfcheck.checkout',
+        'circ',
+        'Formats circ objects for self-checkout receipt',
+        TRUE
+    );
+
+INSERT INTO action_trigger.event_definition (id, active, owner, name, hook, validator, reactor, group_field, granularity, template )
+    VALUES (
+        10,
+        TRUE,
+        1,
+        'Self-Checkout Receipt',
+        'format.selfcheck.checkout',
+        'NOOP_True',
+        'ProcessTemplate',
+        'usr',
+        'print-on-demand',
+$$
+[%- USE date -%]
+[%- SET user = target.0.usr -%]
+[%- SET lib = target.0.circ_lib -%]
+[%- SET lib_addr = target.0.circ_lib.billing_address -%]
+[%- SET hours = lib.hours_of_operation -%]
+<div>
+    <style> li { padding: 8px; margin 5px; }</style>
+    <div>[% date.format %]</div>
+    <div>[% lib.name %]</div>
+    <div>[% lib_addr.street1 %] [% lib_addr.street2 %]</div>
+    <div>[% lib_addr.city %], [% lib_addr.state %] [% lb_addr.post_code %]</div>
+    <div>[% lib.phone %]</div>
+    <br/>
+
+    [% user.family_name %], [% user.first_given_name %]
+    <ol>
+    [% FOR circ IN target %]
+        [%-
+            SET idx = loop.count - 1;
+            SET udata =  user_data.$idx
+        -%]
+        <li>
+            <div>[% helpers.get_copy_bib_basics(circ.target_copy.id).title %]</div>
+            <div>Barcode: [% circ.target_copy.barcode %]</div>
+            [% IF udata.renewal_failure %]
+                <div style='color:red;'>Renewal Failed</div>
+            [% ELSE %]
+                <div>Due Date: [% date.format(helpers.format_date(circ.due_date), '%Y-%m-%d') %]</div>
+            [% END %]
+        </li>
+    [% END %]
+    </ol>
+    
+    <div>
+        Library Hours
+        [%- BLOCK format_time; date.format(time _ ' 1/1/1000', format='%I:%M %p'); END -%]
+        <div>
+            Monday 
+            [% PROCESS format_time time = hours.dow_0_open %] 
+            [% PROCESS format_time time = hours.dow_0_close %] 
+        </div>
+        <div>
+            Tuesday 
+            [% PROCESS format_time time = hours.dow_1_open %] 
+            [% PROCESS format_time time = hours.dow_1_close %] 
+        </div>
+        <div>
+            Wednesday 
+            [% PROCESS format_time time = hours.dow_2_open %] 
+            [% PROCESS format_time time = hours.dow_2_close %] 
+        </div>
+        <div>
+            Thursday
+            [% PROCESS format_time time = hours.dow_3_open %] 
+            [% PROCESS format_time time = hours.dow_3_close %] 
+        </div>
+        <div>
+            Friday
+            [% PROCESS format_time time = hours.dow_4_open %] 
+            [% PROCESS format_time time = hours.dow_4_close %] 
+        </div>
+        <div>
+            Saturday
+            [% PROCESS format_time time = hours.dow_5_open %] 
+            [% PROCESS format_time time = hours.dow_5_close %] 
+        </div>
+        <div>
+            Sunday 
+            [% PROCESS format_time time = hours.dow_6_open %] 
+            [% PROCESS format_time time = hours.dow_6_close %] 
+        </div>
+    </div>
+</div>
+$$
+);
+
+INSERT INTO action_trigger.environment ( event_def, path) VALUES
+    ( 10, 'target_copy'),
+    ( 10, 'circ_lib.billing_address'),
+    ( 10, 'circ_lib.hours_of_operation'),
+    ( 10, 'usr');
+
+INSERT INTO action_trigger.hook (key, core_type, description, passive) 
+    VALUES (
+        'format.selfcheck.items_out',
+        'circ',
+        'Formats items out for self-checkout receipt',
+        TRUE
+    );
+
+INSERT INTO action_trigger.event_definition (id, active, owner, name, hook, validator, reactor, group_field, granularity, template )
+    VALUES (
+        11,
+        TRUE,
+        1,
+        'Self-Checkout Items Out Receipt',
+        'format.selfcheck.items_out',
+        'NOOP_True',
+        'ProcessTemplate',
+        'usr',
+        'print-on-demand',
+$$
+[%- USE date -%]
+[%- SET user = target.0.usr -%]
+<div>
+    <style> li { padding: 8px; margin 5px; }</style>
+    <div>[% date.format %]</div>
+    <br/>
+
+    [% user.family_name %], [% user.first_given_name %]
+    <ol>
+    [% FOR circ IN target %]
+        <li>
+            <div>[% helpers.get_copy_bib_basics(circ.target_copy.id).title %]</div>
+            <div>Barcode: [% circ.target_copy.barcode %]</div>
+            <div>Due Date: [% date.format(helpers.format_date(circ.due_date), '%Y-%m-%d') %]</div>
+        </li>
+    [% END %]
+    </ol>
+</div>
+$$
+);
+
+
+INSERT INTO action_trigger.environment ( event_def, path) VALUES
+    ( 11, 'target_copy'),
+    ( 11, 'circ_lib.billing_address'),
+    ( 11, 'circ_lib.hours_of_operation'),
+    ( 11, 'usr');
+
+INSERT INTO action_trigger.hook (key, core_type, description, passive) 
+    VALUES (
+        'format.selfcheck.holds',
+        'ahr',
+        'Formats holds for self-checkout receipt',
+        TRUE
+    );
+
+INSERT INTO action_trigger.event_definition (id, active, owner, name, hook, validator, reactor, group_field, granularity, template )
+    VALUES (
+        12,
+        TRUE,
+        1,
+        'Self-Checkout Holds Receipt',
+        'format.selfcheck.holds',
+        'NOOP_True',
+        'ProcessTemplate',
+        'usr',
+        'print-on-demand',
+$$
+[%- USE date -%]
+[%- SET user = target.0.usr -%]
+<div>
+    <style> li { padding: 8px; margin 5px; }</style>
+    <div>[% date.format %]</div>
+    <br/>
+
+    [% user.family_name %], [% user.first_given_name %]
+    <ol>
+    [% FOR hold IN target %]
+        [%-
+            SET idx = loop.count - 1;
+            SET udata =  user_data.$idx
+        -%]
+        <li>
+            <div>Title: [% hold.bib_rec.bib_record.simple_record.title %]</div>
+            <div>Author: [% hold.bib_rec.bib_record.simple_record.author %]</div>
+            <div>Pickup Location: [% hold.pickup_lib.name %]</div>
+            <div>Status: 
+                [%- IF udata.ready -%]
+                    Ready for pickup
+                [% ELSE %]
+                    #[% udata.queue_position %] of [% udata.potential_copies %] copies.
+                [% END %]
+            </div>
+        </li>
+    [% END %]
+    </ol>
+</div>
+$$
+);
+
+
+INSERT INTO action_trigger.environment ( event_def, path) VALUES
+    ( 12, 'bib_rec.bib_record.simple_record'),
+    ( 12, 'pickup_lib'),
+    ( 12, 'usr');
+
+INSERT INTO action_trigger.hook (key, core_type, description, passive) 
+    VALUES (
+        'format.selfcheck.fines',
+        'au',
+        'Formats fines for self-checkout receipt',
+        TRUE
+    );
+
+INSERT INTO action_trigger.event_definition (id, active, owner, name, hook, validator, reactor, granularity, template )
+    VALUES (
+        13,
+        TRUE,
+        1,
+        'Self-Checkout Fines Receipt',
+        'format.selfcheck.fines',
+        'NOOP_True',
+        'ProcessTemplate',
+        'print-on-demand',
+$$
+[%- USE date -%]
+[%- SET user = target -%]
+<div>
+    <style> li { padding: 8px; margin 5px; }</style>
+    <div>[% date.format %]</div>
+    <br/>
+
+    [% user.family_name %], [% user.first_given_name %]
+    <ol>
+    [% FOR xact IN user.open_billable_transactions_summary %]
+        <li>
+            <div>Details: 
+                [% IF xact.xact_type == 'circulation' %]
+                    [%- helpers.get_copy_bib_basics(xact.circulation.target_copy).title -%]
+                [% ELSE %]
+                    [%- xact.last_billing_type -%]
+                [% END %]
+            </div>
+            <div>Total Billed: [% xact.total_owed %]</div>
+            <div>Total Paid: [% xact.total_paid %]</div>
+            <div>Balance Owed : [% xact.balance_owed %]</div>
+        </li>
+    [% END %]
+    </ol>
+</div>
+$$
+);
+
+INSERT INTO action_trigger.environment ( event_def, path) VALUES
+    ( 13, 'open_billable_transactions_summary.circulation' );
+
+INSERT INTO action_trigger.reactor (module,description) VALUES
+(   'SendFile',
+    oils_i18n_gettext(
+        'SendFile',
+        'Build and transfer a file to a remote server.  Required parameter "remote_host" specifying target server.  Optional parameters: remote_user, remote_password, remote_account, port, type (FTP, SFTP or SCP), and debug.',
+        'atreact',
+        'description'
+    )
+);
+
+INSERT INTO action_trigger.hook (key, core_type, description, passive) 
+    VALUES (
+        'format.acqli.html',
+        'jub',
+        'Formats lineitem worksheet for titles received',
+        TRUE
+    );
+
+INSERT INTO action_trigger.event_definition (id, active, owner, name, hook, validator, reactor, granularity, template)
+    VALUES (
+        14,
+        TRUE,
+        1,
+        'Lineitem Worksheet',
+        'format.acqli.html',
+        'NOOP_True',
+        'ProcessTemplate',
+        'print-on-demand',
+$$
+[%- USE date -%]
+[%- SET li = target; -%]
+<div class="wrapper">
+    <div class="summary" style='font-size:110%; font-weight:bold;'>
+
+        <div>Title: [% helpers.get_li_attr("title", "", li.attributes) %]</div>
+        <div>Author: [% helpers.get_li_attr("author", "", li.attributes) %]</div>
+        <div class="count">Item Count: [% li.lineitem_details.size %]</div>
+        <div class="lineid">Lineitem ID: [% li.id %]</div>
+
+        [% IF li.distribution_formulas.size > 0 %]
+            [% SET forms = [] %]
+            [% FOREACH form IN li.distribution_formulas; forms.push(form.formula.name); END %]
+            <div>Distribution Formulas: [% forms.join(',') %]</div>
+        [% END %]
+
+        [% IF li.lineitem_notes.size > 0 %]
+            Lineitem Notes:
+            <ul>
+                [%- FOR note IN li.lineitem_notes -%]
+                    <li>
+                    [% IF note.alert_text %]
+                        [% note.alert_text.code -%] 
+                        [% IF note.value -%]
+                            : [% note.value %]
+                        [% END %]
+                    [% ELSE %]
+                        [% note.value -%] 
+                    [% END %]
+                    </li>
+                [% END %]
+            </ul>
+        [% END %]
+    </div>
+    <br/>
+    <table>
+        <thead>
+            <tr>
+                <th>Branch</th>
+                <th>Barcode</th>
+                <th>Call Number</th>
+                <th>Fund</th>
+                <th>Recd.</th>
+                <th>Notes</th>
+            </tr>
+        </thead>
+        <tbody>
+        [% FOREACH detail IN li.lineitem_details.sort('owning_lib') %]
+            [% 
+                IF copy.eg_copy_id;
+                    SET copy = copy.eg_copy_id;
+                    SET cn_label = copy.call_number.label;
+                ELSE; 
+                    SET copy = detail; 
+                    SET cn_label = detail.cn_label;
+                END 
+            %]
+            <tr>
+                <!-- acq.lineitem_detail.id = [%- detail.id -%] -->
+                <td style='padding:5px;'>[% detail.owning_lib.shortname %]</td>
+                <td style='padding:5px;'>[% IF copy.barcode   %]<span class="barcode"  >[% detail.barcode   %]</span>[% END %]</td>
+                <td style='padding:5px;'>[% IF cn_label %]<span class="cn_label" >[% cn_label  %]</span>[% END %]</td>
+                <td style='padding:5px;'>[% IF detail.fund %]<span class="fund">[% detail.fund.code %] ([% detail.fund.year %])</span>[% END %]</td>
+                <td style='padding:5px;'>[% IF detail.recv_time %]<span class="recv_time">[% detail.recv_time %]</span>[% END %]</td>
+                <td style='padding:5px;'>[% detail.note %]</td>
+            </tr>
+        [% END %]
+        </tbody>
+    </table>
+</div>
+$$
+);
+
+
+INSERT INTO action_trigger.environment (event_def, path) VALUES
+    ( 14, 'attributes' ),
+    ( 14, 'lineitem_details' ),
+    ( 14, 'lineitem_details.owning_lib' ),
+    ( 14, 'lineitem_notes' )
+;
+
+INSERT INTO action_trigger.hook (key,core_type,description,passive) VALUES (
+        'aur.ordered',
+        'aur', 
+        oils_i18n_gettext(
+            'aur.ordered',
+            'A patron acquisition request has been marked On-Order.',
+            'ath',
+            'description'
+        ), 
+        TRUE
+    ), (
+        'aur.received', 
+        'aur', 
+        oils_i18n_gettext(
+            'aur.received', 
+            'A patron acquisition request has been marked Received.',
+            'ath',
+            'description'
+        ),
+        TRUE
+    ), (
+        'aur.cancelled',
+        'aur',
+        oils_i18n_gettext(
+            'aur.cancelled',
+            'A patron acquisition request has been marked Cancelled.',
+            'ath',
+            'description'
+        ),
+        TRUE
+    )
+;
+
+INSERT INTO action_trigger.validator (module,description) VALUES (
+        'Acq::UserRequestOrdered',
+        oils_i18n_gettext(
+            'Acq::UserRequestOrdered',
+            'Tests to see if the corresponding Line Item has a state of "on-order".',
+            'atval',
+            'description'
+        )
+    ), (
+        'Acq::UserRequestReceived',
+        oils_i18n_gettext(
+            'Acq::UserRequestReceived',
+            'Tests to see if the corresponding Line Item has a state of "received".',
+            'atval',
+            'description'
+        )
+    ), (
+        'Acq::UserRequestCancelled',
+        oils_i18n_gettext(
+            'Acq::UserRequestCancelled',
+            'Tests to see if the corresponding Line Item has a state of "cancelled".',
+            'atval',
+            'description'
+        )
+    )
+;
+
+-- What was event_definition #15 in v1.6.1 will be recreated as #20.  This
+-- renumbering requires some juggling:
+--
+-- 1. Update any child rows to point to #20.  These updates will temporarily
+-- violate foreign key constraints, but that's okay as long as we create
+-- #20 before committing.
+--
+-- 2. Delete the old #15.
+--
+-- 3. Insert the new #15.
+--
+-- 4. Insert #20.
+--
+-- We could combine steps 2 and 3 into a single update, but that would create
+-- additional opportunities for typos, since we already have the insert from
+-- an upgrade script.
+
+UPDATE action_trigger.environment
+SET event_def = 20
+WHERE event_def = 15;
+
+UPDATE action_trigger.event
+SET event_def = 20
+WHERE event_def = 15;
+
+UPDATE action_trigger.event_params
+SET event_def = 20
+WHERE event_def = 15;
+
+DELETE FROM action_trigger.event_definition
+WHERE id = 15;
+
+INSERT INTO action_trigger.event_definition (
+        id,
+        active,
+        owner,
+        name,
+        hook,
+        validator,
+        reactor,
+        template
+    ) VALUES (
+        15,
+        FALSE,
+        1,
+        'Email Notice: Patron Acquisition Request marked On-Order.',
+        'aur.ordered',
+        'Acq::UserRequestOrdered',
+        'SendEmail',
+$$
+[%- USE date -%]
+[%- SET li = target.lineitem; -%]
+[%- SET user = target.usr -%]
+[%- SET title = helpers.get_li_attr("title", "", li.attributes) -%]
+[%- SET author = helpers.get_li_attr("author", "", li.attributes) -%]
+[%- SET edition = helpers.get_li_attr("edition", "", li.attributes) -%]
+[%- SET isbn = helpers.get_li_attr("isbn", "", li.attributes) -%]
+[%- SET publisher = helpers.get_li_attr("publisher", "", li.attributes) -%]
+[%- SET pubdate = helpers.get_li_attr("pubdate", "", li.attributes) -%]
+
+To: [%- params.recipient_email || user.email %]
+From: [%- params.sender_email || default_sender %]
+Subject: Acquisition Request Notification
+
+Dear [% user.family_name %], [% user.first_given_name %]
+Our records indicate the following acquisition request has been placed on order.
+
+Title: [% title %]
+[% IF author %]Author: [% author %][% END %]
+[% IF edition %]Edition: [% edition %][% END %]
+[% IF isbn %]ISBN: [% isbn %][% END %]
+[% IF publisher %]Publisher: [% publisher %][% END %]
+[% IF pubdate %]Publication Date: [% pubdate %][% END %]
+Lineitem ID: [% li.id %]
+$$
+    ), (
+        16,
+        FALSE,
+        1,
+        'Email Notice: Patron Acquisition Request marked Received.',
+        'aur.received',
+        'Acq::UserRequestReceived',
+        'SendEmail',
+$$
+[%- USE date -%]
+[%- SET li = target.lineitem; -%]
+[%- SET user = target.usr -%]
+[%- SET title = helpers.get_li_attr("title", "", li.attributes) %]
+[%- SET author = helpers.get_li_attr("author", "", li.attributes) %]
+[%- SET edition = helpers.get_li_attr("edition", "", li.attributes) %]
+[%- SET isbn = helpers.get_li_attr("isbn", "", li.attributes) %]
+[%- SET publisher = helpers.get_li_attr("publisher", "", li.attributes) -%]
+[%- SET pubdate = helpers.get_li_attr("pubdate", "", li.attributes) -%]
+
+To: [%- params.recipient_email || user.email %]
+From: [%- params.sender_email || default_sender %]
+Subject: Acquisition Request Notification
+
+Dear [% user.family_name %], [% user.first_given_name %]
+Our records indicate the materials for the following acquisition request have been received.
+
+Title: [% title %]
+[% IF author %]Author: [% author %][% END %]
+[% IF edition %]Edition: [% edition %][% END %]
+[% IF isbn %]ISBN: [% isbn %][% END %]
+[% IF publisher %]Publisher: [% publisher %][% END %]
+[% IF pubdate %]Publication Date: [% pubdate %][% END %]
+Lineitem ID: [% li.id %]
+$$
+    ), (
+        17,
+        FALSE,
+        1,
+        'Email Notice: Patron Acquisition Request marked Cancelled.',
+        'aur.cancelled',
+        'Acq::UserRequestCancelled',
+        'SendEmail',
+$$
+[%- USE date -%]
+[%- SET li = target.lineitem; -%]
+[%- SET user = target.usr -%]
+[%- SET title = helpers.get_li_attr("title", "", li.attributes) %]
+[%- SET author = helpers.get_li_attr("author", "", li.attributes) %]
+[%- SET edition = helpers.get_li_attr("edition", "", li.attributes) %]
+[%- SET isbn = helpers.get_li_attr("isbn", "", li.attributes) %]
+[%- SET publisher = helpers.get_li_attr("publisher", "", li.attributes) -%]
+[%- SET pubdate = helpers.get_li_attr("pubdate", "", li.attributes) -%]
+
+To: [%- params.recipient_email || user.email %]
+From: [%- params.sender_email || default_sender %]
+Subject: Acquisition Request Notification
+
+Dear [% user.family_name %], [% user.first_given_name %]
+Our records indicate the following acquisition request has been cancelled.
+
+Title: [% title %]
+[% IF author %]Author: [% author %][% END %]
+[% IF edition %]Edition: [% edition %][% END %]
+[% IF isbn %]ISBN: [% isbn %][% END %]
+[% IF publisher %]Publisher: [% publisher %][% END %]
+[% IF pubdate %]Publication Date: [% pubdate %][% END %]
+Lineitem ID: [% li.id %]
+$$
+    );
+
+INSERT INTO action_trigger.environment (
+        event_def,
+        path
+    ) VALUES 
+        ( 15, 'lineitem' ),
+        ( 15, 'lineitem.attributes' ),
+        ( 15, 'usr' ),
+
+        ( 16, 'lineitem' ),
+        ( 16, 'lineitem.attributes' ),
+        ( 16, 'usr' ),
+
+        ( 17, 'lineitem' ),
+        ( 17, 'lineitem.attributes' ),
+        ( 17, 'usr' )
+    ;
+
+INSERT INTO action_trigger.event_definition
+(id, active, owner, name, hook, validator, reactor, cleanup_success, cleanup_failure, delay, delay_field, group_field, template) VALUES
+(23, true, 1, 'PO JEDI', 'acqpo.activated', 'Acq::PurchaseOrderEDIRequired', 'GeneratePurchaseOrderJEDI', NULL, NULL, '00:05:00', NULL, NULL,
+$$[%- USE date -%]
+[%# start JEDI document -%]
+[%- BLOCK big_block -%]
+{
+   "recipient":"[% target.provider.san %]",
+   "sender":"[% target.ordering_agency.mailing_address.san %]",
+   "body": [{
+     "ORDERS":[ "order", {
+        "po_number":[% target.id %],
+        "date":"[% date.format(date.now, '%Y%m%d') %]",
+        "buyer":[{
+            [%- IF target.provider.edi_default.vendcode -%]
+                "id":"[% target.ordering_agency.mailing_address.san _ ' ' _ target.provider.edi_default.vendcode %]", 
+                "id-qualifier": 91
+            [%- ELSE -%]
+                "id":"[% target.ordering_agency.mailing_address.san %]"
+            [%- END  -%]
+        }],
+        "vendor":[ 
+            [%- # target.provider.name (target.provider.id) -%]
+            "[% target.provider.san %]",
+            {"id-qualifier": 92, "id":"[% target.provider.id %]"}
+        ],
+        "currency":"[% target.provider.currency_type %]",
+        "items":[
+        [% FOR li IN target.lineitems %]
+        {
+            "identifiers":[   [%-# li.isbns = helpers.get_li_isbns(li.attributes) %]
+            [% FOR isbn IN helpers.get_li_isbns(li.attributes) -%]
+                [% IF isbn.length == 13 -%]
+                {"id-qualifier":"EN","id":"[% isbn %]"},
+                [% ELSE -%]
+                {"id-qualifier":"IB","id":"[% isbn %]"},
+                [%- END %]
+            [% END %]
+                {"id-qualifier":"SA","id":"[% li.id %]"}
+            ],
+            "price":[% li.estimated_unit_price || '0.00' %],
+            "desc":[
+                {"BTI":"[% helpers.get_li_attr('title',     '', li.attributes) %]"}, 
+                {"BPU":"[% helpers.get_li_attr('publisher', '', li.attributes) %]"},
+                {"BPD":"[% helpers.get_li_attr('pubdate',   '', li.attributes) %]"},
+                {"BPH":"[% helpers.get_li_attr('pagination','', li.attributes) %]"}
+            ],
+            "quantity":[% li.lineitem_details.size %]
+        }[% UNLESS loop.last %],[% END %]
+        [%-# TODO: lineitem details (later) -%]
+        [% END %]
+        ],
+        "line_items":[% target.lineitems.size %]
+     }]  [% # close ORDERS array %]
+   }]    [% # close  body  array %]
+}
+[% END %]
+[% tempo = PROCESS big_block; helpers.escape_json(tempo) %]
+$$
+);
+
+INSERT INTO action_trigger.environment (event_def, path) VALUES 
+  (23, 'lineitems.attributes'), 
+  (23, 'lineitems.lineitem_details'), 
+  (23, 'lineitems.lineitem_notes'), 
+  (23, 'ordering_agency.mailing_address'), 
+  (23, 'provider');
+
+UPDATE action_trigger.event_definition SET template = 
+$$
+[%- USE date -%]
+[%-
+    # find a lineitem attribute by name and optional type
+    BLOCK get_li_attr;
+        FOR attr IN li.attributes;
+            IF attr.attr_name == attr_name;
+                IF !attr_type OR attr_type == attr.attr_type;
+                    attr.attr_value;
+                    LAST;
+                END;
+            END;
+        END;
+    END
+-%]
+
+<h2>Purchase Order [% target.id %]</h2>
+<br/>
+date <b>[% date.format(date.now, '%Y%m%d') %]</b>
+<br/>
+
+<style>
+    table td { padding:5px; border:1px solid #aaa;}
+    table { width:95%; border-collapse:collapse; }
+    #vendor-notes { padding:5px; border:1px solid #aaa; }
+</style>
+<table id='vendor-table'>
+  <tr>
+    <td valign='top'>Vendor</td>
+    <td>
+      <div>[% target.provider.name %]</div>
+      <div>[% target.provider.addresses.0.street1 %]</div>
+      <div>[% target.provider.addresses.0.street2 %]</div>
+      <div>[% target.provider.addresses.0.city %]</div>
+      <div>[% target.provider.addresses.0.state %]</div>
+      <div>[% target.provider.addresses.0.country %]</div>
+      <div>[% target.provider.addresses.0.post_code %]</div>
+    </td>
+    <td valign='top'>Ship to / Bill to</td>
+    <td>
+      <div>[% target.ordering_agency.name %]</div>
+      <div>[% target.ordering_agency.billing_address.street1 %]</div>
+      <div>[% target.ordering_agency.billing_address.street2 %]</div>
+      <div>[% target.ordering_agency.billing_address.city %]</div>
+      <div>[% target.ordering_agency.billing_address.state %]</div>
+      <div>[% target.ordering_agency.billing_address.country %]</div>
+      <div>[% target.ordering_agency.billing_address.post_code %]</div>
+    </td>
+  </tr>
+</table>
+
+<br/><br/>
+<fieldset id='vendor-notes'>
+    <legend>Notes to the Vendor</legend>
+    <ul>
+    [% FOR note IN target.notes %]
+        [% IF note.vendor_public == 't' %]
+            <li>[% note.value %]</li>
+        [% END %]
+    [% END %]
+    </ul>
+</fieldset>
+<br/><br/>
+
+<table>
+  <thead>
+    <tr>
+      <th>PO#</th>
+      <th>ISBN or Item #</th>
+      <th>Title</th>
+      <th>Quantity</th>
+      <th>Unit Price</th>
+      <th>Line Total</th>
+      <th>Notes</th>
+    </tr>
+  </thead>
+  <tbody>
+
+  [% subtotal = 0 %]
+  [% FOR li IN target.lineitems %]
+
+  <tr>
+    [% count = li.lineitem_details.size %]
+    [% price = li.estimated_unit_price %]
+    [% litotal = (price * count) %]
+    [% subtotal = subtotal + litotal %]
+    [% isbn = PROCESS get_li_attr attr_name = 'isbn' %]
+    [% ident = PROCESS get_li_attr attr_name = 'identifier' %]
+
+    <td>[% target.id %]</td>
+    <td>[% isbn || ident %]</td>
+    <td>[% PROCESS get_li_attr attr_name = 'title' %]</td>
+    <td>[% count %]</td>
+    <td>[% price %]</td>
+    <td>[% litotal %]</td>
+    <td>
+        <ul>
+        [% FOR note IN li.lineitem_notes %]
+            [% IF note.vendor_public == 't' %]
+                <li>[% note.value %]</li>
+            [% END %]
+        [% END %]
+        </ul>
+    </td>
+  </tr>
+  [% END %]
+  <tr>
+    <td/><td/><td/><td/>
+    <td>Subtotal</td>
+    <td>[% subtotal %]</td>
+  </tr>
+  </tbody>
+</table>
+
+<br/>
+
+Total Line Item Count: [% target.lineitems.size %]
+$$
+WHERE id = 4;
+
+INSERT INTO action_trigger.environment (event_def, path) VALUES 
+    (4, 'lineitems.lineitem_notes'),
+    (4, 'notes');
+
+INSERT INTO action_trigger.environment (event_def, path) VALUES
+    ( 14, 'lineitem_notes.alert_text' ),
+    ( 14, 'distribution_formulas.formula' ),
+    ( 14, 'lineitem_details.fund' ),
+    ( 14, 'lineitem_details.eg_copy_id' ),
+    ( 14, 'lineitem_details.eg_copy_id.call_number' )
+;
+
+INSERT INTO action_trigger.hook (key,core_type,description,passive) VALUES (
+        'aur.created',
+        'aur',
+        oils_i18n_gettext(
+            'aur.created',
+            'A patron has made an acquisitions request.',
+            'ath',
+            'description'
+        ),
+        TRUE
+    ), (
+        'aur.rejected',
+        'aur',
+        oils_i18n_gettext(
+            'aur.rejected',
+            'A patron acquisition request has been rejected.',
+            'ath',
+            'description'
+        ),
+        TRUE
+    )
+;
+
+INSERT INTO action_trigger.event_definition (
+        id,
+        active,
+        owner,
+        name,
+        hook,
+        validator,
+        reactor,
+        template
+    ) VALUES (
+        18,
+        FALSE,
+        1,
+        'Email Notice: Acquisition Request created.',
+        'aur.created',
+        'NOOP_True',
+        'SendEmail',
+$$
+[%- USE date -%]
+[%- SET user = target.usr -%]
+[%- SET title = target.title -%]
+[%- SET author = target.author -%]
+[%- SET isxn = target.isxn -%]
+[%- SET publisher = target.publisher -%]
+[%- SET pubdate = target.pubdate -%]
+
+To: [%- params.recipient_email || user.email %]
+From: [%- params.sender_email || default_sender %]
+Subject: Acquisition Request Notification
+
+Dear [% user.family_name %], [% user.first_given_name %]
+Our records indicate that you have made the following acquisition request:
+
+Title: [% title %]
+[% IF author %]Author: [% author %][% END %]
+[% IF edition %]Edition: [% edition %][% END %]
+[% IF isbn %]ISXN: [% isxn %][% END %]
+[% IF publisher %]Publisher: [% publisher %][% END %]
+[% IF pubdate %]Publication Date: [% pubdate %][% END %]
+$$
+    ), (
+        19,
+        FALSE,
+        1,
+        'Email Notice: Acquisition Request Rejected.',
+        'aur.rejected',
+        'NOOP_True',
+        'SendEmail',
+$$
+[%- USE date -%]
+[%- SET user = target.usr -%]
+[%- SET title = target.title -%]
+[%- SET author = target.author -%]
+[%- SET isxn = target.isxn -%]
+[%- SET publisher = target.publisher -%]
+[%- SET pubdate = target.pubdate -%]
+[%- SET cancel_reason = target.cancel_reason.description -%]
+
+To: [%- params.recipient_email || user.email %]
+From: [%- params.sender_email || default_sender %]
+Subject: Acquisition Request Notification
+
+Dear [% user.family_name %], [% user.first_given_name %]
+Our records indicate the following acquisition request has been rejected for this reason: [% cancel_reason %]
+
+Title: [% title %]
+[% IF author %]Author: [% author %][% END %]
+[% IF edition %]Edition: [% edition %][% END %]
+[% IF isbn %]ISBN: [% isbn %][% END %]
+[% IF publisher %]Publisher: [% publisher %][% END %]
+[% IF pubdate %]Publication Date: [% pubdate %][% END %]
+$$
+    );
+
+INSERT INTO action_trigger.environment (
+        event_def,
+        path
+    ) VALUES 
+        ( 18, 'usr' ),
+        ( 19, 'usr' ),
+        ( 19, 'cancel_reason' )
+    ;
+
+INSERT INTO action_trigger.event_definition (id, active, owner, name, hook, validator, reactor, delay, template) 
+    VALUES (20, 'f', 1, 'Password reset request notification', 'password.reset_request', 'NOOP_True', 'SendEmail', '00:00:01',
+$$
+[%- USE date -%]
+[%- user = target.usr -%]
+To: [%- params.recipient_email || user.email %]
+From: [%- params.sender_email || user.home_ou.email || default_sender %]
+Subject: [% user.home_ou.name %]: library account password reset request
+  
+You have received this message because you, or somebody else, requested a reset
+of your library system password. If you did not request a reset of your library
+system password, just ignore this message and your current password will
+continue to work.
+
+If you did request a reset of your library system password, please perform
+the following steps to continue the process of resetting your password:
+
+1. Open the following link in a web browser: https://[% params.hostname %]/opac/password/[% params.locale || 'en-US' %]/[% target.uuid %]
+The browser displays a password reset form.
+
+2. Enter your new password in the password reset form in the browser. You must
+enter the password twice to ensure that you do not make a mistake. If the
+passwords match, you will then be able to log in to your library system account
+with the new password.
+
+$$);
+
+INSERT INTO action_trigger.hook (key, core_type, description, passive)
+    VALUES (
+        'format.acqcle.html',
+        'acqcle',
+        'Formats claim events into a voucher',
+        TRUE
+    );
+
+INSERT INTO action_trigger.event_definition (
+        id, active, owner, name, hook, group_field,
+        validator, reactor, granularity, template
+    ) VALUES (
+        21,
+        TRUE,
+        1,
+        'Claim Voucher',
+        'format.acqcle.html',
+        'claim',
+        'NOOP_True',
+        'ProcessTemplate',
+        'print-on-demand',
+$$
+[%- USE date -%]
+[%- SET claim = target.0.claim -%]
+<!-- This will need refined/prettified. -->
+<div class="acq-claim-voucher">
+    <h2>Claim: [% claim.id %] ([% claim.type.code %])</h2>
+    <h3>Against: [%- helpers.get_li_attr("title", "", claim.lineitem_detail.lineitem.attributes) -%]</h3>
+    <ul>
+        [% FOR event IN target %]
+        <li>
+            Event type: [% event.type.code %]
+            [% IF event.type.library_initiated %](Library initiated)[% END %]
+            <br />
+            Event date: [% event.event_date %]<br />
+            Order date: [% event.claim.lineitem_detail.lineitem.purchase_order.order_date %]<br />
+            Expected receive date: [% event.claim.lineitem_detail.lineitem.expected_recv_time %]<br />
+            Initiated by: [% event.creator.family_name %], [% event.creator.first_given_name %] [% event.creator.second_given_name %]<br />
+            Barcode: [% event.claim.lineitem_detail.barcode %]; Fund:
+            [% event.claim.lineitem_detail.fund.code %]
+            ([% event.claim.lineitem_detail.fund.year %])
+        </li>
+        [% END %]
+    </ul>
+</div>
+$$
+);
+
+INSERT INTO action_trigger.environment (event_def, path) VALUES
+    (21, 'claim'),
+    (21, 'claim.type'),
+    (21, 'claim.lineitem_detail'),
+    (21, 'claim.lineitem_detail.fund'),
+    (21, 'claim.lineitem_detail.lineitem.attributes'),
+    (21, 'claim.lineitem_detail.lineitem.purchase_order'),
+    (21, 'creator'),
+    (21, 'type')
+;
+
+INSERT INTO action_trigger.hook (key, core_type, description, passive)
+    VALUES (
+        'format.acqinv.html',
+        'acqinv',
+        'Formats invoices into a voucher',
+        TRUE
+    );
+
+INSERT INTO action_trigger.event_definition (
+        id, active, owner, name, hook,
+        validator, reactor, granularity, template
+    ) VALUES (
+        22,
+        TRUE,
+        1,
+        'Invoice',
+        'format.acqinv.html',
+        'NOOP_True',
+        'ProcessTemplate',
+        'print-on-demand',
+$$
+[% FILTER collapse %]
+[%- SET invoice = target -%]
+<!-- This lacks totals, info about funds (for invoice entries,
+    funds are per-LID!), and general refinement -->
+<div class="acq-invoice-voucher">
+    <h1>Invoice</h1>
+    <div>
+        <strong>No.</strong> [% invoice.inv_ident %]
+        [% IF invoice.inv_type %]
+            / <strong>Type:</strong>[% invoice.inv_type %]
+        [% END %]
+    </div>
+    <div>
+        <dl>
+            [% BLOCK ent_with_address %]
+            <dt>[% ent_label %]: [% ent.name %] ([% ent.code %])</dt>
+            <dd>
+                [% IF ent.addresses.0 %]
+                    [% SET addr = ent.addresses.0 %]
+                    [% addr.street1 %]<br />
+                    [% IF addr.street2 %][% addr.street2 %]<br />[% END %]
+                    [% addr.city %],
+                    [% IF addr.county %] [% addr.county %], [% END %]
+                    [% IF addr.state %] [% addr.state %] [% END %]
+                    [% IF addr.post_code %][% addr.post_code %][% END %]<br />
+                    [% IF addr.country %] [% addr.country %] [% END %]
+                [% END %]
+                <p>
+                    [% IF ent.phone %] Phone: [% ent.phone %]<br />[% END %]
+                    [% IF ent.fax_phone %] Fax: [% ent.fax_phone %]<br />[% END %]
+                    [% IF ent.url %] URL: [% ent.url %]<br />[% END %]
+                    [% IF ent.email %] E-mail: [% ent.email %] [% END %]
+                </p>
+            </dd>
+            [% END %]
+            [% INCLUDE ent_with_address
+                ent = invoice.provider
+                ent_label = "Provider" %]
+            [% INCLUDE ent_with_address
+                ent = invoice.shipper
+                ent_label = "Shipper" %]
+            <dt>Receiver</dt>
+            <dd>
+                [% invoice.receiver.name %] ([% invoice.receiver.shortname %])
+            </dd>
+            <dt>Received</dt>
+            <dd>
+                [% helpers.format_date(invoice.recv_date) %] by
+                [% invoice.recv_method %]
+            </dd>
+            [% IF invoice.note %]
+                <dt>Note</dt>
+                <dd>
+                    [% invoice.note %]
+                </dd>
+            [% END %]
+        </dl>
+    </div>
+    <ul>
+        [% FOR entry IN invoice.entries %]
+            <li>
+                [% IF entry.lineitem %]
+                    Title: [% helpers.get_li_attr(
+                        "title", "", entry.lineitem.attributes
+                    ) %]<br />
+                    Author: [% helpers.get_li_attr(
+                        "author", "", entry.lineitem.attributes
+                    ) %]
+                [% END %]
+                [% IF entry.purchase_order %]
+                    (PO: [% entry.purchase_order.name %])
+                [% END %]<br />
+                Invoice item count: [% entry.inv_item_count %]
+                [% IF entry.phys_item_count %]
+                    / Physical item count: [% entry.phys_item_count %]
+                [% END %]
+                <br />
+                [% IF entry.cost_billed %]
+                    Cost billed: [% entry.cost_billed %]
+                    [% IF entry.billed_per_item %](per item)[% END %]
+                    <br />
+                [% END %]
+                [% IF entry.actual_cost %]
+                    Actual cost: [% entry.actual_cost %]<br />
+                [% END %]
+                [% IF entry.amount_paid %]
+                    Amount paid: [% entry.amount_paid %]<br />
+                [% END %]
+                [% IF entry.note %]Note: [% entry.note %][% END %]
+            </li>
+        [% END %]
+        [% FOR item IN invoice.items %]
+            <li>
+                [% IF item.inv_item_type %]
+                    Item Type: [% item.inv_item_type %]<br />
+                [% END %]
+                [% IF item.title %]Title/Description:
+                    [% item.title %]<br />
+                [% END %]
+                [% IF item.author %]Author: [% item.author %]<br />[% END %]
+                [% IF item.purchase_order %]PO: [% item.purchase_order %]<br />[% END %]
+                [% IF item.note %]Note: [% item.note %]<br />[% END %]
+                [% IF item.cost_billed %]
+                    Cost billed: [% item.cost_billed %]<br />
+                [% END %]
+                [% IF item.actual_cost %]
+                    Actual cost: [% item.actual_cost %]<br />
+                [% END %]
+                [% IF item.amount_paid %]
+                    Amount paid: [% item.amount_paid %]<br />
+                [% END %]
+            </li>
+        [% END %]
+    </ul>
+</div>
+[% END %]
+$$
+);
+
+INSERT INTO action_trigger.environment (event_def, path) VALUES
+    (22, 'provider'),
+    (22, 'provider.addresses'),
+    (22, 'shipper'),
+    (22, 'shipper.addresses'),
+    (22, 'receiver'),
+    (22, 'entries'),
+    (22, 'entries.purchase_order'),
+    (22, 'entries.lineitem'),
+    (22, 'entries.lineitem.attributes'),
+    (22, 'items')
+;
+
+INSERT INTO action_trigger.environment (event_def, path) VALUES 
+  (23, 'provider.edi_default');
+
+INSERT INTO action_trigger.validator (module, description) 
+    VALUES (
+        'Acq::PurchaseOrderEDIRequired',
+        oils_i18n_gettext(
+            'Acq::PurchaseOrderEDIRequired',
+            'Purchase order is delivered via EDI',
+            'atval',
+            'description'
+        )
+    );
+
+INSERT INTO action_trigger.reactor (module, description)
+    VALUES (
+        'GeneratePurchaseOrderJEDI',
+        oils_i18n_gettext(
+            'GeneratePurchaseOrderJEDI',
+            'Creates purchase order JEDI (JSON EDI) for subsequent EDI processing',
+            'atreact',
+            'description'
+        )
+    );
+
+UPDATE action_trigger.hook 
+    SET 
+        key = 'acqpo.activated', 
+        passive = FALSE,
+        description = oils_i18n_gettext(
+            'acqpo.activated',
+            'Purchase order was activated',
+            'ath',
+            'description'
+        )
+    WHERE key = 'format.po.jedi';
+
+-- We just changed a key in action_trigger.hook.  Now redirect any
+-- child rows to point to the new key.  (There probably aren't any;
+-- this is just a precaution against possible local modifications.)
+
+UPDATE action_trigger.event_definition
+SET hook = 'acqpo.activated'
+WHERE hook = 'format.po.jedi';
+
+INSERT INTO action_trigger.reactor (module, description) VALUES (
+    'AstCall', 'Possibly place a phone call with Asterisk'
+);
+
+INSERT INTO
+    action_trigger.event_definition (
+        id, active, owner, name, hook, validator, reactor,
+        cleanup_success, cleanup_failure, delay, delay_field, group_field,
+        max_delay, granularity, usr_field, opt_in_setting, template
+    ) VALUES (
+        24,
+        FALSE,
+        1,
+        'Telephone Overdue Notice',
+        'checkout.due', 'NOOP_True', 'AstCall',
+        DEFAULT, DEFAULT, '5 seconds', 'due_date', 'usr',
+        DEFAULT, DEFAULT, DEFAULT, DEFAULT,
+        $$
+[% phone = target.0.usr.day_phone | replace('[\s\-\(\)]', '') -%]
+[% IF phone.match('^[2-9]') %][% country = 1 %][% ELSE %][% country = '' %][% END -%]
+Channel: [% channel_prefix %]/[% country %][% phone %]
+Context: overdue-test
+MaxRetries: 1
+RetryTime: 60
+WaitTime: 30
+Extension: 10
+Archive: 1
+Set: eg_user_id=[% target.0.usr.id %]
+Set: items=[% target.size %]
+Set: titlestring=[% titles = [] %][% FOR circ IN target %][% titles.push(circ.target_copy.call_number.record.simple_record.title) %][% END %][% titles.join(". ") %]
+$$
+    );
+
+INSERT INTO
+    action_trigger.environment (id, event_def, path)
+    VALUES
+        (DEFAULT, 24, 'target_copy.call_number.record.simple_record'),
+        (DEFAULT, 24, 'usr')
+    ;
+
+INSERT INTO action_trigger.hook (key,core_type,description,passive) VALUES (
+        'circ.format.history.email',
+        'circ', 
+        oils_i18n_gettext(
+            'circ.format.history.email',
+            'An email has been requested for a circ history.',
+            'ath',
+            'description'
+        ), 
+        FALSE
+    )
+    ,(
+        'circ.format.history.print',
+        'circ', 
+        oils_i18n_gettext(
+            'circ.format.history.print',
+            'A circ history needs to be formatted for printing.',
+            'ath',
+            'description'
+        ), 
+        FALSE
+    )
+    ,(
+        'ahr.format.history.email',
+        'ahr', 
+        oils_i18n_gettext(
+            'ahr.format.history.email',
+            'An email has been requested for a hold request history.',
+            'ath',
+            'description'
+        ), 
+        FALSE
+    )
+    ,(
+        'ahr.format.history.print',
+        'ahr', 
+        oils_i18n_gettext(
+            'ahr.format.history.print',
+            'A hold request history needs to be formatted for printing.',
+            'ath',
+            'description'
+        ), 
+        FALSE
+    )
+
+;
+
+INSERT INTO action_trigger.event_definition (
+        id,
+        active,
+        owner,
+        name,
+        hook,
+        validator,
+        reactor,
+        group_field,
+        granularity,
+        template
+    ) VALUES (
+        25,
+        TRUE,
+        1,
+        'circ.history.email',
+        'circ.format.history.email',
+        'NOOP_True',
+        'SendEmail',
+        'usr',
+        NULL,
+$$
+[%- USE date -%]
+[%- SET user = target.0.usr -%]
+To: [%- params.recipient_email || user.email %]
+From: [%- params.sender_email || default_sender %]
+Subject: Circulation History
+
+    [% FOR circ IN target %]
+            [% helpers.get_copy_bib_basics(circ.target_copy.id).title %]
+            Barcode: [% circ.target_copy.barcode %]
+            Checked Out: [% date.format(helpers.format_date(circ.xact_start), '%Y-%m-%d') %]
+            Due Date: [% date.format(helpers.format_date(circ.due_date), '%Y-%m-%d') %]
+            Returned: [% date.format(helpers.format_date(circ.checkin_time), '%Y-%m-%d') %]
+    [% END %]
+$$
+    )
+    ,(
+        26,
+        TRUE,
+        1,
+        'circ.history.print',
+        'circ.format.history.print',
+        'NOOP_True',
+        'ProcessTemplate',
+        'usr',
+        'print-on-demand',
+$$
+[%- USE date -%]
+<div>
+    <style> li { padding: 8px; margin 5px; }</style>
+    <div>[% date.format %]</div>
+    <br/>
+
+    [% user.family_name %], [% user.first_given_name %]
+    <ol>
+    [% FOR circ IN target %]
+        <li>
+            <div>[% helpers.get_copy_bib_basics(circ.target_copy.id).title %]</div>
+            <div>Barcode: [% circ.target_copy.barcode %]</div>
+            <div>Checked Out: [% date.format(helpers.format_date(circ.xact_start), '%Y-%m-%d') %]</div>
+            <div>Due Date: [% date.format(helpers.format_date(circ.due_date), '%Y-%m-%d') %]</div>
+            <div>Returned: [% date.format(helpers.format_date(circ.checkin_time), '%Y-%m-%d') %]</div>
+        </li>
+    [% END %]
+    </ol>
+</div>
+$$
+    )
+    ,(
+        27,
+        TRUE,
+        1,
+        'ahr.history.email',
+        'ahr.format.history.email',
+        'NOOP_True',
+        'SendEmail',
+        'usr',
+        NULL,
+$$
+[%- USE date -%]
+[%- SET user = target.0.usr -%]
+To: [%- params.recipient_email || user.email %]
+From: [%- params.sender_email || default_sender %]
+Subject: Hold Request History
+
+    [% FOR hold IN target %]
+            [% helpers.get_copy_bib_basics(hold.current_copy.id).title %]
+            Requested: [% date.format(helpers.format_date(hold.request_time), '%Y-%m-%d') %]
+            [% IF hold.fulfillment_time %]Fulfilled: [% date.format(helpers.format_date(hold.fulfillment_time), '%Y-%m-%d') %][% END %]
+    [% END %]
+$$
+    )
+    ,(
+        28,
+        TRUE,
+        1,
+        'ahr.history.print',
+        'ahr.format.history.print',
+        'NOOP_True',
+        'ProcessTemplate',
+        'usr',
+        'print-on-demand',
+$$
+[%- USE date -%]
+<div>
+    <style> li { padding: 8px; margin 5px; }</style>
+    <div>[% date.format %]</div>
+    <br/>
+
+    [% user.family_name %], [% user.first_given_name %]
+    <ol>
+    [% FOR hold IN target %]
+        <li>
+            <div>[% helpers.get_copy_bib_basics(hold.current_copy.id).title %]</div>
+            <div>Requested: [% date.format(helpers.format_date(hold.request_time), '%Y-%m-%d') %]</div>
+            [% IF hold.fulfillment_time %]<div>Fulfilled: [% date.format(helpers.format_date(hold.fulfillment_time), '%Y-%m-%d') %]</div>[% END %]
+        </li>
+    [% END %]
+    </ol>
+</div>
+$$
+    )
+
+;
+
+INSERT INTO action_trigger.environment (
+        event_def,
+        path
+    ) VALUES 
+         ( 25, 'target_copy')
+        ,( 25, 'usr' )
+        ,( 26, 'target_copy' )
+        ,( 26, 'usr' )
+        ,( 27, 'current_copy' )
+        ,( 27, 'usr' )
+        ,( 28, 'current_copy' )
+        ,( 28, 'usr' )
+;
+
+INSERT INTO action_trigger.hook (key,core_type,description,passive) VALUES (
+        'money.format.payment_receipt.email',
+        'mp', 
+        oils_i18n_gettext(
+            'money.format.payment_receipt.email',
+            'An email has been requested for a payment receipt.',
+            'ath',
+            'description'
+        ), 
+        FALSE
+    )
+    ,(
+        'money.format.payment_receipt.print',
+        'mp', 
+        oils_i18n_gettext(
+            'money.format.payment_receipt.print',
+            'A payment receipt needs to be formatted for printing.',
+            'ath',
+            'description'
+        ), 
+        FALSE
+    )
+;
+
+INSERT INTO action_trigger.event_definition (
+        id,
+        active,
+        owner,
+        name,
+        hook,
+        validator,
+        reactor,
+        group_field,
+        granularity,
+        template
+    ) VALUES (
+        29,
+        TRUE,
+        1,
+        'money.payment_receipt.email',
+        'money.format.payment_receipt.email',
+        'NOOP_True',
+        'SendEmail',
+        'xact.usr',
+        NULL,
+$$
+[%- USE date -%]
+[%- SET user = target.0.xact.usr -%]
+To: [%- params.recipient_email || user.email %]
+From: [%- params.sender_email || default_sender %]
+Subject: Payment Receipt
+
+[% date.format -%]
+[%- SET xact_mp_hash = {} -%]
+[%- FOR mp IN target %][%# Template is hooked around payments, but let us make the receipt focused on transactions -%]
+    [%- SET xact_id = mp.xact.id -%]
+    [%- IF ! xact_mp_hash.defined( xact_id ) -%][%- xact_mp_hash.$xact_id = { 'xact' => mp.xact, 'payments' => [] } -%][%- END -%]
+    [%- xact_mp_hash.$xact_id.payments.push(mp) -%]
+[%- END -%]
+[%- FOR xact_id IN xact_mp_hash.keys.sort -%]
+    [%- SET xact = xact_mp_hash.$xact_id.xact %]
+Transaction ID: [% xact_id %]
+    [% IF xact.circulation %][% helpers.get_copy_bib_basics(xact.circulation.target_copy).title %]
+    [% ELSE %]Miscellaneous
+    [% END %]
+    Line item billings:
+        [%- SET mb_type_hash = {} -%]
+        [%- FOR mb IN xact.billings %][%# Group billings by their btype -%]
+            [%- IF mb.voided == 'f' -%]
+                [%- SET mb_type = mb.btype.id -%]
+                [%- IF ! mb_type_hash.defined( mb_type ) -%][%- mb_type_hash.$mb_type = { 'sum' => 0.00, 'billings' => [] } -%][%- END -%]
+                [%- IF ! mb_type_hash.$mb_type.defined( 'first_ts' ) -%][%- mb_type_hash.$mb_type.first_ts = mb.billing_ts -%][%- END -%]
+                [%- mb_type_hash.$mb_type.last_ts = mb.billing_ts -%]
+                [%- mb_type_hash.$mb_type.sum = mb_type_hash.$mb_type.sum + mb.amount -%]
+                [%- mb_type_hash.$mb_type.billings.push( mb ) -%]
+            [%- END -%]
+        [%- END -%]
+        [%- FOR mb_type IN mb_type_hash.keys.sort -%]
+            [%- IF mb_type == 1 %][%-# Consolidated view of overdue billings -%]
+                $[% mb_type_hash.$mb_type.sum %] for [% mb_type_hash.$mb_type.billings.0.btype.name %] 
+                    on [% mb_type_hash.$mb_type.first_ts %] through [% mb_type_hash.$mb_type.last_ts %]
+            [%- ELSE -%][%# all other billings show individually %]
+                [% FOR mb IN mb_type_hash.$mb_type.billings %]
+                    $[% mb.amount %] for [% mb.btype.name %] on [% mb.billing_ts %] [% mb.note %]
+                [% END %]
+            [% END %]
+        [% END %]
+    Line item payments:
+        [% FOR mp IN xact_mp_hash.$xact_id.payments %]
+            Payment ID: [% mp.id %]
+                Paid [% mp.amount %] via [% SWITCH mp.payment_type -%]
+                    [% CASE "cash_payment" %]cash
+                    [% CASE "check_payment" %]check
+                    [% CASE "credit_card_payment" %]credit card (
+                        [%- SET cc_chunks = mp.credit_card_payment.cc_number.replace(' ','').chunk(4); -%]
+                        [%- cc_chunks.slice(0, -1+cc_chunks.max).join.replace('\S','X') -%] 
+                        [% cc_chunks.last -%]
+                        exp [% mp.credit_card_payment.expire_month %]/[% mp.credit_card_payment.expire_year -%]
+                    )
+                    [% CASE "credit_payment" %]credit
+                    [% CASE "forgive_payment" %]forgiveness
+                    [% CASE "goods_payment" %]goods
+                    [% CASE "work_payment" %]work
+                [%- END %] on [% mp.payment_ts %] [% mp.note %]
+        [% END %]
+[% END %]
+$$
+    )
+    ,(
+        30,
+        TRUE,
+        1,
+        'money.payment_receipt.print',
+        'money.format.payment_receipt.print',
+        'NOOP_True',
+        'ProcessTemplate',
+        'xact.usr',
+        'print-on-demand',
+$$
+[%- USE date -%][%- SET user = target.0.xact.usr -%]
+<div style="li { padding: 8px; margin 5px; }">
+    <div>[% date.format %]</div><br/>
+    <ol>
+    [% SET xact_mp_hash = {} %]
+    [% FOR mp IN target %][%# Template is hooked around payments, but let us make the receipt focused on transactions %]
+        [% SET xact_id = mp.xact.id %]
+        [% IF ! xact_mp_hash.defined( xact_id ) %][% xact_mp_hash.$xact_id = { 'xact' => mp.xact, 'payments' => [] } %][% END %]
+        [% xact_mp_hash.$xact_id.payments.push(mp) %]
+    [% END %]
+    [% FOR xact_id IN xact_mp_hash.keys.sort %]
+        [% SET xact = xact_mp_hash.$xact_id.xact %]
+        <li>Transaction ID: [% xact_id %]
+            [% IF xact.circulation %][% helpers.get_copy_bib_basics(xact.circulation.target_copy).title %]
+            [% ELSE %]Miscellaneous
+            [% END %]
+            Line item billings:<ol>
+                [% SET mb_type_hash = {} %]
+                [% FOR mb IN xact.billings %][%# Group billings by their btype %]
+                    [% IF mb.voided == 'f' %]
+                        [% SET mb_type = mb.btype.id %]
+                        [% IF ! mb_type_hash.defined( mb_type ) %][% mb_type_hash.$mb_type = { 'sum' => 0.00, 'billings' => [] } %][% END %]
+                        [% IF ! mb_type_hash.$mb_type.defined( 'first_ts' ) %][% mb_type_hash.$mb_type.first_ts = mb.billing_ts %][% END %]
+                        [% mb_type_hash.$mb_type.last_ts = mb.billing_ts %]
+                        [% mb_type_hash.$mb_type.sum = mb_type_hash.$mb_type.sum + mb.amount %]
+                        [% mb_type_hash.$mb_type.billings.push( mb ) %]
+                    [% END %]
+                [% END %]
+                [% FOR mb_type IN mb_type_hash.keys.sort %]
+                    <li>[% IF mb_type == 1 %][%# Consolidated view of overdue billings %]
+                        $[% mb_type_hash.$mb_type.sum %] for [% mb_type_hash.$mb_type.billings.0.btype.name %] 
+                            on [% mb_type_hash.$mb_type.first_ts %] through [% mb_type_hash.$mb_type.last_ts %]
+                    [% ELSE %][%# all other billings show individually %]
+                        [% FOR mb IN mb_type_hash.$mb_type.billings %]
+                            $[% mb.amount %] for [% mb.btype.name %] on [% mb.billing_ts %] [% mb.note %]
+                        [% END %]
+                    [% END %]</li>
+                [% END %]
+            </ol>
+            Line item payments:<ol>
+                [% FOR mp IN xact_mp_hash.$xact_id.payments %]
+                    <li>Payment ID: [% mp.id %]
+                        Paid [% mp.amount %] via [% SWITCH mp.payment_type -%]
+                            [% CASE "cash_payment" %]cash
+                            [% CASE "check_payment" %]check
+                            [% CASE "credit_card_payment" %]credit card (
+                                [%- SET cc_chunks = mp.credit_card_payment.cc_number.replace(' ','').chunk(4); -%]
+                                [%- cc_chunks.slice(0, -1+cc_chunks.max).join.replace('\S','X') -%] 
+                                [% cc_chunks.last -%]
+                                exp [% mp.credit_card_payment.expire_month %]/[% mp.credit_card_payment.expire_year -%]
+                            )
+                            [% CASE "credit_payment" %]credit
+                            [% CASE "forgive_payment" %]forgiveness
+                            [% CASE "goods_payment" %]goods
+                            [% CASE "work_payment" %]work
+                        [%- END %] on [% mp.payment_ts %] [% mp.note %]
+                    </li>
+                [% END %]
+            </ol>
+        </li>
+    [% END %]
+    </ol>
+</div>
+$$
+    )
+;
+
+INSERT INTO action_trigger.environment (
+        event_def,
+        path
+    ) VALUES -- for fleshing mp objects
+         ( 29, 'xact')
+        ,( 29, 'xact.usr')
+        ,( 29, 'xact.grocery' )
+        ,( 29, 'xact.circulation' )
+        ,( 29, 'xact.summary' )
+        ,( 30, 'xact')
+        ,( 30, 'xact.usr')
+        ,( 30, 'xact.grocery' )
+        ,( 30, 'xact.circulation' )
+        ,( 30, 'xact.summary' )
+;
+
+INSERT INTO action_trigger.cleanup ( module, description ) VALUES (
+    'DeleteTempBiblioBucket',
+    oils_i18n_gettext(
+        'DeleteTempBiblioBucket',
+        'Deletes a cbreb object used as a target if it has a btype of "temp"',
+        'atclean',
+        'description'
+    )
+);
+
+INSERT INTO action_trigger.hook (key,core_type,description,passive) VALUES (
+        'biblio.format.record_entry.email',
+        'cbreb', 
+        oils_i18n_gettext(
+            'biblio.format.record_entry.email',
+            'An email has been requested for one or more biblio record entries.',
+            'ath',
+            'description'
+        ), 
+        FALSE
+    )
+    ,(
+        'biblio.format.record_entry.print',
+        'cbreb', 
+        oils_i18n_gettext(
+            'biblio.format.record_entry.print',
+            'One or more biblio record entries need to be formatted for printing.',
+            'ath',
+            'description'
+        ), 
+        FALSE
+    )
+;
+
+INSERT INTO action_trigger.event_definition (
+        id,
+        active,
+        owner,
+        name,
+        hook,
+        validator,
+        reactor,
+        cleanup_success,
+        cleanup_failure,
+        group_field,
+        granularity,
+        template
+    ) VALUES (
+        31,
+        TRUE,
+        1,
+        'biblio.record_entry.email',
+        'biblio.format.record_entry.email',
+        'NOOP_True',
+        'SendEmail',
+        'DeleteTempBiblioBucket',
+        'DeleteTempBiblioBucket',
+        'owner',
+        NULL,
+$$
+[%- USE date -%]
+[%- SET user = target.0.owner -%]
+To: [%- params.recipient_email || user.email %]
+From: [%- params.sender_email || default_sender %]
+Subject: Bibliographic Records
+
+    [% FOR cbreb IN target %]
+    [% FOR cbrebi IN cbreb.items %]
+        Bib ID# [% cbrebi.target_biblio_record_entry.id %] ISBN: [% crebi.target_biblio_record_entry.simple_record.isbn %]
+        Title: [% cbrebi.target_biblio_record_entry.simple_record.title %]
+        Author: [% cbrebi.target_biblio_record_entry.simple_record.author %]
+        Publication Year: [% cbrebi.target_biblio_record_entry.simple_record.pubdate %]
+
+    [% END %]
+    [% END %]
+$$
+    )
+    ,(
+        32,
+        TRUE,
+        1,
+        'biblio.record_entry.print',
+        'biblio.format.record_entry.print',
+        'NOOP_True',
+        'ProcessTemplate',
+        'DeleteTempBiblioBucket',
+        'DeleteTempBiblioBucket',
+        'owner',
+        'print-on-demand',
+$$
+[%- USE date -%]
+<div>
+    <style> li { padding: 8px; margin 5px; }</style>
+    <ol>
+    [% FOR cbreb IN target %]
+    [% FOR cbrebi IN cbreb.items %]
+        <li>Bib ID# [% cbrebi.target_biblio_record_entry.id %] ISBN: [% crebi.target_biblio_record_entry.simple_record.isbn %]<br />
+            Title: [% cbrebi.target_biblio_record_entry.simple_record.title %]<br />
+            Author: [% cbrebi.target_biblio_record_entry.simple_record.author %]<br />
+            Publication Year: [% cbrebi.target_biblio_record_entry.simple_record.pubdate %]
+        </li>
+    [% END %]
+    [% END %]
+    </ol>
+</div>
+$$
+    )
+;
+
+INSERT INTO action_trigger.environment (
+        event_def,
+        path
+    ) VALUES -- for fleshing cbreb objects
+         ( 31, 'owner' )
+        ,( 31, 'items' )
+        ,( 31, 'items.target_biblio_record_entry' )
+        ,( 31, 'items.target_biblio_record_entry.simple_record' )
+        ,( 31, 'items.target_biblio_record_entry.call_numbers' )
+        ,( 31, 'items.target_biblio_record_entry.fixed_fields' )
+        ,( 31, 'items.target_biblio_record_entry.notes' )
+        ,( 31, 'items.target_biblio_record_entry.full_record_entries' )
+        ,( 32, 'owner' )
+        ,( 32, 'items' )
+        ,( 32, 'items.target_biblio_record_entry' )
+        ,( 32, 'items.target_biblio_record_entry.simple_record' )
+        ,( 32, 'items.target_biblio_record_entry.call_numbers' )
+        ,( 32, 'items.target_biblio_record_entry.fixed_fields' )
+        ,( 32, 'items.target_biblio_record_entry.notes' )
+        ,( 32, 'items.target_biblio_record_entry.full_record_entries' )
+;
+
+INSERT INTO action_trigger.environment (
+        event_def,
+        path
+    ) VALUES -- for fleshing mp objects
+         ( 29, 'credit_card_payment')
+        ,( 29, 'xact.billings')
+        ,( 29, 'xact.billings.btype')
+        ,( 30, 'credit_card_payment')
+        ,( 30, 'xact.billings')
+        ,( 30, 'xact.billings.btype')
+;
+
+INSERT INTO action_trigger.hook (key,core_type,description,passive) VALUES 
+    (   'circ.format.missing_pieces.slip.print',
+        'circ', 
+        oils_i18n_gettext(
+            'circ.format.missing_pieces.slip.print',
+            'A missing pieces slip needs to be formatted for printing.',
+            'ath',
+            'description'
+        ), 
+        FALSE
+    )
+    ,(  'circ.format.missing_pieces.letter.print',
+        'circ', 
+        oils_i18n_gettext(
+            'circ.format.missing_pieces.letter.print',
+            'A missing pieces patron letter needs to be formatted for printing.',
+            'ath',
+            'description'
+        ), 
+        FALSE
+    )
+;
+
+INSERT INTO action_trigger.event_definition (
+        id,
+        active,
+        owner,
+        name,
+        hook,
+        validator,
+        reactor,
+        group_field,
+        granularity,
+        template
+    ) VALUES (
+        33,
+        TRUE,
+        1,
+        'circ.missing_pieces.slip.print',
+        'circ.format.missing_pieces.slip.print',
+        'NOOP_True',
+        'ProcessTemplate',
+        'usr',
+        'print-on-demand',
+$$
+[%- USE date -%]
+[%- SET user = target.0.usr -%]
+<div style="li { padding: 8px; margin 5px; }">
+    <div>[% date.format %]</div><br/>
+    Missing pieces for:
+    <ol>
+    [% FOR circ IN target %]
+        <li>Barcode: [% circ.target_copy.barcode %] Transaction ID: [% circ.id %] Due: [% circ.due_date.format %]<br />
+            [% helpers.get_copy_bib_basics(circ.target_copy.id).title %]
+        </li>
+    [% END %]
+    </ol>
+</div>
+$$
+    )
+    ,(
+        34,
+        TRUE,
+        1,
+        'circ.missing_pieces.letter.print',
+        'circ.format.missing_pieces.letter.print',
+        'NOOP_True',
+        'ProcessTemplate',
+        'usr',
+        'print-on-demand',
+$$
+[%- USE date -%]
+[%- SET user = target.0.usr -%]
+[% date.format %]
+Dear [% user.prefix %] [% user.first_given_name %] [% user.family_name %],
+
+We are missing pieces for the following returned items:
+[% FOR circ IN target %]
+Barcode: [% circ.target_copy.barcode %] Transaction ID: [% circ.id %] Due: [% circ.due_date.format %]
+[% helpers.get_copy_bib_basics(circ.target_copy.id).title %]
+[% END %]
+
+Please return these pieces as soon as possible.
+
+Thanks!
+
+Library Staff
+$$
+    )
+;
+
+INSERT INTO action_trigger.environment (
+        event_def,
+        path
+    ) VALUES -- for fleshing circ objects
+         ( 33, 'usr')
+        ,( 33, 'target_copy')
+        ,( 33, 'target_copy.circ_lib')
+        ,( 33, 'target_copy.circ_lib.mailing_address')
+        ,( 33, 'target_copy.circ_lib.billing_address')
+        ,( 33, 'target_copy.call_number')
+        ,( 33, 'target_copy.call_number.owning_lib')
+        ,( 33, 'target_copy.call_number.owning_lib.mailing_address')
+        ,( 33, 'target_copy.call_number.owning_lib.billing_address')
+        ,( 33, 'circ_lib')
+        ,( 33, 'circ_lib.mailing_address')
+        ,( 33, 'circ_lib.billing_address')
+        ,( 34, 'usr')
+        ,( 34, 'target_copy')
+        ,( 34, 'target_copy.circ_lib')
+        ,( 34, 'target_copy.circ_lib.mailing_address')
+        ,( 34, 'target_copy.circ_lib.billing_address')
+        ,( 34, 'target_copy.call_number')
+        ,( 34, 'target_copy.call_number.owning_lib')
+        ,( 34, 'target_copy.call_number.owning_lib.mailing_address')
+        ,( 34, 'target_copy.call_number.owning_lib.billing_address')
+        ,( 34, 'circ_lib')
+        ,( 34, 'circ_lib.mailing_address')
+        ,( 34, 'circ_lib.billing_address')
+;
+
+INSERT INTO action_trigger.hook (key,core_type,description,passive) 
+    VALUES (   
+        'ahr.format.pull_list',
+        'ahr', 
+        oils_i18n_gettext(
+            'ahr.format.pull_list',
+            'Format holds pull list for printing',
+            'ath',
+            'description'
+        ), 
+        FALSE
+    );
+
+INSERT INTO action_trigger.event_definition (
+        id,
+        active,
+        owner,
+        name,
+        hook,
+        validator,
+        reactor,
+        group_field,
+        granularity,
+        template
+    ) VALUES (
+        35,
+        TRUE,
+        1,
+        'Holds Pull List',
+        'ahr.format.pull_list',
+        'NOOP_True',
+        'ProcessTemplate',
+        'pickup_lib',
+        'print-on-demand',
+$$
+[%- USE date -%]
+<style>
+    table { border-collapse: collapse; } 
+    td { padding: 5px; border-bottom: 1px solid #888; } 
+    th { font-weight: bold; }
+</style>
+[% 
+    # Sort the holds into copy-location buckets
+    # In the main print loop, sort each bucket by callnumber before printing
+    SET holds_list = [];
+    SET loc_data = [];
+    SET current_location = target.0.current_copy.location.id;
+    FOR hold IN target;
+        IF current_location != hold.current_copy.location.id;
+            SET current_location = hold.current_copy.location.id;
+            holds_list.push(loc_data);
+            SET loc_data = [];
+        END;
+        SET hold_data = {
+            'hold' => hold,
+            'callnumber' => hold.current_copy.call_number.label
+        };
+        loc_data.push(hold_data);
+    END;
+    holds_list.push(loc_data)
+%]
+<table>
+    <thead>
+        <tr>
+            <th>Title</th>
+            <th>Author</th>
+            <th>Shelving Location</th>
+            <th>Call Number</th>
+            <th>Barcode</th>
+            <th>Patron</th>
+        </tr>
+    </thead>
+    <tbody>
+    [% FOR loc_data IN holds_list  %]
+        [% FOR hold_data IN loc_data.sort('callnumber') %]
+            [% 
+                SET hold = hold_data.hold;
+                SET copy_data = helpers.get_copy_bib_basics(hold.current_copy.id);
+            %]
+            <tr>
+                <td>[% copy_data.title | truncate %]</td>
+                <td>[% copy_data.author | truncate %]</td>
+                <td>[% hold.current_copy.location.name %]</td>
+                <td>[% hold.current_copy.call_number.label %]</td>
+                <td>[% hold.current_copy.barcode %]</td>
+                <td>[% hold.usr.card.barcode %]</td>
+            </tr>
+        [% END %]
+    [% END %]
+    <tbody>
+</table>
+$$
+);
+
+INSERT INTO action_trigger.environment (
+        event_def,
+        path
+    ) VALUES
+        (35, 'current_copy.location'),
+        (35, 'current_copy.call_number'),
+        (35, 'usr.card'),
+        (35, 'pickup_lib')
+;
+
+INSERT INTO action_trigger.validator (module, description) VALUES ( 
+    'HoldIsCancelled', 
+    oils_i18n_gettext( 
+        'HoldIsCancelled', 
+        'Check whether a hold request is cancelled.', 
+        'atval', 
+        'description' 
+    ) 
+);
+
+-- Create the query schema, and the tables and views therein
+
+DROP SCHEMA IF EXISTS sql CASCADE;
+DROP SCHEMA IF EXISTS query CASCADE;
+
+CREATE SCHEMA query;
+
+CREATE TABLE query.datatype (
+	id              SERIAL            PRIMARY KEY,
+	datatype_name   TEXT              NOT NULL UNIQUE,
+	is_numeric      BOOL              NOT NULL DEFAULT FALSE,
+	is_composite    BOOL              NOT NULL DEFAULT FALSE,
+	CONSTRAINT qdt_comp_not_num CHECK
+	( is_numeric IS FALSE OR is_composite IS FALSE )
+);
+
+-- Define the most common datatypes in query.datatype.  Note that none of
+-- these stock datatypes specifies a width or precision.
+
+-- Also: set the sequence for query.datatype to 1000, leaving plenty of
+-- room for more stock datatypes if we ever want to add them.
+
+SELECT setval( 'query.datatype_id_seq', 1000 );
+
+INSERT INTO query.datatype (id, datatype_name, is_numeric )
+  VALUES (1, 'SMALLINT', true);
+ 
+INSERT INTO query.datatype (id, datatype_name, is_numeric )
+  VALUES (2, 'INTEGER', true);
+ 
+INSERT INTO query.datatype (id, datatype_name, is_numeric )
+  VALUES (3, 'BIGINT', true);
+ 
+INSERT INTO query.datatype (id, datatype_name, is_numeric )
+  VALUES (4, 'DECIMAL', true);
+ 
+INSERT INTO query.datatype (id, datatype_name, is_numeric )
+  VALUES (5, 'NUMERIC', true);
+ 
+INSERT INTO query.datatype (id, datatype_name, is_numeric )
+  VALUES (6, 'REAL', true);
+ 
+INSERT INTO query.datatype (id, datatype_name, is_numeric )
+  VALUES (7, 'DOUBLE PRECISION', true);
+ 
+INSERT INTO query.datatype (id, datatype_name, is_numeric )
+  VALUES (8, 'SERIAL', true);
+ 
+INSERT INTO query.datatype (id, datatype_name, is_numeric )
+  VALUES (9, 'BIGSERIAL', true);
+ 
+INSERT INTO query.datatype (id, datatype_name, is_numeric )
+  VALUES (10, 'MONEY', false);
+ 
+INSERT INTO query.datatype (id, datatype_name, is_numeric )
+  VALUES (11, 'VARCHAR', false);
+ 
+INSERT INTO query.datatype (id, datatype_name, is_numeric )
+  VALUES (12, 'CHAR', false);
+ 
+INSERT INTO query.datatype (id, datatype_name, is_numeric )
+  VALUES (13, 'TEXT', false);
+ 
+INSERT INTO query.datatype (id, datatype_name, is_numeric )
+  VALUES (14, '"char"', false);
+ 
+INSERT INTO query.datatype (id, datatype_name, is_numeric )
+  VALUES (15, 'NAME', false);
+ 
+INSERT INTO query.datatype (id, datatype_name, is_numeric )
+  VALUES (16, 'BYTEA', false);
+ 
+INSERT INTO query.datatype (id, datatype_name, is_numeric )
+  VALUES (17, 'TIMESTAMP WITHOUT TIME ZONE', false);
+ 
+INSERT INTO query.datatype (id, datatype_name, is_numeric )
+  VALUES (18, 'TIMESTAMP WITH TIME ZONE', false);
+ 
+INSERT INTO query.datatype (id, datatype_name, is_numeric )
+  VALUES (19, 'DATE', false);
+ 
+INSERT INTO query.datatype (id, datatype_name, is_numeric )
+  VALUES (20, 'TIME WITHOUT TIME ZONE', false);
+ 
+INSERT INTO query.datatype (id, datatype_name, is_numeric )
+  VALUES (21, 'TIME WITH TIME ZONE', false);
+ 
+INSERT INTO query.datatype (id, datatype_name, is_numeric )
+  VALUES (22, 'INTERVAL', false);
+ 
+INSERT INTO query.datatype (id, datatype_name, is_numeric )
+  VALUES (23, 'BOOLEAN', false);
+ 
+CREATE TABLE query.subfield (
+	id              SERIAL            PRIMARY KEY,
+	composite_type  INT               NOT NULL
+	                                  REFERENCES query.datatype(id)
+	                                  ON DELETE CASCADE
+	                                  DEFERRABLE INITIALLY DEFERRED,
+	seq_no          INT               NOT NULL
+	                                  CONSTRAINT qsf_pos_seq_no
+	                                  CHECK( seq_no > 0 ),
+	subfield_type   INT               NOT NULL
+	                                  REFERENCES query.datatype(id)
+	                                  DEFERRABLE INITIALLY DEFERRED,
+	CONSTRAINT qsf_datatype_seq_no UNIQUE (composite_type, seq_no)
+);
+
+CREATE TABLE query.function_sig (
+	id              SERIAL            PRIMARY KEY,
+	function_name   TEXT              NOT NULL,
+	return_type     INT               REFERENCES query.datatype(id)
+	                                  DEFERRABLE INITIALLY DEFERRED,
+	is_aggregate    BOOL              NOT NULL DEFAULT FALSE,
+	CONSTRAINT qfd_rtn_or_aggr CHECK
+	( return_type IS NULL OR is_aggregate = FALSE )
+);
+
+CREATE INDEX query_function_sig_name_idx 
+	ON query.function_sig (function_name);
+
+CREATE TABLE query.function_param_def (
+	id              SERIAL            PRIMARY KEY,
+	function_id     INT               NOT NULL
+	                                  REFERENCES query.function_sig( id )
+	                                  ON DELETE CASCADE
+	                                  DEFERRABLE INITIALLY DEFERRED,
+	seq_no          INT               NOT NULL
+	                                  CONSTRAINT qfpd_pos_seq_no CHECK
+	                                  ( seq_no > 0 ),
+	datatype        INT               NOT NULL
+	                                  REFERENCES query.datatype( id )
+	                                  DEFERRABLE INITIALLY DEFERRED,
+	CONSTRAINT qfpd_function_param_seq UNIQUE (function_id, seq_no)
+);
+
+CREATE TABLE  query.stored_query (
+	id            SERIAL         PRIMARY KEY,
+	type          TEXT           NOT NULL CONSTRAINT query_type CHECK
+	                             ( type IN ( 'SELECT', 'UNION', 'INTERSECT', 'EXCEPT' ) ),
+	use_all       BOOLEAN        NOT NULL DEFAULT FALSE,
+	use_distinct  BOOLEAN        NOT NULL DEFAULT FALSE,
+	from_clause   INT            , --REFERENCES query.from_clause
+	                             --DEFERRABLE INITIALLY DEFERRED,
+	where_clause  INT            , --REFERENCES query.expression
+	                             --DEFERRABLE INITIALLY DEFERRED,
+	having_clause INT            , --REFERENCES query.expression
+	                             --DEFERRABLE INITIALLY DEFERRED
+	limit_count   INT            , --REFERENCES query.expression( id )
+	                             --DEFERRABLE INITIALLY DEFERRED,
+	offset_count  INT            --REFERENCES query.expression( id )
+	                             --DEFERRABLE INITIALLY DEFERRED
+);
+
+-- (Foreign keys to be defined later after other tables are created)
+
+CREATE TABLE query.query_sequence (
+	id              SERIAL            PRIMARY KEY,
+	parent_query    INT               NOT NULL
+	                                  REFERENCES query.stored_query
+									  ON DELETE CASCADE
+									  DEFERRABLE INITIALLY DEFERRED,
+	seq_no          INT               NOT NULL,
+	child_query     INT               NOT NULL
+	                                  REFERENCES query.stored_query
+									  ON DELETE CASCADE
+									  DEFERRABLE INITIALLY DEFERRED,
+	CONSTRAINT query_query_seq UNIQUE( parent_query, seq_no )
+);
+
+CREATE TABLE query.bind_variable (
+	name          TEXT             PRIMARY KEY,
+	type          TEXT             NOT NULL
+		                           CONSTRAINT bind_variable_type CHECK
+		                           ( type in ( 'string', 'number', 'string_list', 'number_list' )),
+	description   TEXT             NOT NULL,
+	default_value TEXT,            -- to be encoded in JSON
+	label         TEXT             NOT NULL
+);
+
+CREATE TABLE query.expression (
+	id            SERIAL        PRIMARY KEY,
+	type          TEXT          NOT NULL CONSTRAINT expression_type CHECK
+	                            ( type IN (
+                                    'xbet',    -- between
+                                    'xbind',   -- bind variable
+                                    'xbool',   -- boolean
+                                    'xcase',   -- case
+                                    'xcast',   -- cast
+                                    'xcol',    -- column
+                                    'xex',     -- exists
+                                    'xfunc',   -- function
+                                    'xin',     -- in
+                                    'xisnull', -- is null
+                                    'xnull',   -- null
+                                    'xnum',    -- number
+                                    'xop',     -- operator
+                                    'xser',    -- series
+                                    'xstr',    -- string
+                                    'xsubq'    -- subquery
+								) ),
+	parenthesize  BOOL          NOT NULL DEFAULT FALSE,
+	parent_expr   INT           REFERENCES query.expression
+	                            ON DELETE CASCADE
+	                            DEFERRABLE INITIALLY DEFERRED,
+	seq_no        INT           NOT NULL DEFAULT 1,
+	literal       TEXT,
+	table_alias   TEXT,
+	column_name   TEXT,
+	left_operand  INT           REFERENCES query.expression
+	                            DEFERRABLE INITIALLY DEFERRED,
+	operator      TEXT,
+	right_operand INT           REFERENCES query.expression
+	                            DEFERRABLE INITIALLY DEFERRED,
+	function_id   INT           REFERENCES query.function_sig
+	                            DEFERRABLE INITIALLY DEFERRED,
+	subquery      INT           REFERENCES query.stored_query
+	                            DEFERRABLE INITIALLY DEFERRED,
+	cast_type     INT           REFERENCES query.datatype
+	                            DEFERRABLE INITIALLY DEFERRED,
+	negate        BOOL          NOT NULL DEFAULT FALSE,
+	bind_variable TEXT          REFERENCES query.bind_variable
+		                        DEFERRABLE INITIALLY DEFERRED
+);
+
+CREATE UNIQUE INDEX query_expr_parent_seq
+	ON query.expression( parent_expr, seq_no )
+	WHERE parent_expr IS NOT NULL;
+
+-- Due to some circular references, the following foreign key definitions
+-- had to be deferred until query.expression existed:
+
+ALTER TABLE query.stored_query
+	ADD FOREIGN KEY ( where_clause )
+	REFERENCES query.expression( id )
+	DEFERRABLE INITIALLY DEFERRED;
+
+ALTER TABLE query.stored_query
+	ADD FOREIGN KEY ( having_clause )
+	REFERENCES query.expression( id )
+	DEFERRABLE INITIALLY DEFERRED;
+
+ALTER TABLE query.stored_query
+    ADD FOREIGN KEY ( limit_count )
+    REFERENCES query.expression( id )
+    DEFERRABLE INITIALLY DEFERRED;
+
+ALTER TABLE query.stored_query
+    ADD FOREIGN KEY ( offset_count )
+    REFERENCES query.expression( id )
+    DEFERRABLE INITIALLY DEFERRED;
+
+CREATE TABLE query.case_branch (
+	id            SERIAL        PRIMARY KEY,
+	parent_expr   INT           NOT NULL REFERENCES query.expression
+	                            ON DELETE CASCADE
+	                            DEFERRABLE INITIALLY DEFERRED,
+	seq_no        INT           NOT NULL,
+	condition     INT           REFERENCES query.expression
+	                            DEFERRABLE INITIALLY DEFERRED,
+	result        INT           NOT NULL REFERENCES query.expression
+	                            DEFERRABLE INITIALLY DEFERRED,
+	CONSTRAINT case_branch_parent_seq UNIQUE (parent_expr, seq_no)
+);
+
+CREATE TABLE query.from_relation (
+	id               SERIAL        PRIMARY KEY,
+	type             TEXT          NOT NULL CONSTRAINT relation_type CHECK (
+	                                   type IN ( 'RELATION', 'SUBQUERY', 'FUNCTION' ) ),
+	table_name       TEXT,
+	class_name       TEXT,
+	subquery         INT           REFERENCES query.stored_query,
+	function_call    INT           REFERENCES query.expression,
+	table_alias      TEXT,
+	parent_relation  INT           REFERENCES query.from_relation
+	                               ON DELETE CASCADE
+	                               DEFERRABLE INITIALLY DEFERRED,
+	seq_no           INT           NOT NULL DEFAULT 1,
+	join_type        TEXT          CONSTRAINT good_join_type CHECK (
+	                                   join_type IS NULL OR join_type IN
+	                                   ( 'INNER', 'LEFT', 'RIGHT', 'FULL' )
+	                               ),
+	on_clause        INT           REFERENCES query.expression
+	                               DEFERRABLE INITIALLY DEFERRED,
+	CONSTRAINT join_or_core CHECK (
+        ( parent_relation IS NULL AND join_type IS NULL
+          AND on_clause IS NULL )
+        OR
+        ( parent_relation IS NOT NULL AND join_type IS NOT NULL
+          AND on_clause IS NOT NULL )
+	)
+);
+
+CREATE UNIQUE INDEX from_parent_seq
+	ON query.from_relation( parent_relation, seq_no )
+	WHERE parent_relation IS NOT NULL;
+
+-- The following foreign key had to be deferred until
+-- query.from_relation existed
+
+ALTER TABLE query.stored_query
+	ADD FOREIGN KEY (from_clause)
+	REFERENCES query.from_relation
+	DEFERRABLE INITIALLY DEFERRED;
+
+CREATE TABLE query.record_column (
+	id            SERIAL            PRIMARY KEY,
+	from_relation INT               NOT NULL REFERENCES query.from_relation
+	                                ON DELETE CASCADE
+	                                DEFERRABLE INITIALLY DEFERRED,
+	seq_no        INT               NOT NULL,
+	column_name   TEXT              NOT NULL,
+	column_type   INT               NOT NULL REFERENCES query.datatype
+	                                ON DELETE CASCADE
+									DEFERRABLE INITIALLY DEFERRED,
+	CONSTRAINT column_sequence UNIQUE (from_relation, seq_no)
+);
+
+CREATE TABLE query.select_item (
+	id               SERIAL         PRIMARY KEY,
+	stored_query     INT            NOT NULL REFERENCES query.stored_query
+	                                ON DELETE CASCADE
+	                                DEFERRABLE INITIALLY DEFERRED,
+	seq_no           INT            NOT NULL,
+	expression       INT            NOT NULL REFERENCES query.expression
+	                                DEFERRABLE INITIALLY DEFERRED,
+	column_alias     TEXT,
+	grouped_by       BOOL           NOT NULL DEFAULT FALSE,
+	CONSTRAINT select_sequence UNIQUE( stored_query, seq_no )
+);
+
+CREATE TABLE query.order_by_item (
+	id               SERIAL         PRIMARY KEY,
+	stored_query     INT            NOT NULL REFERENCES query.stored_query
+	                                ON DELETE CASCADE
+	                                DEFERRABLE INITIALLY DEFERRED,
+	seq_no           INT            NOT NULL,
+	expression       INT            NOT NULL REFERENCES query.expression
+	                                ON DELETE CASCADE
+	                                DEFERRABLE INITIALLY DEFERRED,
+	CONSTRAINT order_by_sequence UNIQUE( stored_query, seq_no )
+);
+
+------------------------------------------------------------
+-- Create updatable views for different kinds of expressions
+------------------------------------------------------------
+
+-- Create updatable view for BETWEEN expressions
+
+CREATE OR REPLACE VIEW query.expr_xbet AS
+    SELECT
+		id,
+		parenthesize,
+		parent_expr,
+		seq_no,
+		left_operand,
+		negate
+    FROM
+        query.expression
+    WHERE
+        type = 'xbet';
+
+CREATE OR REPLACE RULE query_expr_xbet_insert_rule AS
+    ON INSERT TO query.expr_xbet
+    DO INSTEAD
+    INSERT INTO query.expression (
+		id,
+		type,
+		parenthesize,
+		parent_expr,
+		seq_no,
+		left_operand,
+		negate
+    ) VALUES (
+        COALESCE(NEW.id, NEXTVAL('query.expression_id_seq'::REGCLASS)),
+        'xbet',
+        COALESCE(NEW.parenthesize, FALSE),
+        NEW.parent_expr,
+        COALESCE(NEW.seq_no, 1),
+		NEW.left_operand,
+		COALESCE(NEW.negate, false)
+    );
+
+CREATE OR REPLACE RULE query_expr_xbet_update_rule AS
+    ON UPDATE TO query.expr_xbet
+    DO INSTEAD
+    UPDATE query.expression SET
+        id = NEW.id,
+        parenthesize = NEW.parenthesize,
+        parent_expr = NEW.parent_expr,
+        seq_no = NEW.seq_no,
+		left_operand = NEW.left_operand,
+		negate = NEW.negate
+    WHERE
+        id = OLD.id;
+
+CREATE OR REPLACE RULE query_expr_xbet_delete_rule AS
+    ON DELETE TO query.expr_xbet
+    DO INSTEAD
+    DELETE FROM query.expression WHERE id = OLD.id;
+
+-- Create updatable view for bind variable expressions
+
+CREATE OR REPLACE VIEW query.expr_xbind AS
+    SELECT
+		id,
+		parenthesize,
+		parent_expr,
+		seq_no,
+		bind_variable
+    FROM
+        query.expression
+    WHERE
+        type = 'xbind';
+
+CREATE OR REPLACE RULE query_expr_xbind_insert_rule AS
+    ON INSERT TO query.expr_xbind
+    DO INSTEAD
+    INSERT INTO query.expression (
+		id,
+		type,
+		parenthesize,
+		parent_expr,
+		seq_no,
+		bind_variable
+    ) VALUES (
+        COALESCE(NEW.id, NEXTVAL('query.expression_id_seq'::REGCLASS)),
+        'xbind',
+        COALESCE(NEW.parenthesize, FALSE),
+        NEW.parent_expr,
+        COALESCE(NEW.seq_no, 1),
+		NEW.bind_variable
+    );
+
+CREATE OR REPLACE RULE query_expr_xbind_update_rule AS
+    ON UPDATE TO query.expr_xbind
+    DO INSTEAD
+    UPDATE query.expression SET
+        id = NEW.id,
+        parenthesize = NEW.parenthesize,
+        parent_expr = NEW.parent_expr,
+        seq_no = NEW.seq_no,
+		bind_variable = NEW.bind_variable
+    WHERE
+        id = OLD.id;
+
+CREATE OR REPLACE RULE query_expr_xbind_delete_rule AS
+    ON DELETE TO query.expr_xbind
+    DO INSTEAD
+    DELETE FROM query.expression WHERE id = OLD.id;
+
+-- Create updatable view for boolean expressions
+
+CREATE OR REPLACE VIEW query.expr_xbool AS
+    SELECT
+		id,
+		parenthesize,
+		parent_expr,
+		seq_no,
+		literal,
+		negate
+    FROM
+        query.expression
+    WHERE
+        type = 'xbool';
+
+CREATE OR REPLACE RULE query_expr_xbool_insert_rule AS
+    ON INSERT TO query.expr_xbool
+    DO INSTEAD
+    INSERT INTO query.expression (
+		id,
+		type,
+		parenthesize,
+		parent_expr,
+		seq_no,
+		literal,
+		negate
+    ) VALUES (
+        COALESCE(NEW.id, NEXTVAL('query.expression_id_seq'::REGCLASS)),
+        'xbool',
+        COALESCE(NEW.parenthesize, FALSE),
+        NEW.parent_expr,
+        COALESCE(NEW.seq_no, 1),
+        NEW.literal,
+		COALESCE(NEW.negate, false)
+    );
+
+CREATE OR REPLACE RULE query_expr_xbool_update_rule AS
+    ON UPDATE TO query.expr_xbool
+    DO INSTEAD
+    UPDATE query.expression SET
+        id = NEW.id,
+        parenthesize = NEW.parenthesize,
+        parent_expr = NEW.parent_expr,
+        seq_no = NEW.seq_no,
+        literal = NEW.literal,
+		negate = NEW.negate
+    WHERE
+        id = OLD.id;
+
+CREATE OR REPLACE RULE query_expr_xbool_delete_rule AS
+    ON DELETE TO query.expr_xbool
+    DO INSTEAD
+    DELETE FROM query.expression WHERE id = OLD.id;
+
+-- Create updatable view for CASE expressions
+
+CREATE OR REPLACE VIEW query.expr_xcase AS
+    SELECT
+		id,
+		parenthesize,
+		parent_expr,
+		seq_no,
+		left_operand,
+		negate
+    FROM
+        query.expression
+    WHERE
+        type = 'xcase';
+
+CREATE OR REPLACE RULE query_expr_xcase_insert_rule AS
+    ON INSERT TO query.expr_xcase
+    DO INSTEAD
+    INSERT INTO query.expression (
+		id,
+		type,
+		parenthesize,
+		parent_expr,
+		seq_no,
+		left_operand,
+		negate
+    ) VALUES (
+        COALESCE(NEW.id, NEXTVAL('query.expression_id_seq'::REGCLASS)),
+        'xcase',
+        COALESCE(NEW.parenthesize, FALSE),
+        NEW.parent_expr,
+        COALESCE(NEW.seq_no, 1),
+		NEW.left_operand,
+		COALESCE(NEW.negate, false)
+    );
+
+CREATE OR REPLACE RULE query_expr_xcase_update_rule AS
+    ON UPDATE TO query.expr_xcase
+    DO INSTEAD
+    UPDATE query.expression SET
+        id = NEW.id,
+        parenthesize = NEW.parenthesize,
+        parent_expr = NEW.parent_expr,
+        seq_no = NEW.seq_no,
+		left_operand = NEW.left_operand,
+		negate = NEW.negate
+    WHERE
+        id = OLD.id;
+
+CREATE OR REPLACE RULE query_expr_xcase_delete_rule AS
+    ON DELETE TO query.expr_xcase
+    DO INSTEAD
+    DELETE FROM query.expression WHERE id = OLD.id;
+
+-- Create updatable view for cast expressions
+
+CREATE OR REPLACE VIEW query.expr_xcast AS
+    SELECT
+		id,
+		parenthesize,
+		parent_expr,
+		seq_no,
+		left_operand,
+		cast_type,
+		negate
+    FROM
+        query.expression
+    WHERE
+        type = 'xcast';
+
+CREATE OR REPLACE RULE query_expr_xcast_insert_rule AS
+    ON INSERT TO query.expr_xcast
+    DO INSTEAD
+    INSERT INTO query.expression (
+        id,
+        type,
+        parenthesize,
+        parent_expr,
+        seq_no,
+        left_operand,
+        cast_type,
+        negate
+    ) VALUES (
+        COALESCE(NEW.id, NEXTVAL('query.expression_id_seq'::REGCLASS)),
+        'xcast',
+        COALESCE(NEW.parenthesize, FALSE),
+        NEW.parent_expr,
+        COALESCE(NEW.seq_no, 1),
+        NEW.left_operand,
+        NEW.cast_type,
+        COALESCE(NEW.negate, false)
+    );
+
+CREATE OR REPLACE RULE query_expr_xcast_update_rule AS
+    ON UPDATE TO query.expr_xcast
+    DO INSTEAD
+    UPDATE query.expression SET
+        id = NEW.id,
+        parenthesize = NEW.parenthesize,
+        parent_expr = NEW.parent_expr,
+        seq_no = NEW.seq_no,
+		left_operand = NEW.left_operand,
+		cast_type = NEW.cast_type,
+		negate = NEW.negate
+    WHERE
+        id = OLD.id;
+
+CREATE OR REPLACE RULE query_expr_xcast_delete_rule AS
+    ON DELETE TO query.expr_xcast
+    DO INSTEAD
+    DELETE FROM query.expression WHERE id = OLD.id;
+
+-- Create updatable view for column expressions
+
+CREATE OR REPLACE VIEW query.expr_xcol AS
+    SELECT
+		id,
+		parenthesize,
+		parent_expr,
+		seq_no,
+		table_alias,
+		column_name,
+		negate
+    FROM
+        query.expression
+    WHERE
+        type = 'xcol';
+
+CREATE OR REPLACE RULE query_expr_xcol_insert_rule AS
+    ON INSERT TO query.expr_xcol
+    DO INSTEAD
+    INSERT INTO query.expression (
+		id,
+		type,
+		parenthesize,
+		parent_expr,
+		seq_no,
+		table_alias,
+		column_name,
+		negate
+    ) VALUES (
+        COALESCE(NEW.id, NEXTVAL('query.expression_id_seq'::REGCLASS)),
+        'xcol',
+        COALESCE(NEW.parenthesize, FALSE),
+        NEW.parent_expr,
+        COALESCE(NEW.seq_no, 1),
+		NEW.table_alias,
+		NEW.column_name,
+		COALESCE(NEW.negate, false)
+    );
+
+CREATE OR REPLACE RULE query_expr_xcol_update_rule AS
+    ON UPDATE TO query.expr_xcol
+    DO INSTEAD
+    UPDATE query.expression SET
+        id = NEW.id,
+        parenthesize = NEW.parenthesize,
+        parent_expr = NEW.parent_expr,
+        seq_no = NEW.seq_no,
+		table_alias = NEW.table_alias,
+		column_name = NEW.column_name,
+		negate = NEW.negate
+    WHERE
+        id = OLD.id;
+
+CREATE OR REPLACE RULE query_expr_xcol_delete_rule AS
+    ON DELETE TO query.expr_xcol
+    DO INSTEAD
+    DELETE FROM query.expression WHERE id = OLD.id;
+
+-- Create updatable view for EXISTS expressions
+
+CREATE OR REPLACE VIEW query.expr_xex AS
+    SELECT
+		id,
+		parenthesize,
+		parent_expr,
+		seq_no,
+		subquery,
+		negate
+    FROM
+        query.expression
+    WHERE
+        type = 'xex';
+
+CREATE OR REPLACE RULE query_expr_xex_insert_rule AS
+    ON INSERT TO query.expr_xex
+    DO INSTEAD
+    INSERT INTO query.expression (
+		id,
+		type,
+		parenthesize,
+		parent_expr,
+		seq_no,
+		subquery,
+		negate
+    ) VALUES (
+        COALESCE(NEW.id, NEXTVAL('query.expression_id_seq'::REGCLASS)),
+        'xex',
+        COALESCE(NEW.parenthesize, FALSE),
+        NEW.parent_expr,
+        COALESCE(NEW.seq_no, 1),
+		NEW.subquery,
+		COALESCE(NEW.negate, false)
+    );
+
+CREATE OR REPLACE RULE query_expr_xex_update_rule AS
+    ON UPDATE TO query.expr_xex
+    DO INSTEAD
+    UPDATE query.expression SET
+        id = NEW.id,
+        parenthesize = NEW.parenthesize,
+        parent_expr = NEW.parent_expr,
+        seq_no = NEW.seq_no,
+		subquery = NEW.subquery,
+		negate = NEW.negate
+    WHERE
+        id = OLD.id;
+
+CREATE OR REPLACE RULE query_expr_xex_delete_rule AS
+    ON DELETE TO query.expr_xex
+    DO INSTEAD
+    DELETE FROM query.expression WHERE id = OLD.id;
+
+-- Create updatable view for function call expressions
+
+CREATE OR REPLACE VIEW query.expr_xfunc AS
+    SELECT
+        id,
+        parenthesize,
+        parent_expr,
+        seq_no,
+        column_name,
+        function_id,
+        negate
+    FROM
+        query.expression
+    WHERE
+        type = 'xfunc';
+
+CREATE OR REPLACE RULE query_expr_xfunc_insert_rule AS
+    ON INSERT TO query.expr_xfunc
+    DO INSTEAD
+    INSERT INTO query.expression (
+        id,
+        type,
+        parenthesize,
+        parent_expr,
+        seq_no,
+        column_name,
+        function_id,
+        negate
+    ) VALUES (
+        COALESCE(NEW.id, NEXTVAL('query.expression_id_seq'::REGCLASS)),
+        'xfunc',
+        COALESCE(NEW.parenthesize, FALSE),
+        NEW.parent_expr,
+        COALESCE(NEW.seq_no, 1),
+        NEW.column_name,
+        NEW.function_id,
+        COALESCE(NEW.negate, false)
+    );
+
+CREATE OR REPLACE RULE query_expr_xfunc_update_rule AS
+    ON UPDATE TO query.expr_xfunc
+    DO INSTEAD
+    UPDATE query.expression SET
+        id = NEW.id,
+        parenthesize = NEW.parenthesize,
+        parent_expr = NEW.parent_expr,
+        seq_no = NEW.seq_no,
+        column_name = NEW.column_name,
+        function_id = NEW.function_id,
+        negate = NEW.negate
+    WHERE
+        id = OLD.id;
+
+CREATE OR REPLACE RULE query_expr_xfunc_delete_rule AS
+    ON DELETE TO query.expr_xfunc
+    DO INSTEAD
+    DELETE FROM query.expression WHERE id = OLD.id;
+
+-- Create updatable view for IN expressions
+
+CREATE OR REPLACE VIEW query.expr_xin AS
+    SELECT
+		id,
+		parenthesize,
+		parent_expr,
+		seq_no,
+		left_operand,
+		subquery,
+		negate
+    FROM
+        query.expression
+    WHERE
+        type = 'xin';
+
+CREATE OR REPLACE RULE query_expr_xin_insert_rule AS
+    ON INSERT TO query.expr_xin
+    DO INSTEAD
+    INSERT INTO query.expression (
+		id,
+		type,
+		parenthesize,
+		parent_expr,
+		seq_no,
+		left_operand,
+		subquery,
+		negate
+    ) VALUES (
+        COALESCE(NEW.id, NEXTVAL('query.expression_id_seq'::REGCLASS)),
+        'xin',
+        COALESCE(NEW.parenthesize, FALSE),
+        NEW.parent_expr,
+        COALESCE(NEW.seq_no, 1),
+		NEW.left_operand,
+		NEW.subquery,
+		COALESCE(NEW.negate, false)
+    );
+
+CREATE OR REPLACE RULE query_expr_xin_update_rule AS
+    ON UPDATE TO query.expr_xin
+    DO INSTEAD
+    UPDATE query.expression SET
+        id = NEW.id,
+        parenthesize = NEW.parenthesize,
+        parent_expr = NEW.parent_expr,
+        seq_no = NEW.seq_no,
+		left_operand = NEW.left_operand,
+		subquery = NEW.subquery,
+		negate = NEW.negate
+    WHERE
+        id = OLD.id;
+
+CREATE OR REPLACE RULE query_expr_xin_delete_rule AS
+    ON DELETE TO query.expr_xin
+    DO INSTEAD
+    DELETE FROM query.expression WHERE id = OLD.id;
+
+-- Create updatable view for IS NULL expressions
+
+CREATE OR REPLACE VIEW query.expr_xisnull AS
+    SELECT
+		id,
+		parenthesize,
+		parent_expr,
+		seq_no,
+		left_operand,
+		negate
+    FROM
+        query.expression
+    WHERE
+        type = 'xisnull';
+
+CREATE OR REPLACE RULE query_expr_xisnull_insert_rule AS
+    ON INSERT TO query.expr_xisnull
+    DO INSTEAD
+    INSERT INTO query.expression (
+		id,
+		type,
+		parenthesize,
+		parent_expr,
+		seq_no,
+		left_operand,
+		negate
+    ) VALUES (
+        COALESCE(NEW.id, NEXTVAL('query.expression_id_seq'::REGCLASS)),
+        'xisnull',
+        COALESCE(NEW.parenthesize, FALSE),
+        NEW.parent_expr,
+        COALESCE(NEW.seq_no, 1),
+		NEW.left_operand,
+		COALESCE(NEW.negate, false)
+    );
+
+CREATE OR REPLACE RULE query_expr_xisnull_update_rule AS
+    ON UPDATE TO query.expr_xisnull
+    DO INSTEAD
+    UPDATE query.expression SET
+        id = NEW.id,
+        parenthesize = NEW.parenthesize,
+        parent_expr = NEW.parent_expr,
+        seq_no = NEW.seq_no,
+		left_operand = NEW.left_operand,
+		negate = NEW.negate
+    WHERE
+        id = OLD.id;
+
+CREATE OR REPLACE RULE query_expr_xisnull_delete_rule AS
+    ON DELETE TO query.expr_xisnull
+    DO INSTEAD
+    DELETE FROM query.expression WHERE id = OLD.id;
+
+-- Create updatable view for NULL expressions
+
+CREATE OR REPLACE VIEW query.expr_xnull AS
+    SELECT
+		id,
+		parenthesize,
+		parent_expr,
+		seq_no,
+		negate
+    FROM
+        query.expression
+    WHERE
+        type = 'xnull';
+
+CREATE OR REPLACE RULE query_expr_xnull_insert_rule AS
+    ON INSERT TO query.expr_xnull
+    DO INSTEAD
+    INSERT INTO query.expression (
+		id,
+		type,
+		parenthesize,
+		parent_expr,
+		seq_no,
+		negate
+    ) VALUES (
+        COALESCE(NEW.id, NEXTVAL('query.expression_id_seq'::REGCLASS)),
+        'xnull',
+        COALESCE(NEW.parenthesize, FALSE),
+        NEW.parent_expr,
+        COALESCE(NEW.seq_no, 1),
+		COALESCE(NEW.negate, false)
+    );
+
+CREATE OR REPLACE RULE query_expr_xnull_update_rule AS
+    ON UPDATE TO query.expr_xnull
+    DO INSTEAD
+    UPDATE query.expression SET
+        id = NEW.id,
+        parenthesize = NEW.parenthesize,
+        parent_expr = NEW.parent_expr,
+        seq_no = NEW.seq_no,
+		negate = NEW.negate
+    WHERE
+        id = OLD.id;
+
+CREATE OR REPLACE RULE query_expr_xnull_delete_rule AS
+    ON DELETE TO query.expr_xnull
+    DO INSTEAD
+    DELETE FROM query.expression WHERE id = OLD.id;
+
+-- Create updatable view for numeric literal expressions
+
+CREATE OR REPLACE VIEW query.expr_xnum AS
+    SELECT
+		id,
+		parenthesize,
+		parent_expr,
+		seq_no,
+		literal
+    FROM
+        query.expression
+    WHERE
+        type = 'xnum';
+
+CREATE OR REPLACE RULE query_expr_xnum_insert_rule AS
+    ON INSERT TO query.expr_xnum
+    DO INSTEAD
+    INSERT INTO query.expression (
+		id,
+		type,
+		parenthesize,
+		parent_expr,
+		seq_no,
+		literal
+    ) VALUES (
+        COALESCE(NEW.id, NEXTVAL('query.expression_id_seq'::REGCLASS)),
+        'xnum',
+        COALESCE(NEW.parenthesize, FALSE),
+        NEW.parent_expr,
+        COALESCE(NEW.seq_no, 1),
+        NEW.literal
+    );
+
+CREATE OR REPLACE RULE query_expr_xnum_update_rule AS
+    ON UPDATE TO query.expr_xnum
+    DO INSTEAD
+    UPDATE query.expression SET
+        id = NEW.id,
+        parenthesize = NEW.parenthesize,
+        parent_expr = NEW.parent_expr,
+        seq_no = NEW.seq_no,
+        literal = NEW.literal
+    WHERE
+        id = OLD.id;
+
+CREATE OR REPLACE RULE query_expr_xnum_delete_rule AS
+    ON DELETE TO query.expr_xnum
+    DO INSTEAD
+    DELETE FROM query.expression WHERE id = OLD.id;
+
+-- Create updatable view for operator expressions
+
+CREATE OR REPLACE VIEW query.expr_xop AS
+    SELECT
+		id,
+		parenthesize,
+		parent_expr,
+		seq_no,
+		left_operand,
+		operator,
+		right_operand,
+		negate
+    FROM
+        query.expression
+    WHERE
+        type = 'xop';
+
+CREATE OR REPLACE RULE query_expr_xop_insert_rule AS
+    ON INSERT TO query.expr_xop
+    DO INSTEAD
+    INSERT INTO query.expression (
+		id,
+		type,
+		parenthesize,
+		parent_expr,
+		seq_no,
+		left_operand,
+		operator,
+		right_operand,
+		negate
+    ) VALUES (
+        COALESCE(NEW.id, NEXTVAL('query.expression_id_seq'::REGCLASS)),
+        'xop',
+        COALESCE(NEW.parenthesize, FALSE),
+        NEW.parent_expr,
+        COALESCE(NEW.seq_no, 1),
+		NEW.left_operand,
+		NEW.operator,
+		NEW.right_operand,
+		COALESCE(NEW.negate, false)
+    );
+
+CREATE OR REPLACE RULE query_expr_xop_update_rule AS
+    ON UPDATE TO query.expr_xop
+    DO INSTEAD
+    UPDATE query.expression SET
+        id = NEW.id,
+        parenthesize = NEW.parenthesize,
+        parent_expr = NEW.parent_expr,
+        seq_no = NEW.seq_no,
+		left_operand = NEW.left_operand,
+		operator = NEW.operator,
+		right_operand = NEW.right_operand,
+		negate = NEW.negate
+    WHERE
+        id = OLD.id;
+
+CREATE OR REPLACE RULE query_expr_xop_delete_rule AS
+    ON DELETE TO query.expr_xop
+    DO INSTEAD
+    DELETE FROM query.expression WHERE id = OLD.id;
+
+-- Create updatable view for series expressions
+-- i.e. series of expressions separated by operators
+
+CREATE OR REPLACE VIEW query.expr_xser AS
+    SELECT
+		id,
+		parenthesize,
+		parent_expr,
+		seq_no,
+		operator,
+		negate
+    FROM
+        query.expression
+    WHERE
+        type = 'xser';
+
+CREATE OR REPLACE RULE query_expr_xser_insert_rule AS
+    ON INSERT TO query.expr_xser
+    DO INSTEAD
+    INSERT INTO query.expression (
+		id,
+		type,
+		parenthesize,
+		parent_expr,
+		seq_no,
+		operator,
+		negate
+    ) VALUES (
+        COALESCE(NEW.id, NEXTVAL('query.expression_id_seq'::REGCLASS)),
+        'xser',
+        COALESCE(NEW.parenthesize, FALSE),
+        NEW.parent_expr,
+        COALESCE(NEW.seq_no, 1),
+		NEW.operator,
+		COALESCE(NEW.negate, false)
+    );
+
+CREATE OR REPLACE RULE query_expr_xser_update_rule AS
+    ON UPDATE TO query.expr_xser
+    DO INSTEAD
+    UPDATE query.expression SET
+        id = NEW.id,
+        parenthesize = NEW.parenthesize,
+        parent_expr = NEW.parent_expr,
+        seq_no = NEW.seq_no,
+		operator = NEW.operator,
+		negate = NEW.negate
+    WHERE
+        id = OLD.id;
+
+CREATE OR REPLACE RULE query_expr_xser_delete_rule AS
+    ON DELETE TO query.expr_xser
+    DO INSTEAD
+    DELETE FROM query.expression WHERE id = OLD.id;
+
+-- Create updatable view for string literal expressions
+
+CREATE OR REPLACE VIEW query.expr_xstr AS
+    SELECT
+        id,
+        parenthesize,
+        parent_expr,
+        seq_no,
+        literal
+    FROM
+        query.expression
+    WHERE
+        type = 'xstr';
+
+CREATE OR REPLACE RULE query_expr_string_insert_rule AS
+    ON INSERT TO query.expr_xstr
+    DO INSTEAD
+    INSERT INTO query.expression (
+        id,
+        type,
+        parenthesize,
+        parent_expr,
+        seq_no,
+        literal
+    ) VALUES (
+        COALESCE(NEW.id, NEXTVAL('query.expression_id_seq'::REGCLASS)),
+        'xstr',
+        COALESCE(NEW.parenthesize, FALSE),
+        NEW.parent_expr,
+        COALESCE(NEW.seq_no, 1),
+        NEW.literal
+    );
+
+CREATE OR REPLACE RULE query_expr_string_update_rule AS
+    ON UPDATE TO query.expr_xstr
+    DO INSTEAD
+    UPDATE query.expression SET
+        id = NEW.id,
+        parenthesize = NEW.parenthesize,
+        parent_expr = NEW.parent_expr,
+        seq_no = NEW.seq_no,
+        literal = NEW.literal
+    WHERE
+        id = OLD.id;
+
+CREATE OR REPLACE RULE query_expr_string_delete_rule AS
+    ON DELETE TO query.expr_xstr
+    DO INSTEAD
+    DELETE FROM query.expression WHERE id = OLD.id;
+
+-- Create updatable view for subquery expressions
+
+CREATE OR REPLACE VIEW query.expr_xsubq AS
+    SELECT
+		id,
+		parenthesize,
+		parent_expr,
+		seq_no,
+		subquery,
+		negate
+    FROM
+        query.expression
+    WHERE
+        type = 'xsubq';
+
+CREATE OR REPLACE RULE query_expr_xsubq_insert_rule AS
+    ON INSERT TO query.expr_xsubq
+    DO INSTEAD
+    INSERT INTO query.expression (
+		id,
+		type,
+		parenthesize,
+		parent_expr,
+		seq_no,
+		subquery,
+		negate
+    ) VALUES (
+        COALESCE(NEW.id, NEXTVAL('query.expression_id_seq'::REGCLASS)),
+        'xsubq',
+        COALESCE(NEW.parenthesize, FALSE),
+        NEW.parent_expr,
+        COALESCE(NEW.seq_no, 1),
+		NEW.subquery,
+		COALESCE(NEW.negate, false)
+    );
+
+CREATE OR REPLACE RULE query_expr_xsubq_update_rule AS
+    ON UPDATE TO query.expr_xsubq
+    DO INSTEAD
+    UPDATE query.expression SET
+        id = NEW.id,
+        parenthesize = NEW.parenthesize,
+        parent_expr = NEW.parent_expr,
+        seq_no = NEW.seq_no,
+		subquery = NEW.subquery,
+		negate = NEW.negate
+    WHERE
+        id = OLD.id;
+
+CREATE OR REPLACE RULE query_expr_xsubq_delete_rule AS
+    ON DELETE TO query.expr_xsubq
+    DO INSTEAD
+    DELETE FROM query.expression WHERE id = OLD.id;
+
+CREATE TABLE action.fieldset (
+    id              SERIAL          PRIMARY KEY,
+    owner           INT             NOT NULL REFERENCES actor.usr (id)
+                                    DEFERRABLE INITIALLY DEFERRED,
+    owning_lib      INT             NOT NULL REFERENCES actor.org_unit (id)
+                                    DEFERRABLE INITIALLY DEFERRED,
+    status          TEXT            NOT NULL
+                                    CONSTRAINT valid_status CHECK ( status in
+                                    ( 'PENDING', 'APPLIED', 'ERROR' )),
+    creation_time   TIMESTAMPTZ     NOT NULL DEFAULT NOW(),
+    scheduled_time  TIMESTAMPTZ,
+    applied_time    TIMESTAMPTZ,
+    classname       TEXT            NOT NULL, -- an IDL class name
+    name            TEXT            NOT NULL,
+    stored_query    INT             REFERENCES query.stored_query (id)
+                                    DEFERRABLE INITIALLY DEFERRED,
+    pkey_value      TEXT,
+    CONSTRAINT lib_name_unique UNIQUE (owning_lib, name),
+    CONSTRAINT fieldset_one_or_the_other CHECK (
+        (stored_query IS NOT NULL AND pkey_value IS NULL) OR
+        (pkey_value IS NOT NULL AND stored_query IS NULL)
+    )
+    -- the CHECK constraint means we can update the fields for a single
+    -- row without all the extra overhead involved in a query
+);
+
+CREATE INDEX action_fieldset_sched_time_idx ON action.fieldset( scheduled_time );
+CREATE INDEX action_owner_idx               ON action.fieldset( owner );
+
+CREATE TABLE action.fieldset_col_val (
+    id              SERIAL  PRIMARY KEY,
+    fieldset        INT     NOT NULL REFERENCES action.fieldset
+                                         ON DELETE CASCADE
+                                         DEFERRABLE INITIALLY DEFERRED,
+    col             TEXT    NOT NULL,  -- "field" from the idl ... the column on the table
+    val             TEXT,              -- value for the column ... NULL means, well, NULL
+    CONSTRAINT fieldset_col_once_per_set UNIQUE (fieldset, col)
+);
+
+CREATE OR REPLACE FUNCTION action.apply_fieldset(
+	fieldset_id IN INT,        -- id from action.fieldset
+	table_name  IN TEXT,       -- table to be updated
+	pkey_name   IN TEXT,       -- name of primary key column in that table
+	query       IN TEXT        -- query constructed by qstore (for query-based
+	                           --    fieldsets only; otherwise null
+)
+RETURNS TEXT AS $$
+DECLARE
+	statement TEXT;
+	fs_status TEXT;
+	fs_pkey_value TEXT;
+	fs_query TEXT;
+	sep CHAR;
+	status_code TEXT;
+	msg TEXT;
+	update_count INT;
+	cv RECORD;
+BEGIN
+	-- Sanity checks
+	IF fieldset_id IS NULL THEN
+		RETURN 'Fieldset ID parameter is NULL';
+	END IF;
+	IF table_name IS NULL THEN
+		RETURN 'Table name parameter is NULL';
+	END IF;
+	IF pkey_name IS NULL THEN
+		RETURN 'Primary key name parameter is NULL';
+	END IF;
+	--
+	statement := 'UPDATE ' || table_name || ' SET';
+	--
+	SELECT
+		status,
+		quote_literal( pkey_value )
+	INTO
+		fs_status,
+		fs_pkey_value
+	FROM
+		action.fieldset
+	WHERE
+		id = fieldset_id;
+	--
+	IF fs_status IS NULL THEN
+		RETURN 'No fieldset found for id = ' || fieldset_id;
+	ELSIF fs_status = 'APPLIED' THEN
+		RETURN 'Fieldset ' || fieldset_id || ' has already been applied';
+	END IF;
+	--
+	sep := '';
+	FOR cv IN
+		SELECT  col,
+				val
+		FROM    action.fieldset_col_val
+		WHERE   fieldset = fieldset_id
+	LOOP
+		statement := statement || sep || ' ' || cv.col
+					 || ' = ' || coalesce( quote_literal( cv.val ), 'NULL' );
+		sep := ',';
+	END LOOP;
+	--
+	IF sep = '' THEN
+		RETURN 'Fieldset ' || fieldset_id || ' has no column values defined';
+	END IF;
+	--
+	-- Add the WHERE clause.  This differs according to whether it's a
+	-- single-row fieldset or a query-based fieldset.
+	--
+	IF query IS NULL        AND fs_pkey_value IS NULL THEN
+		RETURN 'Incomplete fieldset: neither a primary key nor a query available';
+	ELSIF query IS NOT NULL AND fs_pkey_value IS NULL THEN
+	    fs_query := rtrim( query, ';' );
+	    statement := statement || ' WHERE ' || pkey_name || ' IN ( '
+	                 || fs_query || ' );';
+	ELSIF query IS NULL     AND fs_pkey_value IS NOT NULL THEN
+		statement := statement || ' WHERE ' || pkey_name || ' = '
+				     || fs_pkey_value || ';';
+	ELSE  -- both are not null
+		RETURN 'Ambiguous fieldset: both a primary key and a query provided';
+	END IF;
+	--
+	-- Execute the update
+	--
+	BEGIN
+		EXECUTE statement;
+		GET DIAGNOSTICS update_count = ROW_COUNT;
+		--
+		IF UPDATE_COUNT > 0 THEN
+			status_code := 'APPLIED';
+			msg := NULL;
+		ELSE
+			status_code := 'ERROR';
+			msg := 'No eligible rows found for fieldset ' || fieldset_id;
+    	END IF;
+	EXCEPTION WHEN OTHERS THEN
+		status_code := 'ERROR';
+		msg := 'Unable to apply fieldset ' || fieldset_id
+			   || ': ' || sqlerrm;
+	END;
+	--
+	-- Update fieldset status
+	--
+	UPDATE action.fieldset
+	SET status       = status_code,
+	    applied_time = now()
+	WHERE id = fieldset_id;
+	--
+	RETURN msg;
+END;
+$$ LANGUAGE plpgsql;
+
+COMMENT ON FUNCTION action.apply_fieldset( INT, TEXT, TEXT, TEXT ) IS $$
+/**
+ * Applies a specified fieldset, using a supplied table name and primary
+ * key name.  The query parameter should be non-null only for
+ * query-based fieldsets.
+ *
+ * Returns NULL if successful, or an error message if not.
+ */
+$$;
+
+CREATE INDEX uhr_hold_idx ON action.unfulfilled_hold_list (hold);
+
+CREATE OR REPLACE VIEW action.unfulfilled_hold_loops AS
+    SELECT  u.hold,
+            c.circ_lib,
+            count(*)
+      FROM  action.unfulfilled_hold_list u
+            JOIN asset.copy c ON (c.id = u.current_copy)
+      GROUP BY 1,2;
+
+CREATE OR REPLACE VIEW action.unfulfilled_hold_min_loop AS
+    SELECT  hold,
+            min(count)
+      FROM  action.unfulfilled_hold_loops
+      GROUP BY 1;
+
+CREATE OR REPLACE VIEW action.unfulfilled_hold_innermost_loop AS
+    SELECT  DISTINCT l.*
+      FROM  action.unfulfilled_hold_loops l
+            JOIN action.unfulfilled_hold_min_loop m USING (hold)
+      WHERE l.count = m.min;
+
+ALTER TABLE asset.copy
+ADD COLUMN dummy_isbn TEXT;
+
+ALTER TABLE auditor.asset_copy_history
+ADD COLUMN dummy_isbn TEXT;
+
+-- Add new column status_changed_date to asset.copy, with trigger to maintain it
+-- Add corresponding new column to auditor.asset_copy_history
+
+ALTER TABLE asset.copy
+	ADD COLUMN status_changed_time TIMESTAMPTZ;
+
+ALTER TABLE auditor.asset_copy_history
+	ADD COLUMN status_changed_time TIMESTAMPTZ;
+
+CREATE OR REPLACE FUNCTION asset.acp_status_changed()
+RETURNS TRIGGER AS $$
+BEGIN
+	IF NEW.status <> OLD.status THEN
+		NEW.status_changed_time := now();
+	END IF;
+	RETURN NEW;
+END;
+$$ LANGUAGE plpgsql;
+
+CREATE TRIGGER acp_status_changed_trig
+	BEFORE UPDATE ON asset.copy
+	FOR EACH ROW EXECUTE PROCEDURE asset.acp_status_changed();
+
+ALTER TABLE asset.copy
+ADD COLUMN mint_condition boolean NOT NULL DEFAULT TRUE;
+
+ALTER TABLE auditor.asset_copy_history
+ADD COLUMN mint_condition boolean NOT NULL DEFAULT TRUE;
+
+ALTER TABLE asset.copy ADD COLUMN floating BOOL NOT NULL DEFAULT FALSE;
+ALTER TABLE auditor.asset_copy_history ADD COLUMN floating BOOL;
+
+DROP INDEX IF EXISTS asset.copy_barcode_key;
+CREATE UNIQUE INDEX copy_barcode_key ON asset.copy (barcode) WHERE deleted = FALSE OR deleted IS FALSE;
+
+-- Note: later we create a trigger a_opac_vis_mat_view_tgr
+-- AFTER INSERT OR UPDATE ON asset.copy
+
+ALTER TABLE asset.copy ADD COLUMN cost NUMERIC(8,2);
+ALTER TABLE auditor.asset_copy_history ADD COLUMN cost NUMERIC(8,2);
+
+-- Moke mostly parallel changes to action.circulation
+-- and action.aged_circulation
+
+ALTER TABLE action.circulation
+ADD COLUMN workstation INT
+    REFERENCES actor.workstation
+	ON DELETE SET NULL
+	DEFERRABLE INITIALLY DEFERRED;
+
+ALTER TABLE action.aged_circulation
+ADD COLUMN workstation INT;
+
+ALTER TABLE action.circulation
+ADD COLUMN parent_circ BIGINT
+	REFERENCES action.circulation(id)
+	DEFERRABLE INITIALLY DEFERRED;
+
+CREATE UNIQUE INDEX circ_parent_idx
+ON action.circulation( parent_circ )
+WHERE parent_circ IS NOT NULL;
+
+ALTER TABLE action.aged_circulation
+ADD COLUMN parent_circ BIGINT;
+
+ALTER TABLE action.circulation
+ADD COLUMN checkin_workstation INT
+	REFERENCES actor.workstation(id)
+	ON DELETE SET NULL
+	DEFERRABLE INITIALLY DEFERRED;
+
+ALTER TABLE action.aged_circulation
+ADD COLUMN checkin_workstation INT;
+
+ALTER TABLE action.circulation
+ADD COLUMN checkin_scan_time TIMESTAMPTZ;
+
+ALTER TABLE action.aged_circulation
+ADD COLUMN checkin_scan_time TIMESTAMPTZ;
+
+CREATE INDEX action_circulation_target_copy_idx
+ON action.circulation (target_copy);
+
+CREATE INDEX action_aged_circulation_target_copy_idx
+ON action.aged_circulation (target_copy);
+
+ALTER TABLE action.circulation
+DROP CONSTRAINT circulation_stop_fines_check;
+
+ALTER TABLE action.circulation
+	ADD CONSTRAINT circulation_stop_fines_check
+	CHECK (stop_fines IN (
+        'CHECKIN','CLAIMSRETURNED','LOST','MAXFINES','RENEW','LONGOVERDUE','CLAIMSNEVERCHECKEDOUT'));
+
+-- Correct some long-standing misspellings involving variations of "recur"
+
+ALTER TABLE action.circulation RENAME COLUMN recuring_fine TO recurring_fine;
+ALTER TABLE action.circulation RENAME COLUMN recuring_fine_rule TO recurring_fine_rule;
+
+ALTER TABLE action.aged_circulation RENAME COLUMN recuring_fine TO recurring_fine;
+ALTER TABLE action.aged_circulation RENAME COLUMN recuring_fine_rule TO recurring_fine_rule;
+
+ALTER TABLE config.rule_recuring_fine RENAME TO rule_recurring_fine;
+ALTER TABLE config.rule_recuring_fine_id_seq RENAME TO rule_recurring_fine_id_seq;
+
+ALTER TABLE config.rule_recurring_fine RENAME COLUMN recurance_interval TO recurrence_interval;
+
+-- Might as well keep the comment in sync as well
+COMMENT ON TABLE config.rule_recurring_fine IS $$
+/*
+ * Copyright (C) 2005  Georgia Public Library Service 
+ * Mike Rylander <mrylander at gmail.com>
+ *
+ * Circulation Recurring Fine rules
+ *
+ * Each circulation is given a recurring fine amount based on one of
+ * these rules.  The recurrence_interval should not be any shorter
+ * than the interval between runs of the fine_processor.pl script
+ * (which is run from CRON), or you could miss fines.
+ * 
+ *
+ * ****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+$$;
+
+-- Extend the name change to some related views:
+
+DROP VIEW IF EXISTS reporter.overdue_circs;
+
+CREATE OR REPLACE VIEW reporter.overdue_circs AS
+SELECT  *
+  FROM  action.circulation
+    WHERE checkin_time is null
+	        AND (stop_fines NOT IN ('LOST','CLAIMSRETURNED') OR stop_fines IS NULL)
+			        AND due_date < now();
+
+DROP VIEW IF EXISTS stats.fleshed_circulation;
+
+DROP VIEW IF EXISTS stats.fleshed_copy;
+
+CREATE VIEW stats.fleshed_copy AS
+        SELECT  cp.*,
+        CAST(cp.create_date AS DATE) AS create_date_day,
+        CAST(cp.edit_date AS DATE) AS edit_date_day,
+        DATE_TRUNC('hour', cp.create_date) AS create_date_hour,
+        DATE_TRUNC('hour', cp.edit_date) AS edit_date_hour,
+                cn.label AS call_number_label,
+                cn.owning_lib,
+                rd.item_lang,
+                rd.item_type,
+                rd.item_form
+        FROM    asset.copy cp
+                JOIN asset.call_number cn ON (cp.call_number = cn.id)
+                JOIN metabib.rec_descriptor rd ON (rd.record = cn.record);
+
+CREATE VIEW stats.fleshed_circulation AS
+        SELECT  c.*,
+                CAST(c.xact_start AS DATE) AS start_date_day,
+                CAST(c.xact_finish AS DATE) AS finish_date_day,
+                DATE_TRUNC('hour', c.xact_start) AS start_date_hour,
+                DATE_TRUNC('hour', c.xact_finish) AS finish_date_hour,
+                cp.call_number_label,
+                cp.owning_lib,
+                cp.item_lang,
+                cp.item_type,
+                cp.item_form
+        FROM    action.circulation c
+                JOIN stats.fleshed_copy cp ON (cp.id = c.target_copy);
+
+-- Drop a view temporarily in order to alter action.all_circulation, upon
+-- which it is dependent.  We will recreate the view later.
+
+DROP VIEW IF EXISTS extend_reporter.full_circ_count;
+
+-- You would think that CREATE OR REPLACE would be enough, but in testing
+-- PostgreSQL complained about renaming the columns in the view. So we
+-- drop the view first.
+DROP VIEW IF EXISTS action.all_circulation;
+
+CREATE OR REPLACE VIEW action.all_circulation AS
+    SELECT  id,usr_post_code, usr_home_ou, usr_profile, usr_birth_year, copy_call_number, copy_location,
+        copy_owning_lib, copy_circ_lib, copy_bib_record, xact_start, xact_finish, target_copy,
+        circ_lib, circ_staff, checkin_staff, checkin_lib, renewal_remaining, due_date,
+        stop_fines_time, checkin_time, create_time, duration, fine_interval, recurring_fine,
+        max_fine, phone_renewal, desk_renewal, opac_renewal, duration_rule, recurring_fine_rule,
+        max_fine_rule, stop_fines, workstation, checkin_workstation, checkin_scan_time, parent_circ
+      FROM  action.aged_circulation
+            UNION ALL
+    SELECT  DISTINCT circ.id,COALESCE(a.post_code,b.post_code) AS usr_post_code, p.home_ou AS usr_home_ou, p.profile AS usr_profile, EXTRACT(YEAR FROM p.dob)::INT AS usr_birth_year,
+        cp.call_number AS copy_call_number, cp.location AS copy_location, cn.owning_lib AS copy_owning_lib, cp.circ_lib AS copy_circ_lib,
+        cn.record AS copy_bib_record, circ.xact_start, circ.xact_finish, circ.target_copy, circ.circ_lib, circ.circ_staff, circ.checkin_staff,
+        circ.checkin_lib, circ.renewal_remaining, circ.due_date, circ.stop_fines_time, circ.checkin_time, circ.create_time, circ.duration,
+        circ.fine_interval, circ.recurring_fine, circ.max_fine, circ.phone_renewal, circ.desk_renewal, circ.opac_renewal, circ.duration_rule,
+        circ.recurring_fine_rule, circ.max_fine_rule, circ.stop_fines, circ.workstation, circ.checkin_workstation, circ.checkin_scan_time,
+        circ.parent_circ
+      FROM  action.circulation circ
+        JOIN asset.copy cp ON (circ.target_copy = cp.id)
+        JOIN asset.call_number cn ON (cp.call_number = cn.id)
+        JOIN actor.usr p ON (circ.usr = p.id)
+        LEFT JOIN actor.usr_address a ON (p.mailing_address = a.id)
+        LEFT JOIN actor.usr_address b ON (p.billing_address = a.id);
+
+-- Recreate the temporarily dropped view, having altered the action.all_circulation view:
+
+CREATE OR REPLACE VIEW extend_reporter.full_circ_count AS
+ SELECT cp.id, COALESCE(sum(c.circ_count), 0::bigint) + COALESCE(count(circ.id), 0::bigint) + COALESCE(count(acirc.id), 0::bigint) AS circ_count
+   FROM asset."copy" cp
+   LEFT JOIN extend_reporter.legacy_circ_count c USING (id)
+   LEFT JOIN "action".circulation circ ON circ.target_copy = cp.id
+   LEFT JOIN "action".aged_circulation acirc ON acirc.target_copy = cp.id
+  GROUP BY cp.id;
+
+CREATE UNIQUE INDEX only_one_concurrent_checkout_per_copy ON action.circulation(target_copy) WHERE checkin_time IS NULL;
+
+ALTER TABLE action.circulation DROP CONSTRAINT action_circulation_target_copy_fkey;
+
+CREATE OR REPLACE FUNCTION action.age_circ_on_delete () RETURNS TRIGGER AS $$
+DECLARE
+found char := 'N';
+BEGIN
+
+    -- If there are any renewals for this circulation, don't archive or delete
+    -- it yet.   We'll do so later, when we archive and delete the renewals.
+
+    SELECT 'Y' INTO found
+    FROM action.circulation
+    WHERE parent_circ = OLD.id
+    LIMIT 1;
+
+    IF found = 'Y' THEN
+        RETURN NULL;  -- don't delete
+        END IF;
+
+    -- Archive a copy of the old row to action.aged_circulation
+
+    INSERT INTO action.aged_circulation
+        (id,usr_post_code, usr_home_ou, usr_profile, usr_birth_year, copy_call_number, copy_location,
+        copy_owning_lib, copy_circ_lib, copy_bib_record, xact_start, xact_finish, target_copy,
+        circ_lib, circ_staff, checkin_staff, checkin_lib, renewal_remaining, due_date,
+        stop_fines_time, checkin_time, create_time, duration, fine_interval, recurring_fine,
+        max_fine, phone_renewal, desk_renewal, opac_renewal, duration_rule, recurring_fine_rule,
+        max_fine_rule, stop_fines, workstation, checkin_workstation, checkin_scan_time, parent_circ)
+      SELECT
+        id,usr_post_code, usr_home_ou, usr_profile, usr_birth_year, copy_call_number, copy_location,
+        copy_owning_lib, copy_circ_lib, copy_bib_record, xact_start, xact_finish, target_copy,
+        circ_lib, circ_staff, checkin_staff, checkin_lib, renewal_remaining, due_date,
+        stop_fines_time, checkin_time, create_time, duration, fine_interval, recurring_fine,
+        max_fine, phone_renewal, desk_renewal, opac_renewal, duration_rule, recurring_fine_rule,
+        max_fine_rule, stop_fines, workstation, checkin_workstation, checkin_scan_time, parent_circ
+        FROM action.all_circulation WHERE id = OLD.id;
+
+    RETURN OLD;
+END;
+$$ LANGUAGE 'plpgsql';
+
+UPDATE config.z3950_attr SET truncation = 1 WHERE source = 'biblios' AND name = 'title';
+
+UPDATE config.z3950_attr SET truncation = 1 WHERE source = 'biblios' AND truncation = 0;
+
+-- Adding circ.holds.target_skip_me OU setting logic to the pre-matchpoint tests
+
+CREATE OR REPLACE FUNCTION action.hold_request_permit_test( pickup_ou INT, request_ou INT, match_item BIGINT, match_user INT, match_requestor INT ) RETURNS SETOF action.matrix_test_result AS $func$
+DECLARE
+    matchpoint_id        INT;
+    user_object        actor.usr%ROWTYPE;
+    age_protect_object    config.rule_age_hold_protect%ROWTYPE;
+    standing_penalty    config.standing_penalty%ROWTYPE;
+    transit_range_ou_type    actor.org_unit_type%ROWTYPE;
+    transit_source        actor.org_unit%ROWTYPE;
+    item_object        asset.copy%ROWTYPE;
+    ou_skip              actor.org_unit_setting%ROWTYPE;
+    result            action.matrix_test_result;
+    hold_test        config.hold_matrix_matchpoint%ROWTYPE;
+    hold_count        INT;
+    hold_transit_prox    INT;
+    frozen_hold_count    INT;
+    context_org_list    INT[];
+    done            BOOL := FALSE;
+BEGIN
+    SELECT INTO user_object * FROM actor.usr WHERE id = match_user;
+    SELECT INTO context_org_list ARRAY_ACCUM(id) FROM actor.org_unit_full_path( pickup_ou );
+
+    result.success := TRUE;
+
+    -- Fail if we couldn't find a user
+    IF user_object.id IS NULL THEN
+        result.fail_part := 'no_user';
+        result.success := FALSE;
+        done := TRUE;
+        RETURN NEXT result;
+        RETURN;
+    END IF;
+
+    SELECT INTO item_object * FROM asset.copy WHERE id = match_item;
+
+    -- Fail if we couldn't find a copy
+    IF item_object.id IS NULL THEN
+        result.fail_part := 'no_item';
+        result.success := FALSE;
+        done := TRUE;
+        RETURN NEXT result;
+        RETURN;
+    END IF;
+
+    SELECT INTO matchpoint_id action.find_hold_matrix_matchpoint(pickup_ou, request_ou, match_item, match_user, match_requestor);
+    result.matchpoint := matchpoint_id;
+
+    SELECT INTO ou_skip * FROM actor.org_unit_setting WHERE name = 'circ.holds.target_skip_me' AND org_unit = item_object.circ_lib;
+
+    -- Fail if the circ_lib for the item has circ.holds.target_skip_me set to true
+    IF ou_skip.id IS NOT NULL AND ou_skip.value = 'true' THEN
+        result.fail_part := 'circ.holds.target_skip_me';
+        result.success := FALSE;
+        done := TRUE;
+        RETURN NEXT result;
+        RETURN;
+    END IF;
+
+    -- Fail if user is barred
+    IF user_object.barred IS TRUE THEN
+        result.fail_part := 'actor.usr.barred';
+        result.success := FALSE;
+        done := TRUE;
+        RETURN NEXT result;
+        RETURN;
+    END IF;
+
+    -- Fail if we couldn't find any matchpoint (requires a default)
+    IF matchpoint_id IS NULL THEN
+        result.fail_part := 'no_matchpoint';
+        result.success := FALSE;
+        done := TRUE;
+        RETURN NEXT result;
+        RETURN;
+    END IF;
+
+    SELECT INTO hold_test * FROM config.hold_matrix_matchpoint WHERE id = matchpoint_id;
+
+    IF hold_test.holdable IS FALSE THEN
+        result.fail_part := 'config.hold_matrix_test.holdable';
+        result.success := FALSE;
+        done := TRUE;
+        RETURN NEXT result;
+    END IF;
+
+    IF hold_test.transit_range IS NOT NULL THEN
+        SELECT INTO transit_range_ou_type * FROM actor.org_unit_type WHERE id = hold_test.transit_range;
+        IF hold_test.distance_is_from_owner THEN
+            SELECT INTO transit_source ou.* FROM actor.org_unit ou JOIN asset.call_number cn ON (cn.owning_lib = ou.id) WHERE cn.id = item_object.call_number;
+        ELSE
+            SELECT INTO transit_source * FROM actor.org_unit WHERE id = item_object.circ_lib;
+        END IF;
+
+        PERFORM * FROM actor.org_unit_descendants( transit_source.id, transit_range_ou_type.depth ) WHERE id = pickup_ou;
+
+        IF NOT FOUND THEN
+            result.fail_part := 'transit_range';
+            result.success := FALSE;
+            done := TRUE;
+            RETURN NEXT result;
+        END IF;
+    END IF;
+ 
+    FOR standing_penalty IN
+        SELECT  DISTINCT csp.*
+          FROM  actor.usr_standing_penalty usp
+                JOIN config.standing_penalty csp ON (csp.id = usp.standing_penalty)
+          WHERE usr = match_user
+                AND usp.org_unit IN ( SELECT * FROM explode_array(context_org_list) )
+                AND (usp.stop_date IS NULL or usp.stop_date > NOW())
+                AND csp.block_list LIKE '%HOLD%' LOOP
+
+        result.fail_part := standing_penalty.name;
+        result.success := FALSE;
+        done := TRUE;
+        RETURN NEXT result;
+    END LOOP;
+
+    IF hold_test.stop_blocked_user IS TRUE THEN
+        FOR standing_penalty IN
+            SELECT  DISTINCT csp.*
+              FROM  actor.usr_standing_penalty usp
+                    JOIN config.standing_penalty csp ON (csp.id = usp.standing_penalty)
+              WHERE usr = match_user
+                    AND usp.org_unit IN ( SELECT * FROM explode_array(context_org_list) )
+                    AND (usp.stop_date IS NULL or usp.stop_date > NOW())
+                    AND csp.block_list LIKE '%CIRC%' LOOP
+    
+            result.fail_part := standing_penalty.name;
+            result.success := FALSE;
+            done := TRUE;
+            RETURN NEXT result;
+        END LOOP;
+    END IF;
+
+    IF hold_test.max_holds IS NOT NULL THEN
+        SELECT    INTO hold_count COUNT(*)
+          FROM    action.hold_request
+          WHERE    usr = match_user
+            AND fulfillment_time IS NULL
+            AND cancel_time IS NULL
+            AND CASE WHEN hold_test.include_frozen_holds THEN TRUE ELSE frozen IS FALSE END;
+
+        IF hold_count >= hold_test.max_holds THEN
+            result.fail_part := 'config.hold_matrix_test.max_holds';
+            result.success := FALSE;
+            done := TRUE;
+            RETURN NEXT result;
+        END IF;
+    END IF;
+
+    IF item_object.age_protect IS NOT NULL THEN
+        SELECT INTO age_protect_object * FROM config.rule_age_hold_protect WHERE id = item_object.age_protect;
+
+        IF item_object.create_date + age_protect_object.age > NOW() THEN
+            IF hold_test.distance_is_from_owner THEN
+                SELECT INTO hold_transit_prox prox FROM actor.org_unit_proximity WHERE from_org = item_cn_object.owning_lib AND to_org = pickup_ou;
+            ELSE
+                SELECT INTO hold_transit_prox prox FROM actor.org_unit_proximity WHERE from_org = item_object.circ_lib AND to_org = pickup_ou;
+            END IF;
+
+            IF hold_transit_prox > age_protect_object.prox THEN
+                result.fail_part := 'config.rule_age_hold_protect.prox';
+                result.success := FALSE;
+                done := TRUE;
+                RETURN NEXT result;
+            END IF;
+        END IF;
+    END IF;
+
+    IF NOT done THEN
+        RETURN NEXT result;
+    END IF;
+
+    RETURN;
+END;
+$func$ LANGUAGE plpgsql;
+
+-- New post-delete trigger to propagate deletions to parent(s)
+
+CREATE OR REPLACE FUNCTION action.age_parent_circ_on_delete () RETURNS TRIGGER AS $$
+BEGIN
+
+    -- Having deleted a renewal, we can delete the original circulation (or a previous
+    -- renewal, if that's what parent_circ is pointing to).  That deletion will trigger
+    -- deletion of any prior parents, etc. recursively.
+
+    IF OLD.parent_circ IS NOT NULL THEN
+        DELETE FROM action.circulation
+        WHERE id = OLD.parent_circ;
+    END IF;
+
+    RETURN OLD;
+END;
+$$ LANGUAGE 'plpgsql';
+
+CREATE TRIGGER age_parent_circ AFTER DELETE ON action.circulation
+FOR EACH ROW EXECUTE PROCEDURE action.age_parent_circ_on_delete ();
+
+-- This only gets inserted if there are no other id > 100 billing types
+INSERT INTO config.billing_type (id, name, owner) SELECT DISTINCT 101, oils_i18n_gettext(101, 'Misc', 'cbt', 'name'), 1 FROM config.billing_type_id_seq WHERE last_value < 101;
+SELECT SETVAL('config.billing_type_id_seq'::TEXT, 101) FROM config.billing_type_id_seq WHERE last_value < 101;
+
+-- Populate xact_type column in the materialized version of billable_xact_summary
+
+CREATE OR REPLACE FUNCTION money.mat_summary_create () RETURNS TRIGGER AS $$
+BEGIN
+	INSERT INTO money.materialized_billable_xact_summary (id, usr, xact_start, xact_finish, total_paid, total_owed, balance_owed, xact_type)
+		VALUES ( NEW.id, NEW.usr, NEW.xact_start, NEW.xact_finish, 0.0, 0.0, 0.0, TG_ARGV[0]);
+	RETURN NEW;
+END;
+$$ LANGUAGE PLPGSQL;
+ 
+DROP TRIGGER IF EXISTS mat_summary_create_tgr ON action.circulation;
+CREATE TRIGGER mat_summary_create_tgr AFTER INSERT ON action.circulation FOR EACH ROW EXECUTE PROCEDURE money.mat_summary_create ('circulation');
+ 
+DROP TRIGGER IF EXISTS mat_summary_create_tgr ON money.grocery;
+CREATE TRIGGER mat_summary_create_tgr AFTER INSERT ON money.grocery FOR EACH ROW EXECUTE PROCEDURE money.mat_summary_create ('grocery');
+
+CREATE RULE money_payment_view_update AS ON UPDATE TO money.payment_view DO INSTEAD 
+    UPDATE money.payment SET xact = NEW.xact, payment_ts = NEW.payment_ts, voided = NEW.voided, amount = NEW.amount, note = NEW.note WHERE id = NEW.id;
+
+-- Generate the equivalent of compound subject entries from the existing rows
+-- so that we don't have to laboriously reindex them
+
+--INSERT INTO config.metabib_field (field_class, name, format, xpath ) VALUES
+--    ( 'subject', 'complete', 'mods32', $$//mods32:mods/mods32:subject//text()$$ );
+--
+--CREATE INDEX metabib_subject_field_entry_source_idx ON metabib.subject_field_entry (source);
+--
+--INSERT INTO metabib.subject_field_entry (source, field, value)
+--    SELECT source, (
+--            SELECT id 
+--            FROM config.metabib_field
+--            WHERE field_class = 'subject' AND name = 'complete'
+--        ), 
+--        ARRAY_TO_STRING ( 
+--            ARRAY (
+--                SELECT value 
+--                FROM metabib.subject_field_entry msfe
+--                WHERE msfe.source = groupee.source
+--                ORDER BY source 
+--            ), ' ' 
+--        ) AS grouped
+--    FROM ( 
+--        SELECT source
+--        FROM metabib.subject_field_entry
+--        GROUP BY source
+--    ) AS groupee;
+
+CREATE OR REPLACE FUNCTION money.materialized_summary_billing_del () RETURNS TRIGGER AS $$
+DECLARE
+        prev_billing    money.billing%ROWTYPE;
+        old_billing     money.billing%ROWTYPE;
+BEGIN
+        SELECT * INTO prev_billing FROM money.billing WHERE xact = OLD.xact AND NOT voided ORDER BY billing_ts DESC LIMIT 1 OFFSET 1;
+        SELECT * INTO old_billing FROM money.billing WHERE xact = OLD.xact AND NOT voided ORDER BY billing_ts DESC LIMIT 1;
+
+        IF OLD.id = old_billing.id THEN
+                UPDATE  money.materialized_billable_xact_summary
+                  SET   last_billing_ts = prev_billing.billing_ts,
+                        last_billing_note = prev_billing.note,
+                        last_billing_type = prev_billing.billing_type
+                  WHERE id = OLD.xact;
+        END IF;
+
+        IF NOT OLD.voided THEN
+                UPDATE  money.materialized_billable_xact_summary
+                  SET   total_owed = total_owed - OLD.amount,
+                        balance_owed = balance_owed + OLD.amount
+                  WHERE id = OLD.xact;
+        END IF;
+
+        RETURN OLD;
+END;
+$$ LANGUAGE PLPGSQL;
+
+-- ARG! need to rid ourselves of the broken table definition ... this mechanism is not ideal, sorry.
+DROP TABLE IF EXISTS config.index_normalizer CASCADE;
+
+CREATE OR REPLACE FUNCTION public.naco_normalize( TEXT, TEXT ) RETURNS TEXT AS $func$
+	use Unicode::Normalize;
+	use Encode;
+
+	# When working with Unicode data, the first step is to decode it to
+	# a byte string; after that, lowercasing is safe
+	my $txt = lc(decode_utf8(shift));
+	my $sf = shift;
+
+	$txt = NFD($txt);
+	$txt =~ s/\pM+//go;	# Remove diacritics
+
+	$txt =~ s/\xE6/AE/go;	# Convert ae digraph
+	$txt =~ s/\x{153}/OE/go;# Convert oe digraph
+	$txt =~ s/\xFE/TH/go;	# Convert Icelandic thorn
+
+	$txt =~ tr/\x{2070}\x{2071}\x{2072}\x{2073}\x{2074}\x{2075}\x{2076}\x{2077}\x{2078}\x{2079}\x{207A}\x{207B}/0123456789+-/;# Convert superscript numbers
+	$txt =~ tr/\x{2080}\x{2081}\x{2082}\x{2083}\x{2084}\x{2085}\x{2086}\x{2087}\x{2088}\x{2089}\x{208A}\x{208B}/0123456889+-/;# Convert subscript numbers
+
+	$txt =~ tr/\x{0251}\x{03B1}\x{03B2}\x{0262}\x{03B3}/AABGG/;	 	# Convert Latin and Greek
+	$txt =~ tr/\x{2113}\xF0\!\"\(\)\-\{\}\<\>\;\:\.\?\xA1\xBF\/\\\@\*\%\=\xB1\+\xAE\xA9\x{2117}\$\xA3\x{FFE1}\xB0\^\_\~\`/LD /;	# Convert Misc
+	$txt =~ tr/\'\[\]\|//d;							# Remove Misc
+
+	if ($sf && $sf =~ /^a/o) {
+		my $commapos = index($txt,',');
+		if ($commapos > -1) {
+			if ($commapos != length($txt) - 1) {
+				my @list = split /,/, $txt;
+				my $first = shift @list;
+				$txt = $first . ',' . join(' ', @list);
+			} else {
+				$txt =~ s/,/ /go;
+			}
+		}
+	} else {
+		$txt =~ s/,/ /go;
+	}
+
+	$txt =~ s/\s+/ /go;	# Compress multiple spaces
+	$txt =~ s/^\s+//o;	# Remove leading space
+	$txt =~ s/\s+$//o;	# Remove trailing space
+
+	# Encoding the outgoing string is good practice, but not strictly
+	# necessary in this case because we've stripped everything from it
+	return encode_utf8($txt);
+$func$ LANGUAGE 'plperlu' STRICT IMMUTABLE;
+
+-- Some handy functions, based on existing ones, to provide optional ingest normalization
+
+CREATE OR REPLACE FUNCTION public.left_trunc( TEXT, INT ) RETURNS TEXT AS $func$
+	SELECT SUBSTRING($1,$2);
+$func$ LANGUAGE SQL STRICT IMMUTABLE;
+
+CREATE OR REPLACE FUNCTION public.right_trunc( TEXT, INT ) RETURNS TEXT AS $func$
+	SELECT SUBSTRING($1,1,$2);
+$func$ LANGUAGE SQL STRICT IMMUTABLE;
+
+CREATE OR REPLACE FUNCTION public.naco_normalize_keep_comma( TEXT ) RETURNS TEXT AS $func$
+	SELECT public.naco_normalize($1,'a');
+$func$ LANGUAGE SQL STRICT IMMUTABLE;
+
+CREATE OR REPLACE FUNCTION public.split_date_range( TEXT ) RETURNS TEXT AS $func$
+	SELECT REGEXP_REPLACE( $1, E'(\\d{4})-(\\d{4})', E'\\1 \\2', 'g' );
+$func$ LANGUAGE SQL STRICT IMMUTABLE;
+
+-- And ... a table in which to register them
+
+CREATE TABLE config.index_normalizer (
+	id		SERIAL	PRIMARY KEY,
+	name		TEXT	UNIQUE NOT NULL,
+	description	TEXT,
+	func		TEXT	NOT NULL,
+	param_count	INT	NOT NULL DEFAULT 0
+);
+
+CREATE TABLE config.metabib_field_index_norm_map (
+	id	SERIAL	PRIMARY KEY,
+	field	INT	NOT NULL REFERENCES config.metabib_field (id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED,
+	norm	INT	NOT NULL REFERENCES config.index_normalizer (id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED,
+	params	TEXT,
+	pos	INT	NOT NULL DEFAULT 0
+);
+
+INSERT INTO config.index_normalizer (name, description, func, param_count) VALUES (
+	'NACO Normalize',
+	'Apply NACO normalization rules to the extracted text.  See http://www.loc.gov/catdir/pcc/naco/normrule-2.html for details.',
+	'naco_normalize',
+	0
+);
+
+INSERT INTO config.index_normalizer (name, description, func, param_count) VALUES (
+	'Normalize date range',
+	'Split date ranges in the form of "XXXX-YYYY" into "XXXX YYYY" for proper index.',
+	'split_date_range',
+	1
+);
+
+INSERT INTO config.index_normalizer (name, description, func, param_count) VALUES (
+	'NACO Normalize -- retain first comma',
+	'Apply NACO normalization rules to the extracted text, retaining the first comma.  See http://www.loc.gov/catdir/pcc/naco/normrule-2.html for details.',
+	'naco_normalize_keep_comma',
+	0
+);
+
+INSERT INTO config.index_normalizer (name, description, func, param_count) VALUES (
+	'Strip Diacritics',
+	'Convert text to NFD form and remove non-spacing combining marks.',
+	'remove_diacritics',
+	0
+);
+
+INSERT INTO config.index_normalizer (name, description, func, param_count) VALUES (
+	'Up-case',
+	'Convert text upper case.',
+	'uppercase',
+	0
+);
+
+INSERT INTO config.index_normalizer (name, description, func, param_count) VALUES (
+	'Down-case',
+	'Convert text lower case.',
+	'lowercase',
+	0
+);
+
+INSERT INTO config.index_normalizer (name, description, func, param_count) VALUES (
+	'Extract Dewey-like number',
+	'Extract a string of numeric characters ther resembles a DDC number.',
+	'call_number_dewey',
+	0
+);
+
+INSERT INTO config.index_normalizer (name, description, func, param_count) VALUES (
+	'Left truncation',
+	'Discard the specified number of characters from the left side of the string.',
+	'left_trunc',
+	1
+);
+
+INSERT INTO config.index_normalizer (name, description, func, param_count) VALUES (
+	'Right truncation',
+	'Include only the specified number of characters from the left side of the string.',
+	'right_trunc',
+	1
+);
+
+INSERT INTO config.index_normalizer (name, description, func, param_count) VALUES (
+	'First word',
+	'Include only the first space-separated word of a string.',
+	'first_word',
+	0
+);
+
+INSERT INTO config.metabib_field_index_norm_map (field,norm)
+	SELECT	m.id,
+		i.id
+	  FROM	config.metabib_field m,
+		config.index_normalizer i
+	  WHERE	i.func IN ('naco_normalize','split_date_range');
+
+CREATE OR REPLACE FUNCTION oils_tsearch2 () RETURNS TRIGGER AS $$
+DECLARE
+    normalizer      RECORD;
+    value           TEXT := '';
+BEGIN
+
+    value := NEW.value;
+
+    IF TG_TABLE_NAME::TEXT ~ 'field_entry$' THEN
+        FOR normalizer IN
+            SELECT  n.func AS func,
+                    n.param_count AS param_count,
+                    m.params AS params
+              FROM  config.index_normalizer n
+                    JOIN config.metabib_field_index_norm_map m ON (m.norm = n.id)
+              WHERE field = NEW.field AND m.pos < 0
+              ORDER BY m.pos LOOP
+                EXECUTE 'SELECT ' || normalizer.func || '(' ||
+                    quote_literal( value ) ||
+                    CASE
+                        WHEN normalizer.param_count > 0
+                            THEN ',' || REPLACE(REPLACE(BTRIM(normalizer.params,'[]'),E'\'',E'\\\''),E'"',E'\'')
+                            ELSE ''
+                        END ||
+                    ')' INTO value;
+
+        END LOOP;
+
+        NEW.value := value;
+    END IF;
+
+    IF NEW.index_vector = ''::tsvector THEN
+        RETURN NEW;
+    END IF;
+
+    IF TG_TABLE_NAME::TEXT ~ 'field_entry$' THEN
+        FOR normalizer IN
+            SELECT  n.func AS func,
+                    n.param_count AS param_count,
+                    m.params AS params
+              FROM  config.index_normalizer n
+                    JOIN config.metabib_field_index_norm_map m ON (m.norm = n.id)
+              WHERE field = NEW.field AND m.pos >= 0
+              ORDER BY m.pos LOOP
+                EXECUTE 'SELECT ' || normalizer.func || '(' ||
+                    quote_literal( value ) ||
+                    CASE
+                        WHEN normalizer.param_count > 0
+                            THEN ',' || REPLACE(REPLACE(BTRIM(normalizer.params,'[]'),E'\'',E'\\\''),E'"',E'\'')
+                            ELSE ''
+                        END ||
+                    ')' INTO value;
+
+        END LOOP;
+    END IF;
+
+    IF REGEXP_REPLACE(VERSION(),E'^.+?(\\d+\\.\\d+).*?$',E'\\1')::FLOAT > 8.2 THEN
+        NEW.index_vector = to_tsvector((TG_ARGV[0])::regconfig, value);
+    ELSE
+        NEW.index_vector = to_tsvector(TG_ARGV[0], value);
+    END IF;
+
+    RETURN NEW;
+END;
+$$ LANGUAGE PLPGSQL;
+
+CREATE OR REPLACE FUNCTION oils_xpath ( TEXT, TEXT, ANYARRAY ) RETURNS TEXT[] AS 'SELECT XPATH( $1, $2::XML, $3 )::TEXT[];' LANGUAGE SQL IMMUTABLE;
+
+CREATE OR REPLACE FUNCTION oils_xpath ( TEXT, TEXT ) RETURNS TEXT[] AS 'SELECT XPATH( $1, $2::XML )::TEXT[];' LANGUAGE SQL IMMUTABLE;
+
+CREATE OR REPLACE FUNCTION oils_xpath_string ( TEXT, TEXT, TEXT, ANYARRAY ) RETURNS TEXT AS $func$
+    SELECT  ARRAY_TO_STRING(
+                oils_xpath(
+                    $1 ||
+                        CASE WHEN $1 ~ $re$/[^/[]*@[^]]+$$re$ OR $1 ~ $re$text\(\)$$re$ THEN '' ELSE '//text()' END,
+                    $2,
+                    $4
+                ),
+                $3
+            );
+$func$ LANGUAGE SQL IMMUTABLE;
+
+CREATE OR REPLACE FUNCTION oils_xpath_string ( TEXT, TEXT, TEXT ) RETURNS TEXT AS $func$
+    SELECT oils_xpath_string( $1, $2, $3, '{}'::TEXT[] );
+$func$ LANGUAGE SQL IMMUTABLE;
+
+CREATE OR REPLACE FUNCTION oils_xpath_string ( TEXT, TEXT, ANYARRAY ) RETURNS TEXT AS $func$
+    SELECT oils_xpath_string( $1, $2, '', $3 );
+$func$ LANGUAGE SQL IMMUTABLE;
+
+CREATE OR REPLACE FUNCTION oils_xpath_string ( TEXT, TEXT ) RETURNS TEXT AS $func$
+    SELECT oils_xpath_string( $1, $2, '{}'::TEXT[] );
+$func$ LANGUAGE SQL IMMUTABLE;
+
+CREATE TYPE metabib.field_entry_template AS (
+        field_class     TEXT,
+        field           INT,
+        source          BIGINT,
+        value           TEXT
+);
+
+CREATE OR REPLACE FUNCTION oils_xslt_process(TEXT, TEXT) RETURNS TEXT AS $func$
+  use strict;
+
+  use XML::LibXSLT;
+  use XML::LibXML;
+
+  my $doc = shift;
+  my $xslt = shift;
+
+  # The following approach uses the older XML::LibXML 1.69 / XML::LibXSLT 1.68
+  # methods of parsing XML documents and stylesheets, in the hopes of broader
+  # compatibility with distributions
+  my $parser = $_SHARED{'_xslt_process'}{parsers}{xml} || XML::LibXML->new();
+
+  # Cache the XML parser, if we do not already have one
+  $_SHARED{'_xslt_process'}{parsers}{xml} = $parser
+    unless ($_SHARED{'_xslt_process'}{parsers}{xml});
+
+  my $xslt_parser = $_SHARED{'_xslt_process'}{parsers}{xslt} || XML::LibXSLT->new();
+
+  # Cache the XSLT processor, if we do not already have one
+  $_SHARED{'_xslt_process'}{parsers}{xslt} = $xslt_parser
+    unless ($_SHARED{'_xslt_process'}{parsers}{xslt});
+
+  my $stylesheet = $_SHARED{'_xslt_process'}{stylesheets}{$xslt} ||
+    $xslt_parser->parse_stylesheet( $parser->parse_string($xslt) );
+
+  $_SHARED{'_xslt_process'}{stylesheets}{$xslt} = $stylesheet
+    unless ($_SHARED{'_xslt_process'}{stylesheets}{$xslt});
+
+  return $stylesheet->output_string(
+    $stylesheet->transform(
+      $parser->parse_string($doc)
+    )
+  );
+
+$func$ LANGUAGE 'plperlu' STRICT IMMUTABLE;
+
+-- Add two columns so that the following function will compile.
+-- Eventually the label column will be NOT NULL, but not yet.
+ALTER TABLE config.metabib_field ADD COLUMN label TEXT;
+ALTER TABLE config.metabib_field ADD COLUMN facet_xpath TEXT;
+
+CREATE OR REPLACE FUNCTION biblio.extract_metabib_field_entry ( rid BIGINT, default_joiner TEXT ) RETURNS SETOF metabib.field_entry_template AS $func$
+DECLARE
+    bib     biblio.record_entry%ROWTYPE;
+    idx     config.metabib_field%ROWTYPE;
+    xfrm        config.xml_transform%ROWTYPE;
+    prev_xfrm   TEXT;
+    transformed_xml TEXT;
+    xml_node    TEXT;
+    xml_node_list   TEXT[];
+    facet_text  TEXT;
+    raw_text    TEXT;
+    curr_text   TEXT;
+    joiner      TEXT := default_joiner; -- XXX will index defs supply a joiner?
+    output_row  metabib.field_entry_template%ROWTYPE;
+BEGIN
+
+    -- Get the record
+    SELECT INTO bib * FROM biblio.record_entry WHERE id = rid;
+
+    -- Loop over the indexing entries
+    FOR idx IN SELECT * FROM config.metabib_field ORDER BY format LOOP
+
+        SELECT INTO xfrm * from config.xml_transform WHERE name = idx.format;
+
+        -- See if we can skip the XSLT ... it's expensive
+        IF prev_xfrm IS NULL OR prev_xfrm <> xfrm.name THEN
+            -- Can't skip the transform
+            IF xfrm.xslt <> '---' THEN
+                transformed_xml := oils_xslt_process(bib.marc,xfrm.xslt);
+            ELSE
+                transformed_xml := bib.marc;
+            END IF;
+
+            prev_xfrm := xfrm.name;
+        END IF;
+
+        xml_node_list := oils_xpath( idx.xpath, transformed_xml, ARRAY[ARRAY[xfrm.prefix, xfrm.namespace_uri]] );
+
+        raw_text := NULL;
+        FOR xml_node IN SELECT x FROM explode_array(xml_node_list) AS x LOOP
+            CONTINUE WHEN xml_node !~ E'^\\s*<';
+
+            curr_text := ARRAY_TO_STRING(
+                oils_xpath( '//text()',
+                    REGEXP_REPLACE( -- This escapes all &s not followed by "amp;".  Data ise returned from oils_xpath (above) in UTF-8, not entity encoded
+                        REGEXP_REPLACE( -- This escapes embeded <s
+                            xml_node,
+                            $re$(>[^<]+)(<)([^>]+<)$re$,
+                            E'\\1&lt;\\3',
+                            'g'
+                        ),
+                        '&(?!amp;)',
+                        '&amp;',
+                        'g'
+                    )
+                ),
+                ' '
+            );
+
+            CONTINUE WHEN curr_text IS NULL OR curr_text = '';
+
+            IF raw_text IS NOT NULL THEN
+                raw_text := raw_text || joiner;
+            END IF;
+
+            raw_text := COALESCE(raw_text,'') || curr_text;
+
+            -- insert raw node text for faceting
+            IF idx.facet_field THEN
+
+                IF idx.facet_xpath IS NOT NULL AND idx.facet_xpath <> '' THEN
+                    facet_text := oils_xpath_string( idx.facet_xpath, xml_node, joiner, ARRAY[ARRAY[xfrm.prefix, xfrm.namespace_uri]] );
+                ELSE
+                    facet_text := curr_text;
+                END IF;
+
+                output_row.field_class = idx.field_class;
+                output_row.field = -1 * idx.id;
+                output_row.source = rid;
+                output_row.value = BTRIM(REGEXP_REPLACE(facet_text, E'\\s+', ' ', 'g'));
+
+                RETURN NEXT output_row;
+            END IF;
+
+        END LOOP;
+
+        CONTINUE WHEN raw_text IS NULL OR raw_text = '';
+
+        -- insert combined node text for searching
+        IF idx.search_field THEN
+            output_row.field_class = idx.field_class;
+            output_row.field = idx.id;
+            output_row.source = rid;
+            output_row.value = BTRIM(REGEXP_REPLACE(raw_text, E'\\s+', ' ', 'g'));
+
+            RETURN NEXT output_row;
+        END IF;
+
+    END LOOP;
+
+END;
+$func$ LANGUAGE PLPGSQL;
+
+-- default to a space joiner
+CREATE OR REPLACE FUNCTION biblio.extract_metabib_field_entry ( BIGINT ) RETURNS SETOF metabib.field_entry_template AS $func$
+	SELECT * FROM biblio.extract_metabib_field_entry($1, ' ');
+$func$ LANGUAGE SQL;
+
+CREATE OR REPLACE FUNCTION biblio.flatten_marc ( TEXT ) RETURNS SETOF metabib.full_rec AS $func$
+
+use MARC::Record;
+use MARC::File::XML (BinaryEncoding => 'UTF-8');
+
+my $xml = shift;
+my $r = MARC::Record->new_from_xml( $xml );
+
+return_next( { tag => 'LDR', value => $r->leader } );
+
+for my $f ( $r->fields ) {
+    if ($f->is_control_field) {
+        return_next({ tag => $f->tag, value => $f->data });
+    } else {
+        for my $s ($f->subfields) {
+            return_next({
+                tag      => $f->tag,
+                ind1     => $f->indicator(1),
+                ind2     => $f->indicator(2),
+                subfield => $s->[0],
+                value    => $s->[1]
+            });
+
+            if ( $f->tag eq '245' and $s->[0] eq 'a' ) {
+                my $trim = $f->indicator(2) || 0;
+                return_next({
+                    tag      => 'tnf',
+                    ind1     => $f->indicator(1),
+                    ind2     => $f->indicator(2),
+                    subfield => 'a',
+                    value    => substr( $s->[1], $trim )
+                });
+            }
+        }
+    }
+}
+
+return undef;
+
+$func$ LANGUAGE PLPERLU;
+
+CREATE OR REPLACE FUNCTION biblio.flatten_marc ( rid BIGINT ) RETURNS SETOF metabib.full_rec AS $func$
+DECLARE
+    bib biblio.record_entry%ROWTYPE;
+    output  metabib.full_rec%ROWTYPE;
+    field   RECORD;
+BEGIN
+    SELECT INTO bib * FROM biblio.record_entry WHERE id = rid;
+
+    FOR field IN SELECT * FROM biblio.flatten_marc( bib.marc ) LOOP
+        output.record := rid;
+        output.ind1 := field.ind1;
+        output.ind2 := field.ind2;
+        output.tag := field.tag;
+        output.subfield := field.subfield;
+        IF field.subfield IS NOT NULL AND field.tag NOT IN ('020','022','024') THEN -- exclude standard numbers and control fields
+            output.value := naco_normalize(field.value, field.subfield);
+        ELSE
+            output.value := field.value;
+        END IF;
+
+        CONTINUE WHEN output.value IS NULL;
+
+        RETURN NEXT output;
+    END LOOP;
+END;
+$func$ LANGUAGE PLPGSQL;
+
+-- functions to create auditor objects
+
+CREATE FUNCTION auditor.create_auditor_seq     ( sch TEXT, tbl TEXT ) RETURNS BOOL AS $creator$
+BEGIN
+    EXECUTE $$
+        CREATE SEQUENCE auditor.$$ || sch || $$_$$ || tbl || $$_pkey_seq;
+    $$;
+	RETURN TRUE;
+END;
+$creator$ LANGUAGE 'plpgsql';
+
+CREATE FUNCTION auditor.create_auditor_history ( sch TEXT, tbl TEXT ) RETURNS BOOL AS $creator$
+BEGIN
+    EXECUTE $$
+        CREATE TABLE auditor.$$ || sch || $$_$$ || tbl || $$_history (
+            audit_id	BIGINT				PRIMARY KEY,
+            audit_time	TIMESTAMP WITH TIME ZONE	NOT NULL,
+            audit_action	TEXT				NOT NULL,
+            LIKE $$ || sch || $$.$$ || tbl || $$
+        );
+    $$;
+	RETURN TRUE;
+END;
+$creator$ LANGUAGE 'plpgsql';
+
+CREATE FUNCTION auditor.create_auditor_func    ( sch TEXT, tbl TEXT ) RETURNS BOOL AS $creator$
+BEGIN
+    EXECUTE $$
+        CREATE FUNCTION auditor.audit_$$ || sch || $$_$$ || tbl || $$_func ()
+        RETURNS TRIGGER AS $func$
+        BEGIN
+            INSERT INTO auditor.$$ || sch || $$_$$ || tbl || $$_history
+                SELECT	nextval('auditor.$$ || sch || $$_$$ || tbl || $$_pkey_seq'),
+                    now(),
+                    SUBSTR(TG_OP,1,1),
+                    OLD.*;
+            RETURN NULL;
+        END;
+        $func$ LANGUAGE 'plpgsql';
+    $$;
+    RETURN TRUE;
+END;
+$creator$ LANGUAGE 'plpgsql';
+
+CREATE FUNCTION auditor.create_auditor_update_trigger ( sch TEXT, tbl TEXT ) RETURNS BOOL AS $creator$
+BEGIN
+    EXECUTE $$
+        CREATE TRIGGER audit_$$ || sch || $$_$$ || tbl || $$_update_trigger
+            AFTER UPDATE OR DELETE ON $$ || sch || $$.$$ || tbl || $$ FOR EACH ROW
+            EXECUTE PROCEDURE auditor.audit_$$ || sch || $$_$$ || tbl || $$_func ();
+    $$;
+	RETURN TRUE;
+END;
+$creator$ LANGUAGE 'plpgsql';
+
+CREATE FUNCTION auditor.create_auditor_lifecycle     ( sch TEXT, tbl TEXT ) RETURNS BOOL AS $creator$
+BEGIN
+    EXECUTE $$
+        CREATE VIEW auditor.$$ || sch || $$_$$ || tbl || $$_lifecycle AS
+            SELECT	-1, now() as audit_time, '-' as audit_action, *
+              FROM	$$ || sch || $$.$$ || tbl || $$
+                UNION ALL
+            SELECT	*
+              FROM	auditor.$$ || sch || $$_$$ || tbl || $$_history;
+    $$;
+	RETURN TRUE;
+END;
+$creator$ LANGUAGE 'plpgsql';
+
+DROP FUNCTION IF EXISTS auditor.create_auditor (TEXT, TEXT);
+
+-- The main event
+
+CREATE FUNCTION auditor.create_auditor ( sch TEXT, tbl TEXT ) RETURNS BOOL AS $creator$
+BEGIN
+    PERFORM auditor.create_auditor_seq(sch, tbl);
+    PERFORM auditor.create_auditor_history(sch, tbl);
+    PERFORM auditor.create_auditor_func(sch, tbl);
+    PERFORM auditor.create_auditor_update_trigger(sch, tbl);
+    PERFORM auditor.create_auditor_lifecycle(sch, tbl);
+	RETURN TRUE;
+END;
+$creator$ LANGUAGE 'plpgsql';
+
+ALTER TABLE action.hold_request ADD COLUMN cut_in_line BOOL;
+
+ALTER TABLE action.hold_request
+ADD COLUMN mint_condition boolean NOT NULL DEFAULT TRUE;
+
+ALTER TABLE action.hold_request
+ADD COLUMN shelf_expire_time TIMESTAMPTZ;
+
+ALTER TABLE action.hold_request DROP CONSTRAINT hold_request_current_copy_fkey;
+
+ALTER TABLE action.hold_request DROP CONSTRAINT hold_request_hold_type_check;
+
+UPDATE config.index_normalizer SET param_count = 0 WHERE func = 'split_date_range';
+
+CREATE INDEX actor_usr_usrgroup_idx ON actor.usr (usrgroup);
+
+-- Add claims_never_checked_out_count to actor.usr, related history
+
+ALTER TABLE actor.usr ADD COLUMN
+	claims_never_checked_out_count  INT         NOT NULL DEFAULT 0;
+
+ALTER TABLE AUDITOR.actor_usr_history ADD COLUMN 
+	claims_never_checked_out_count INT;
+
+DROP VIEW auditor.actor_usr_lifecycle;
+
+SELECT auditor.create_auditor_lifecycle( 'actor', 'usr' );
+
+-----------
+
+CREATE OR REPLACE FUNCTION action.circulation_claims_returned () RETURNS TRIGGER AS $$
+BEGIN
+	IF OLD.stop_fines IS NULL OR OLD.stop_fines <> NEW.stop_fines THEN
+		IF NEW.stop_fines = 'CLAIMSRETURNED' THEN
+			UPDATE actor.usr SET claims_returned_count = claims_returned_count + 1 WHERE id = NEW.usr;
+		END IF;
+		IF NEW.stop_fines = 'CLAIMSNEVERCHECKEDOUT' THEN
+			UPDATE actor.usr SET claims_never_checked_out_count = claims_never_checked_out_count + 1 WHERE id = NEW.usr;
+		END IF;
+		IF NEW.stop_fines = 'LOST' THEN
+			UPDATE asset.copy SET status = 3 WHERE id = NEW.target_copy;
+		END IF;
+	END IF;
+	RETURN NEW;
+END;
+$$ LANGUAGE 'plpgsql';
+
+-- Create new table acq.fund_allocation_percent
+-- Populate it from acq.fund_allocation
+-- Convert all percentages to amounts in acq.fund_allocation
+
+CREATE TABLE acq.fund_allocation_percent
+(
+    id                   SERIAL            PRIMARY KEY,
+    funding_source       INT               NOT NULL REFERENCES acq.funding_source
+                                               DEFERRABLE INITIALLY DEFERRED,
+    org                  INT               NOT NULL REFERENCES actor.org_unit
+                                               DEFERRABLE INITIALLY DEFERRED,
+    fund_code            TEXT,
+    percent              NUMERIC           NOT NULL,
+    allocator            INTEGER           NOT NULL REFERENCES actor.usr
+                                               DEFERRABLE INITIALLY DEFERRED,
+    note                 TEXT,
+    create_time          TIMESTAMPTZ       NOT NULL DEFAULT now(),
+    CONSTRAINT logical_key UNIQUE( funding_source, org, fund_code ),
+    CONSTRAINT percentage_range CHECK( percent >= 0 AND percent <= 100 )
+);
+
+-- Trigger function to validate combination of org_unit and fund_code
+
+CREATE OR REPLACE FUNCTION acq.fund_alloc_percent_val()
+RETURNS TRIGGER AS $$
+--
+DECLARE
+--
+dummy int := 0;
+--
+BEGIN
+    SELECT
+        1
+    INTO
+        dummy
+    FROM
+        acq.fund
+    WHERE
+        org = NEW.org
+        AND code = NEW.fund_code
+        LIMIT 1;
+    --
+    IF dummy = 1 then
+        RETURN NEW;
+    ELSE
+        RAISE EXCEPTION 'No fund exists for org % and code %', NEW.org, NEW.fund_code;
+    END IF;
+END;
+$$ LANGUAGE plpgsql;
+
+CREATE TRIGGER acq_fund_alloc_percent_val_trig
+    BEFORE INSERT OR UPDATE ON acq.fund_allocation_percent
+    FOR EACH ROW EXECUTE PROCEDURE acq.fund_alloc_percent_val();
+
+CREATE OR REPLACE FUNCTION acq.fap_limit_100()
+RETURNS TRIGGER AS $$
+DECLARE
+--
+total_percent numeric;
+--
+BEGIN
+    SELECT
+        sum( percent )
+    INTO
+        total_percent
+    FROM
+        acq.fund_allocation_percent AS fap
+    WHERE
+        fap.funding_source = NEW.funding_source;
+    --
+    IF total_percent > 100 THEN
+        RAISE EXCEPTION 'Total percentages exceed 100 for funding_source %',
+            NEW.funding_source;
+    ELSE
+        RETURN NEW;
+    END IF;
+END;
+$$ LANGUAGE plpgsql;
+
+CREATE TRIGGER acqfap_limit_100_trig
+    AFTER INSERT OR UPDATE ON acq.fund_allocation_percent
+    FOR EACH ROW EXECUTE PROCEDURE acq.fap_limit_100();
+
+-- Populate new table from acq.fund_allocation
+
+INSERT INTO acq.fund_allocation_percent
+(
+    funding_source,
+    org,
+    fund_code,
+    percent,
+    allocator,
+    note,
+    create_time
+)
+    SELECT
+        fa.funding_source,
+        fund.org,
+        fund.code,
+        fa.percent,
+        fa.allocator,
+        fa.note,
+        fa.create_time
+    FROM
+        acq.fund_allocation AS fa
+            INNER JOIN acq.fund AS fund
+                ON ( fa.fund = fund.id )
+    WHERE
+        fa.percent is not null
+    ORDER BY
+        fund.org;
+
+-- Temporary function to convert percentages to amounts in acq.fund_allocation
+
+-- Algorithm to apply to each funding source:
+
+-- 1. Add up the credits.
+-- 2. Add up the percentages.
+-- 3. Multiply the sum of the percentages times the sum of the credits.  Drop any
+--    fractional cents from the result.  This is the total amount to be allocated.
+-- 4. For each allocation: multiply the percentage by the total allocation.  Drop any
+--    fractional cents to get a preliminary amount.
+-- 5. Add up the preliminary amounts for all the allocations.
+-- 6. Subtract the results of step 5 from the result of step 3.  The difference is the
+--    number of residual cents (resulting from having dropped fractional cents) that
+--    must be distributed across the funds in order to make the total of the amounts
+--    match the total allocation.
+-- 7. Make a second pass through the allocations, in decreasing order of the fractional
+--    cents that were dropped from their amounts in step 4.  Add one cent to the amount
+--    for each successive fund, until all the residual cents have been exhausted.
+
+-- Result: the sum of the individual allocations now equals the total to be allocated,
+-- to the penny.  The individual amounts match the percentages as closely as possible,
+-- given the constraint that the total must match.
+
+CREATE OR REPLACE FUNCTION acq.apply_percents()
+RETURNS VOID AS $$
+declare
+--
+tot              RECORD;
+fund             RECORD;
+tot_cents        INTEGER;
+src              INTEGER;
+id               INTEGER[];
+curr_id          INTEGER;
+pennies          NUMERIC[];
+curr_amount      NUMERIC;
+i                INTEGER;
+total_of_floors  INTEGER;
+total_percent    NUMERIC;
+total_allocation INTEGER;
+residue          INTEGER;
+--
+begin
+	RAISE NOTICE 'Applying percents';
+	FOR tot IN
+		SELECT
+			fsrc.funding_source,
+			sum( fsrc.amount ) AS total
+		FROM
+			acq.funding_source_credit AS fsrc
+		WHERE fsrc.funding_source IN
+			( SELECT DISTINCT fa.funding_source
+			  FROM acq.fund_allocation AS fa
+			  WHERE fa.percent IS NOT NULL )
+		GROUP BY
+			fsrc.funding_source
+	LOOP
+		tot_cents = floor( tot.total * 100 );
+		src = tot.funding_source;
+		RAISE NOTICE 'Funding source % total %',
+			src, tot_cents;
+		i := 0;
+		total_of_floors := 0;
+		total_percent := 0;
+		--
+		FOR fund in
+			SELECT
+				fa.id,
+				fa.percent,
+				floor( fa.percent * tot_cents / 100 ) as floor_pennies
+			FROM
+				acq.fund_allocation AS fa
+			WHERE
+				fa.funding_source = src
+				AND fa.percent IS NOT NULL
+			ORDER BY
+				mod( fa.percent * tot_cents / 100, 1 ),
+				fa.fund,
+				fa.id
+		LOOP
+			RAISE NOTICE '   %: %',
+				fund.id,
+				fund.floor_pennies;
+			i := i + 1;
+			id[i] = fund.id;
+			pennies[i] = fund.floor_pennies;
+			total_percent := total_percent + fund.percent;
+			total_of_floors := total_of_floors + pennies[i];
+		END LOOP;
+		total_allocation := floor( total_percent * tot_cents /100 );
+		RAISE NOTICE 'Total before distributing residue: %', total_of_floors;
+		residue := total_allocation - total_of_floors;
+		RAISE NOTICE 'Residue: %', residue;
+		--
+		-- Post the calculated amounts, revising as needed to
+		-- distribute the rounding error
+		--
+		WHILE i > 0 LOOP
+			IF residue > 0 THEN
+				pennies[i] = pennies[i] + 1;
+				residue := residue - 1;
+			END IF;
+			--
+			-- Post amount
+			--
+			curr_id     := id[i];
+			curr_amount := trunc( pennies[i] / 100, 2 );
+			--
+			UPDATE
+				acq.fund_allocation AS fa
+			SET
+				amount = curr_amount,
+				percent = NULL
+			WHERE
+				fa.id = curr_id;
+			--
+			RAISE NOTICE '   ID % and amount %',
+				curr_id,
+				curr_amount;
+			i = i - 1;
+		END LOOP;
+	END LOOP;
+end;
+$$ LANGUAGE 'plpgsql';
+
+-- Run the temporary function
+
+select * from acq.apply_percents();
+
+-- Drop the temporary function now that we're done with it
+
+DROP FUNCTION IF EXISTS acq.apply_percents();
+
+-- Eliminate acq.fund_allocation.percent, which has been moved to the acq.fund_allocation_percent table.
+
+-- If the following step fails, it's probably because there are still some non-null percent values in
+-- acq.fund_allocation.  They should have all been converted to amounts, and then set to null, by a
+-- previous upgrade step based on 0049.schema.acq_funding_allocation_percent.sql.  If there are any
+-- non-null values, then either that step didn't run, or it didn't work, or some non-null values
+-- slipped in afterwards.
+
+-- To convert any remaining percents to amounts: create, run, and then drop the temporary stored
+-- procedure acq.apply_percents() as defined above.
+
+ALTER TABLE acq.fund_allocation
+ALTER COLUMN amount SET NOT NULL;
+
+CREATE OR REPLACE VIEW acq.fund_allocation_total AS
+    SELECT  fund,
+            SUM(a.amount * acq.exchange_ratio(s.currency_type, f.currency_type))::NUMERIC(100,2) AS amount
+    FROM acq.fund_allocation a
+         JOIN acq.fund f ON (a.fund = f.id)
+         JOIN acq.funding_source s ON (a.funding_source = s.id)
+    GROUP BY 1;
+
+CREATE OR REPLACE VIEW acq.funding_source_allocation_total AS
+    SELECT  funding_source,
+            SUM(a.amount)::NUMERIC(100,2) AS amount
+    FROM  acq.fund_allocation a
+    GROUP BY 1;
+
+ALTER TABLE acq.fund_allocation
+DROP COLUMN percent;
+
+CREATE TABLE asset.copy_location_order
+(
+	id              SERIAL           PRIMARY KEY,
+	location        INT              NOT NULL
+	                                     REFERENCES asset.copy_location
+	                                     ON DELETE CASCADE
+	                                     DEFERRABLE INITIALLY DEFERRED,
+	org             INT              NOT NULL
+	                                     REFERENCES actor.org_unit
+	                                     ON DELETE CASCADE
+	                                     DEFERRABLE INITIALLY DEFERRED,
+	position        INT              NOT NULL DEFAULT 0,
+	CONSTRAINT acplo_once_per_org UNIQUE ( location, org )
+);
+
+ALTER TABLE money.credit_card_payment ADD COLUMN cc_processor TEXT;
+
+-- If you ran this before its most recent incarnation:
+-- delete from config.upgrade_log where version = '0328';
+-- alter table money.credit_card_payment drop column cc_name;
+
+ALTER TABLE money.credit_card_payment ADD COLUMN cc_first_name TEXT;
+ALTER TABLE money.credit_card_payment ADD COLUMN cc_last_name TEXT;
+
+CREATE OR REPLACE FUNCTION action.find_circ_matrix_matchpoint( context_ou INT, match_item BIGINT, match_user INT, renewal BOOL ) RETURNS config.circ_matrix_matchpoint AS $func$
+DECLARE
+    current_group    permission.grp_tree%ROWTYPE;
+    user_object    actor.usr%ROWTYPE;
+    item_object    asset.copy%ROWTYPE;
+    cn_object    asset.call_number%ROWTYPE;
+    rec_descriptor    metabib.rec_descriptor%ROWTYPE;
+    current_mp    config.circ_matrix_matchpoint%ROWTYPE;
+    matchpoint    config.circ_matrix_matchpoint%ROWTYPE;
+BEGIN
+    SELECT INTO user_object * FROM actor.usr WHERE id = match_user;
+    SELECT INTO item_object * FROM asset.copy WHERE id = match_item;
+    SELECT INTO cn_object * FROM asset.call_number WHERE id = item_object.call_number;
+    SELECT INTO rec_descriptor r.* FROM metabib.rec_descriptor r JOIN asset.call_number c USING (record) WHERE c.id = item_object.call_number;
+    SELECT INTO current_group * FROM permission.grp_tree WHERE id = user_object.profile;
+
+    LOOP 
+        -- for each potential matchpoint for this ou and group ...
+        FOR current_mp IN
+            SELECT  m.*
+              FROM  config.circ_matrix_matchpoint m
+                    JOIN actor.org_unit_ancestors( context_ou ) d ON (m.org_unit = d.id)
+                    LEFT JOIN actor.org_unit_proximity p ON (p.from_org = context_ou AND p.to_org = d.id)
+              WHERE m.grp = current_group.id
+                    AND m.active
+                    AND (m.copy_owning_lib IS NULL OR cn_object.owning_lib IN ( SELECT id FROM actor.org_unit_descendants(m.copy_owning_lib) ))
+                    AND (m.copy_circ_lib   IS NULL OR item_object.circ_lib IN ( SELECT id FROM actor.org_unit_descendants(m.copy_circ_lib)   ))
+              ORDER BY    CASE WHEN p.prox        IS NULL THEN 999 ELSE p.prox END,
+                    CASE WHEN m.copy_owning_lib IS NOT NULL
+                        THEN 256 / ( SELECT COALESCE(prox, 255) + 1 FROM actor.org_unit_proximity WHERE to_org = cn_object.owning_lib AND from_org = m.copy_owning_lib LIMIT 1 )
+                        ELSE 0
+                    END +
+                    CASE WHEN m.copy_circ_lib IS NOT NULL
+                        THEN 256 / ( SELECT COALESCE(prox, 255) + 1 FROM actor.org_unit_proximity WHERE to_org = item_object.circ_lib AND from_org = m.copy_circ_lib LIMIT 1 )
+                        ELSE 0
+                    END +
+                    CASE WHEN m.is_renewal = renewal        THEN 128 ELSE 0 END +
+                    CASE WHEN m.juvenile_flag    IS NOT NULL THEN 64 ELSE 0 END +
+                    CASE WHEN m.circ_modifier    IS NOT NULL THEN 32 ELSE 0 END +
+                    CASE WHEN m.marc_type        IS NOT NULL THEN 16 ELSE 0 END +
+                    CASE WHEN m.marc_form        IS NOT NULL THEN 8 ELSE 0 END +
+                    CASE WHEN m.marc_vr_format    IS NOT NULL THEN 4 ELSE 0 END +
+                    CASE WHEN m.ref_flag        IS NOT NULL THEN 2 ELSE 0 END +
+                    CASE WHEN m.usr_age_lower_bound    IS NOT NULL THEN 0.5 ELSE 0 END +
+                    CASE WHEN m.usr_age_upper_bound    IS NOT NULL THEN 0.5 ELSE 0 END DESC LOOP
+
+            IF current_mp.is_renewal IS NOT NULL THEN
+                CONTINUE WHEN current_mp.is_renewal <> renewal;
+            END IF;
+
+            IF current_mp.circ_modifier IS NOT NULL THEN
+                CONTINUE WHEN current_mp.circ_modifier <> item_object.circ_modifier OR item_object.circ_modifier IS NULL;
+            END IF;
+
+            IF current_mp.marc_type IS NOT NULL THEN
+                IF item_object.circ_as_type IS NOT NULL THEN
+                    CONTINUE WHEN current_mp.marc_type <> item_object.circ_as_type;
+                ELSE
+                    CONTINUE WHEN current_mp.marc_type <> rec_descriptor.item_type;
+                END IF;
+            END IF;
+
+            IF current_mp.marc_form IS NOT NULL THEN
+                CONTINUE WHEN current_mp.marc_form <> rec_descriptor.item_form;
+            END IF;
+
+            IF current_mp.marc_vr_format IS NOT NULL THEN
+                CONTINUE WHEN current_mp.marc_vr_format <> rec_descriptor.vr_format;
+            END IF;
+
+            IF current_mp.ref_flag IS NOT NULL THEN
+                CONTINUE WHEN current_mp.ref_flag <> item_object.ref;
+            END IF;
+
+            IF current_mp.juvenile_flag IS NOT NULL THEN
+                CONTINUE WHEN current_mp.juvenile_flag <> user_object.juvenile;
+            END IF;
+
+            IF current_mp.usr_age_lower_bound IS NOT NULL THEN
+                CONTINUE WHEN user_object.dob IS NULL OR current_mp.usr_age_lower_bound < age(user_object.dob);
+            END IF;
+
+            IF current_mp.usr_age_upper_bound IS NOT NULL THEN
+                CONTINUE WHEN user_object.dob IS NULL OR current_mp.usr_age_upper_bound > age(user_object.dob);
+            END IF;
+
+
+            -- everything was undefined or matched
+            matchpoint = current_mp;
+
+            EXIT WHEN matchpoint.id IS NOT NULL;
+        END LOOP;
+
+        EXIT WHEN current_group.parent IS NULL OR matchpoint.id IS NOT NULL;
+
+        SELECT INTO current_group * FROM permission.grp_tree WHERE id = current_group.parent;
+    END LOOP;
+
+    RETURN matchpoint;
+END;
+$func$ LANGUAGE plpgsql;
+
+CREATE TYPE action.hold_stats AS (
+    hold_count              INT,
+    copy_count              INT,
+    available_count         INT,
+    total_copy_ratio        FLOAT,
+    available_copy_ratio    FLOAT
+);
+
+CREATE OR REPLACE FUNCTION action.copy_related_hold_stats (copy_id INT) RETURNS action.hold_stats AS $func$
+DECLARE
+    output          action.hold_stats%ROWTYPE;
+    hold_count      INT := 0;
+    copy_count      INT := 0;
+    available_count INT := 0;
+    hold_map_data   RECORD;
+BEGIN
+
+    output.hold_count := 0;
+    output.copy_count := 0;
+    output.available_count := 0;
+
+    SELECT  COUNT( DISTINCT m.hold ) INTO hold_count
+      FROM  action.hold_copy_map m
+            JOIN action.hold_request h ON (m.hold = h.id)
+      WHERE m.target_copy = copy_id
+            AND NOT h.frozen;
+
+    output.hold_count := hold_count;
+
+    IF output.hold_count > 0 THEN
+        FOR hold_map_data IN
+            SELECT  DISTINCT m.target_copy,
+                    acp.status
+              FROM  action.hold_copy_map m
+                    JOIN asset.copy acp ON (m.target_copy = acp.id)
+                    JOIN action.hold_request h ON (m.hold = h.id)
+              WHERE m.hold IN ( SELECT DISTINCT hold FROM action.hold_copy_map WHERE target_copy = copy_id ) AND NOT h.frozen
+        LOOP
+            output.copy_count := output.copy_count + 1;
+            IF hold_map_data.status IN (0,7,12) THEN
+                output.available_count := output.available_count + 1;
+            END IF;
+        END LOOP;
+        output.total_copy_ratio = output.copy_count::FLOAT / output.hold_count::FLOAT;
+        output.available_copy_ratio = output.available_count::FLOAT / output.hold_count::FLOAT;
+
+    END IF;
+
+    RETURN output;
+
+END;
+$func$ LANGUAGE PLPGSQL;
+
+ALTER TABLE config.circ_matrix_matchpoint ADD COLUMN total_copy_hold_ratio FLOAT;
+ALTER TABLE config.circ_matrix_matchpoint ADD COLUMN available_copy_hold_ratio FLOAT;
+
+ALTER TABLE config.circ_matrix_matchpoint DROP CONSTRAINT ep_once_per_grp_loc_mod_marc;
+
+ALTER TABLE config.circ_matrix_matchpoint ADD COLUMN copy_circ_lib   INT REFERENCES actor.org_unit (id) DEFERRABLE INITIALLY DEFERRED;
+ALTER TABLE config.circ_matrix_matchpoint ADD COLUMN copy_owning_lib INT REFERENCES actor.org_unit (id) DEFERRABLE INITIALLY DEFERRED;
+
+ALTER TABLE config.circ_matrix_matchpoint ADD CONSTRAINT ep_once_per_grp_loc_mod_marc UNIQUE (
+    grp, org_unit, circ_modifier, marc_type, marc_form, marc_vr_format, ref_flag,
+    juvenile_flag, usr_age_lower_bound, usr_age_upper_bound, is_renewal, copy_circ_lib,
+    copy_owning_lib
+);
+
+-- Return the correct fail_part when the item can't be found
+CREATE OR REPLACE FUNCTION action.item_user_circ_test( circ_ou INT, match_item BIGINT, match_user INT, renewal BOOL ) RETURNS SETOF action.matrix_test_result AS $func$
+DECLARE
+    user_object        actor.usr%ROWTYPE;
+    standing_penalty    config.standing_penalty%ROWTYPE;
+    item_object        asset.copy%ROWTYPE;
+    item_status_object    config.copy_status%ROWTYPE;
+    item_location_object    asset.copy_location%ROWTYPE;
+    result            action.matrix_test_result;
+    circ_test        config.circ_matrix_matchpoint%ROWTYPE;
+    out_by_circ_mod        config.circ_matrix_circ_mod_test%ROWTYPE;
+    circ_mod_map        config.circ_matrix_circ_mod_test_map%ROWTYPE;
+    hold_ratio          action.hold_stats%ROWTYPE;
+    penalty_type         TEXT;
+    tmp_grp         INT;
+    items_out        INT;
+    context_org_list        INT[];
+    done            BOOL := FALSE;
+BEGIN
+    result.success := TRUE;
+
+    -- Fail if the user is BARRED
+    SELECT INTO user_object * FROM actor.usr WHERE id = match_user;
+
+    -- Fail if we couldn't find the user 
+    IF user_object.id IS NULL THEN
+        result.fail_part := 'no_user';
+        result.success := FALSE;
+        done := TRUE;
+        RETURN NEXT result;
+        RETURN;
+    END IF;
+
+    SELECT INTO item_object * FROM asset.copy WHERE id = match_item;
+
+    -- Fail if we couldn't find the item 
+    IF item_object.id IS NULL THEN
+        result.fail_part := 'no_item';
+        result.success := FALSE;
+        done := TRUE;
+        RETURN NEXT result;
+        RETURN;
+    END IF;
+
+    SELECT INTO circ_test * FROM action.find_circ_matrix_matchpoint(circ_ou, match_item, match_user, renewal);
+    result.matchpoint := circ_test.id;
+
+    -- Fail if we couldn't find a matchpoint
+    IF result.matchpoint IS NULL THEN
+        result.fail_part := 'no_matchpoint';
+        result.success := FALSE;
+        done := TRUE;
+        RETURN NEXT result;
+    END IF;
+
+    IF user_object.barred IS TRUE THEN
+        result.fail_part := 'actor.usr.barred';
+        result.success := FALSE;
+        done := TRUE;
+        RETURN NEXT result;
+    END IF;
+
+    -- Fail if the item can't circulate
+    IF item_object.circulate IS FALSE THEN
+        result.fail_part := 'asset.copy.circulate';
+        result.success := FALSE;
+        done := TRUE;
+        RETURN NEXT result;
+    END IF;
+
+    -- Fail if the item isn't in a circulateable status on a non-renewal
+    IF NOT renewal AND item_object.status NOT IN ( 0, 7, 8 ) THEN
+        result.fail_part := 'asset.copy.status';
+        result.success := FALSE;
+        done := TRUE;
+        RETURN NEXT result;
+    ELSIF renewal AND item_object.status <> 1 THEN
+        result.fail_part := 'asset.copy.status';
+        result.success := FALSE;
+        done := TRUE;
+        RETURN NEXT result;
+    END IF;
+
+    -- Fail if the item can't circulate because of the shelving location
+    SELECT INTO item_location_object * FROM asset.copy_location WHERE id = item_object.location;
+    IF item_location_object.circulate IS FALSE THEN
+        result.fail_part := 'asset.copy_location.circulate';
+        result.success := FALSE;
+        done := TRUE;
+        RETURN NEXT result;
+    END IF;
+
+    SELECT INTO context_org_list ARRAY_ACCUM(id) FROM actor.org_unit_full_path( circ_test.org_unit );
+
+    -- Fail if the test is set to hard non-circulating
+    IF circ_test.circulate IS FALSE THEN
+        result.fail_part := 'config.circ_matrix_test.circulate';
+        result.success := FALSE;
+        done := TRUE;
+        RETURN NEXT result;
+    END IF;
+
+    -- Fail if the total copy-hold ratio is too low
+    IF circ_test.total_copy_hold_ratio IS NOT NULL THEN
+        SELECT INTO hold_ratio * FROM action.copy_related_hold_stats(match_item);
+        IF hold_ratio.total_copy_ratio IS NOT NULL AND hold_ratio.total_copy_ratio < circ_test.total_copy_hold_ratio THEN
+            result.fail_part := 'config.circ_matrix_test.total_copy_hold_ratio';
+            result.success := FALSE;
+            done := TRUE;
+            RETURN NEXT result;
+        END IF;
+    END IF;
+
+    -- Fail if the available copy-hold ratio is too low
+    IF circ_test.available_copy_hold_ratio IS NOT NULL THEN
+        SELECT INTO hold_ratio * FROM action.copy_related_hold_stats(match_item);
+        IF hold_ratio.available_copy_ratio IS NOT NULL AND hold_ratio.available_copy_ratio < circ_test.available_copy_hold_ratio THEN
+            result.fail_part := 'config.circ_matrix_test.available_copy_hold_ratio';
+            result.success := FALSE;
+            done := TRUE;
+            RETURN NEXT result;
+        END IF;
+    END IF;
+
+    IF renewal THEN
+        penalty_type = '%RENEW%';
+    ELSE
+        penalty_type = '%CIRC%';
+    END IF;
+
+    FOR standing_penalty IN
+        SELECT  DISTINCT csp.*
+          FROM  actor.usr_standing_penalty usp
+                JOIN config.standing_penalty csp ON (csp.id = usp.standing_penalty)
+          WHERE usr = match_user
+                AND usp.org_unit IN ( SELECT * FROM explode_array(context_org_list) )
+                AND (usp.stop_date IS NULL or usp.stop_date > NOW())
+                AND csp.block_list LIKE penalty_type LOOP
+
+        result.fail_part := standing_penalty.name;
+        result.success := FALSE;
+        done := TRUE;
+        RETURN NEXT result;
+    END LOOP;
+
+    -- Fail if the user has too many items with specific circ_modifiers checked out
+    FOR out_by_circ_mod IN SELECT * FROM config.circ_matrix_circ_mod_test WHERE matchpoint = circ_test.id LOOP
+        SELECT  INTO items_out COUNT(*)
+          FROM  action.circulation circ
+            JOIN asset.copy cp ON (cp.id = circ.target_copy)
+          WHERE circ.usr = match_user
+               AND circ.circ_lib IN ( SELECT * FROM explode_array(context_org_list) )
+            AND circ.checkin_time IS NULL
+            AND (circ.stop_fines IN ('MAXFINES','LONGOVERDUE') OR circ.stop_fines IS NULL)
+            AND cp.circ_modifier IN (SELECT circ_mod FROM config.circ_matrix_circ_mod_test_map WHERE circ_mod_test = out_by_circ_mod.id);
+        IF items_out >= out_by_circ_mod.items_out THEN
+            result.fail_part := 'config.circ_matrix_circ_mod_test';
+            result.success := FALSE;
+            done := TRUE;
+            RETURN NEXT result;
+        END IF;
+    END LOOP;
+
+    -- If we passed everything, return the successful matchpoint id
+    IF NOT done THEN
+        RETURN NEXT result;
+    END IF;
+
+    RETURN;
+END;
+$func$ LANGUAGE plpgsql;
+
+CREATE TABLE config.remote_account (
+    id          SERIAL  PRIMARY KEY,
+    label       TEXT    NOT NULL,
+    host        TEXT    NOT NULL,   -- name or IP, :port optional
+    username    TEXT,               -- optional, since we could default to $USER
+    password    TEXT,               -- optional, since we could use SSH keys, or anonymous login.
+    account     TEXT,               -- aka profile or FTP "account" command
+    path        TEXT,               -- aka directory
+    owner       INT     NOT NULL REFERENCES actor.org_unit (id) DEFERRABLE INITIALLY DEFERRED,
+    last_activity TIMESTAMP WITH TIME ZONE
+);
+
+CREATE TABLE acq.edi_account (      -- similar tables can extend remote_account for other parts of EG
+    provider    INT     NOT NULL REFERENCES acq.provider          (id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED,
+    in_dir      TEXT,   -- incoming messages dir (probably different than config.remote_account.path, the outgoing dir)
+	vendcode    TEXT,
+	vendacct    TEXT
+
+) INHERITS (config.remote_account);
+
+ALTER TABLE acq.edi_account ADD PRIMARY KEY (id);
+
+CREATE TABLE acq.claim_type (
+	id             SERIAL           PRIMARY KEY,
+	org_unit       INT              NOT NULL REFERENCES actor.org_unit(id)
+	                                         DEFERRABLE INITIALLY DEFERRED,
+	code           TEXT             NOT NULL,
+	description    TEXT             NOT NULL,
+	CONSTRAINT claim_type_once_per_org UNIQUE ( org_unit, code )
+);
+
+CREATE TABLE acq.claim (
+	id             SERIAL           PRIMARY KEY,
+	type           INT              NOT NULL REFERENCES acq.claim_type
+	                                         DEFERRABLE INITIALLY DEFERRED,
+	lineitem_detail BIGINT          NOT NULL REFERENCES acq.lineitem_detail
+	                                         DEFERRABLE INITIALLY DEFERRED
+);
+
+CREATE TABLE acq.claim_policy (
+	id              SERIAL       PRIMARY KEY,
+	org_unit        INT          NOT NULL REFERENCES actor.org_unit
+	                             DEFERRABLE INITIALLY DEFERRED,
+	name            TEXT         NOT NULL,
+	description     TEXT         NOT NULL,
+	CONSTRAINT name_once_per_org UNIQUE (org_unit, name)
+);
+
+-- Add a san column for EDI. 
+-- See: http://isbn.org/standards/home/isbn/us/san/san-qa.asp
+
+ALTER TABLE acq.provider ADD COLUMN san INT;
+
+ALTER TABLE acq.provider ALTER COLUMN san TYPE TEXT USING lpad(text(san), 7, '0');
+
+-- null edi_default is OK... it has to be, since we have no values in acq.edi_account yet
+ALTER TABLE acq.provider ADD COLUMN edi_default INT REFERENCES acq.edi_account (id) DEFERRABLE INITIALLY DEFERRED;
+
+ALTER TABLE acq.provider
+	ADD COLUMN active BOOL NOT NULL DEFAULT TRUE;
+
+ALTER TABLE acq.provider
+	ADD COLUMN prepayment_required BOOLEAN NOT NULL DEFAULT FALSE;
+
+ALTER TABLE acq.provider
+	ADD COLUMN url TEXT;
+
+ALTER TABLE acq.provider
+	ADD COLUMN email TEXT;
+
+ALTER TABLE acq.provider
+	ADD COLUMN phone TEXT;
+
+ALTER TABLE acq.provider
+	ADD COLUMN fax_phone TEXT;
+
+ALTER TABLE acq.provider
+	ADD COLUMN default_claim_policy INT
+		REFERENCES acq.claim_policy
+		DEFERRABLE INITIALLY DEFERRED;
+
+ALTER TABLE action.transit_copy
+ADD COLUMN prev_dest INTEGER REFERENCES actor.org_unit( id )
+							 DEFERRABLE INITIALLY DEFERRED;
+
+DROP SCHEMA IF EXISTS booking CASCADE;
+
+CREATE SCHEMA booking;
+
+CREATE TABLE booking.resource_type (
+	id             SERIAL          PRIMARY KEY,
+	name           TEXT            NOT NULL,
+	fine_interval  INTERVAL,
+	fine_amount    DECIMAL(8,2)    NOT NULL DEFAULT 0,
+	owner          INT             NOT NULL
+	                               REFERENCES actor.org_unit( id )
+	                               DEFERRABLE INITIALLY DEFERRED,
+	catalog_item   BOOLEAN         NOT NULL DEFAULT FALSE,
+	transferable   BOOLEAN         NOT NULL DEFAULT FALSE,
+    record         BIGINT          REFERENCES biblio.record_entry (id)
+	                               DEFERRABLE INITIALLY DEFERRED,
+    max_fine       NUMERIC(8,2),
+    elbow_room     INTERVAL,
+    CONSTRAINT brt_name_or_record_once_per_owner UNIQUE(owner, name, record)
+);
+
+CREATE TABLE booking.resource (
+	id             SERIAL           PRIMARY KEY,
+	owner          INT              NOT NULL
+	                                REFERENCES actor.org_unit(id)
+	                                DEFERRABLE INITIALLY DEFERRED,
+	type           INT              NOT NULL
+	                                REFERENCES booking.resource_type(id)
+	                                DEFERRABLE INITIALLY DEFERRED,
+	overbook       BOOLEAN          NOT NULL DEFAULT FALSE,
+	barcode        TEXT             NOT NULL,
+	deposit        BOOLEAN          NOT NULL DEFAULT FALSE,
+	deposit_amount DECIMAL(8,2)     NOT NULL DEFAULT 0.00,
+	user_fee       DECIMAL(8,2)     NOT NULL DEFAULT 0.00,
+	CONSTRAINT br_unique UNIQUE (owner, barcode)
+);
+
+-- For non-catalog items: hijack barcode for name/description
+
+CREATE TABLE booking.resource_attr (
+	id              SERIAL          PRIMARY KEY,
+	owner           INT             NOT NULL
+	                                REFERENCES actor.org_unit(id)
+	                                DEFERRABLE INITIALLY DEFERRED,
+	name            TEXT            NOT NULL,
+	resource_type   INT             NOT NULL
+	                                REFERENCES booking.resource_type(id)
+	                                ON DELETE CASCADE
+	                                DEFERRABLE INITIALLY DEFERRED,
+	required        BOOLEAN         NOT NULL DEFAULT FALSE,
+	CONSTRAINT bra_name_once_per_type UNIQUE(resource_type, name)
+);
+
+CREATE TABLE booking.resource_attr_value (
+	id               SERIAL         PRIMARY KEY,
+	owner            INT            NOT NULL
+	                                REFERENCES actor.org_unit(id)
+	                                DEFERRABLE INITIALLY DEFERRED,
+	attr             INT            NOT NULL
+	                                REFERENCES booking.resource_attr(id)
+	                                DEFERRABLE INITIALLY DEFERRED,
+	valid_value      TEXT           NOT NULL,
+	CONSTRAINT brav_logical_key UNIQUE(owner, attr, valid_value)
+);
+
+CREATE TABLE booking.resource_attr_map (
+	id               SERIAL         PRIMARY KEY,
+	resource         INT            NOT NULL
+	                                REFERENCES booking.resource(id)
+	                                ON DELETE CASCADE
+	                                DEFERRABLE INITIALLY DEFERRED,
+	resource_attr    INT            NOT NULL
+	                                REFERENCES booking.resource_attr(id)
+	                                ON DELETE CASCADE
+	                                DEFERRABLE INITIALLY DEFERRED,
+	value            INT            NOT NULL
+	                                REFERENCES booking.resource_attr_value(id)
+	                                DEFERRABLE INITIALLY DEFERRED,
+	CONSTRAINT bram_one_value_per_attr UNIQUE(resource, resource_attr)
+);
+
+CREATE TABLE booking.reservation (
+	request_time     TIMESTAMPTZ   NOT NULL DEFAULT now(),
+	start_time       TIMESTAMPTZ,
+	end_time         TIMESTAMPTZ,
+	capture_time     TIMESTAMPTZ,
+	cancel_time      TIMESTAMPTZ,
+	pickup_time      TIMESTAMPTZ,
+	return_time      TIMESTAMPTZ,
+	booking_interval INTERVAL,
+	fine_interval    INTERVAL,
+	fine_amount      DECIMAL(8,2),
+	target_resource_type  INT       NOT NULL
+	                                REFERENCES booking.resource_type(id)
+	                                ON DELETE CASCADE
+	                                DEFERRABLE INITIALLY DEFERRED,
+	target_resource  INT            REFERENCES booking.resource(id)
+	                                ON DELETE CASCADE
+	                                DEFERRABLE INITIALLY DEFERRED,
+	current_resource INT            REFERENCES booking.resource(id)
+	                                ON DELETE CASCADE
+	                                DEFERRABLE INITIALLY DEFERRED,
+	request_lib      INT            NOT NULL
+	                                REFERENCES actor.org_unit(id)
+	                                DEFERRABLE INITIALLY DEFERRED,
+	pickup_lib       INT            REFERENCES actor.org_unit(id)
+	                                DEFERRABLE INITIALLY DEFERRED,
+	capture_staff    INT            REFERENCES actor.usr(id)
+	                                DEFERRABLE INITIALLY DEFERRED,
+    max_fine         NUMERIC(8,2)
+) INHERITS (money.billable_xact);
+
+ALTER TABLE booking.reservation ADD PRIMARY KEY (id);
+
+ALTER TABLE booking.reservation
+	ADD CONSTRAINT booking_reservation_usr_fkey
+	FOREIGN KEY (usr) REFERENCES actor.usr (id)
+	DEFERRABLE INITIALLY DEFERRED;
+
+CREATE TABLE booking.reservation_attr_value_map (
+	id               SERIAL         PRIMARY KEY,
+	reservation      INT            NOT NULL
+	                                REFERENCES booking.reservation(id)
+	                                ON DELETE CASCADE
+	                                DEFERRABLE INITIALLY DEFERRED,
+	attr_value       INT            NOT NULL
+	                                REFERENCES booking.resource_attr_value(id)
+	                                ON DELETE CASCADE
+	                                DEFERRABLE INITIALLY DEFERRED,
+	CONSTRAINT bravm_logical_key UNIQUE(reservation, attr_value)
+);
+
+-- represents a circ chain summary
+CREATE TYPE action.circ_chain_summary AS (
+    num_circs INTEGER,
+    start_time TIMESTAMP WITH TIME ZONE,
+    checkout_workstation TEXT,
+    last_renewal_time TIMESTAMP WITH TIME ZONE, -- NULL if no renewals
+    last_stop_fines TEXT,
+    last_stop_fines_time TIMESTAMP WITH TIME ZONE,
+    last_renewal_workstation TEXT, -- NULL if no renewals
+    last_checkin_workstation TEXT,
+    last_checkin_time TIMESTAMP WITH TIME ZONE,
+    last_checkin_scan_time TIMESTAMP WITH TIME ZONE
+);
+
+CREATE OR REPLACE FUNCTION action.circ_chain ( ctx_circ_id INTEGER ) RETURNS SETOF action.circulation AS $$
+DECLARE
+    tmp_circ action.circulation%ROWTYPE;
+    circ_0 action.circulation%ROWTYPE;
+BEGIN
+
+    SELECT INTO tmp_circ * FROM action.circulation WHERE id = ctx_circ_id;
+
+    IF tmp_circ IS NULL THEN
+        RETURN NEXT tmp_circ;
+    END IF;
+    circ_0 := tmp_circ;
+
+    -- find the front of the chain
+    WHILE TRUE LOOP
+        SELECT INTO tmp_circ * FROM action.circulation WHERE id = tmp_circ.parent_circ;
+        IF tmp_circ IS NULL THEN
+            EXIT;
+        END IF;
+        circ_0 := tmp_circ;
+    END LOOP;
+
+    -- now send the circs to the caller, oldest to newest
+    tmp_circ := circ_0;
+    WHILE TRUE LOOP
+        IF tmp_circ IS NULL THEN
+            EXIT;
+        END IF;
+        RETURN NEXT tmp_circ;
+        SELECT INTO tmp_circ * FROM action.circulation WHERE parent_circ = tmp_circ.id;
+    END LOOP;
+
+END;
+$$ LANGUAGE 'plpgsql';
+
+CREATE OR REPLACE FUNCTION action.summarize_circ_chain ( ctx_circ_id INTEGER ) RETURNS action.circ_chain_summary AS $$
+
+DECLARE
+
+    -- first circ in the chain
+    circ_0 action.circulation%ROWTYPE;
+
+    -- last circ in the chain
+    circ_n action.circulation%ROWTYPE;
+
+    -- circ chain under construction
+    chain action.circ_chain_summary;
+    tmp_circ action.circulation%ROWTYPE;
+
+BEGIN
+    
+    chain.num_circs := 0;
+    FOR tmp_circ IN SELECT * FROM action.circ_chain(ctx_circ_id) LOOP
+
+        IF chain.num_circs = 0 THEN
+            circ_0 := tmp_circ;
+        END IF;
+
+        chain.num_circs := chain.num_circs + 1;
+        circ_n := tmp_circ;
+    END LOOP;
+
+    chain.start_time := circ_0.xact_start;
+    chain.last_stop_fines := circ_n.stop_fines;
+    chain.last_stop_fines_time := circ_n.stop_fines_time;
+    chain.last_checkin_time := circ_n.checkin_time;
+    chain.last_checkin_scan_time := circ_n.checkin_scan_time;
+    SELECT INTO chain.checkout_workstation name FROM actor.workstation WHERE id = circ_0.workstation;
+    SELECT INTO chain.last_checkin_workstation name FROM actor.workstation WHERE id = circ_n.checkin_workstation;
+
+    IF chain.num_circs > 1 THEN
+        chain.last_renewal_time := circ_n.xact_start;
+        SELECT INTO chain.last_renewal_workstation name FROM actor.workstation WHERE id = circ_n.workstation;
+    END IF;
+
+    RETURN chain;
+
+END;
+$$ LANGUAGE 'plpgsql';
+
+CREATE TRIGGER mat_summary_create_tgr AFTER INSERT ON booking.reservation FOR EACH ROW EXECUTE PROCEDURE money.mat_summary_create ('reservation');
+CREATE TRIGGER mat_summary_change_tgr AFTER UPDATE ON booking.reservation FOR EACH ROW EXECUTE PROCEDURE money.mat_summary_update ();
+CREATE TRIGGER mat_summary_remove_tgr AFTER DELETE ON booking.reservation FOR EACH ROW EXECUTE PROCEDURE money.mat_summary_delete ();
+
+ALTER TABLE config.standing_penalty
+	ADD COLUMN org_depth   INTEGER;
+
+CREATE OR REPLACE FUNCTION actor.calculate_system_penalties( match_user INT, context_org INT ) RETURNS SETOF actor.usr_standing_penalty AS $func$
+DECLARE
+    user_object         actor.usr%ROWTYPE;
+    new_sp_row          actor.usr_standing_penalty%ROWTYPE;
+    existing_sp_row     actor.usr_standing_penalty%ROWTYPE;
+    collections_fines   permission.grp_penalty_threshold%ROWTYPE;
+    max_fines           permission.grp_penalty_threshold%ROWTYPE;
+    max_overdue         permission.grp_penalty_threshold%ROWTYPE;
+    max_items_out       permission.grp_penalty_threshold%ROWTYPE;
+    tmp_grp             INT;
+    items_overdue       INT;
+    items_out           INT;
+    context_org_list    INT[];
+    current_fines        NUMERIC(8,2) := 0.0;
+    tmp_fines            NUMERIC(8,2);
+    tmp_groc            RECORD;
+    tmp_circ            RECORD;
+    tmp_org             actor.org_unit%ROWTYPE;
+    tmp_penalty         config.standing_penalty%ROWTYPE;
+    tmp_depth           INTEGER;
+BEGIN
+    SELECT INTO user_object * FROM actor.usr WHERE id = match_user;
+
+    -- Max fines
+    SELECT INTO tmp_org * FROM actor.org_unit WHERE id = context_org;
+
+    -- Fail if the user has a high fine balance
+    LOOP
+        tmp_grp := user_object.profile;
+        LOOP
+            SELECT * INTO max_fines FROM permission.grp_penalty_threshold WHERE grp = tmp_grp AND penalty = 1 AND org_unit = tmp_org.id;
+
+            IF max_fines.threshold IS NULL THEN
+                SELECT parent INTO tmp_grp FROM permission.grp_tree WHERE id = tmp_grp;
+            ELSE
+                EXIT;
+            END IF;
+
+            IF tmp_grp IS NULL THEN
+                EXIT;
+            END IF;
+        END LOOP;
+
+        IF max_fines.threshold IS NOT NULL OR tmp_org.parent_ou IS NULL THEN
+            EXIT;
+        END IF;
+
+        SELECT * INTO tmp_org FROM actor.org_unit WHERE id = tmp_org.parent_ou;
+
+    END LOOP;
+
+    IF max_fines.threshold IS NOT NULL THEN
+
+        FOR existing_sp_row IN
+                SELECT  *
+                  FROM  actor.usr_standing_penalty
+                  WHERE usr = match_user
+                        AND org_unit = max_fines.org_unit
+                        AND (stop_date IS NULL or stop_date > NOW())
+                        AND standing_penalty = 1
+                LOOP
+            RETURN NEXT existing_sp_row;
+        END LOOP;
+
+        SELECT  SUM(f.balance_owed) INTO current_fines
+          FROM  money.materialized_billable_xact_summary f
+                JOIN (
+                    SELECT  r.id
+                      FROM  booking.reservation r
+                            JOIN  actor.org_unit_full_path( max_fines.org_unit ) fp ON (r.pickup_lib = fp.id)
+                      WHERE usr = match_user
+                            AND xact_finish IS NULL
+                                UNION ALL
+                    SELECT  g.id
+                      FROM  money.grocery g
+                            JOIN  actor.org_unit_full_path( max_fines.org_unit ) fp ON (g.billing_location = fp.id)
+                      WHERE usr = match_user
+                            AND xact_finish IS NULL
+                                UNION ALL
+                    SELECT  circ.id
+                      FROM  action.circulation circ
+                            JOIN  actor.org_unit_full_path( max_fines.org_unit ) fp ON (circ.circ_lib = fp.id)
+                      WHERE usr = match_user
+                            AND xact_finish IS NULL ) l USING (id);
+
+        IF current_fines >= max_fines.threshold THEN
+            new_sp_row.usr := match_user;
+            new_sp_row.org_unit := max_fines.org_unit;
+            new_sp_row.standing_penalty := 1;
+            RETURN NEXT new_sp_row;
+        END IF;
+    END IF;
+
+    -- Start over for max overdue
+    SELECT INTO tmp_org * FROM actor.org_unit WHERE id = context_org;
+
+    -- Fail if the user has too many overdue items
+    LOOP
+        tmp_grp := user_object.profile;
+        LOOP
+
+            SELECT * INTO max_overdue FROM permission.grp_penalty_threshold WHERE grp = tmp_grp AND penalty = 2 AND org_unit = tmp_org.id;
+
+            IF max_overdue.threshold IS NULL THEN
+                SELECT parent INTO tmp_grp FROM permission.grp_tree WHERE id = tmp_grp;
+            ELSE
+                EXIT;
+            END IF;
+
+            IF tmp_grp IS NULL THEN
+                EXIT;
+            END IF;
+        END LOOP;
+
+        IF max_overdue.threshold IS NOT NULL OR tmp_org.parent_ou IS NULL THEN
+            EXIT;
+        END IF;
+
+        SELECT INTO tmp_org * FROM actor.org_unit WHERE id = tmp_org.parent_ou;
+
+    END LOOP;
+
+    IF max_overdue.threshold IS NOT NULL THEN
+
+        FOR existing_sp_row IN
+                SELECT  *
+                  FROM  actor.usr_standing_penalty
+                  WHERE usr = match_user
+                        AND org_unit = max_overdue.org_unit
+                        AND (stop_date IS NULL or stop_date > NOW())
+                        AND standing_penalty = 2
+                LOOP
+            RETURN NEXT existing_sp_row;
+        END LOOP;
+
+        SELECT  INTO items_overdue COUNT(*)
+          FROM  action.circulation circ
+                JOIN  actor.org_unit_full_path( max_overdue.org_unit ) fp ON (circ.circ_lib = fp.id)
+          WHERE circ.usr = match_user
+            AND circ.checkin_time IS NULL
+            AND circ.due_date < NOW()
+            AND (circ.stop_fines = 'MAXFINES' OR circ.stop_fines IS NULL);
+
+        IF items_overdue >= max_overdue.threshold::INT THEN
+            new_sp_row.usr := match_user;
+            new_sp_row.org_unit := max_overdue.org_unit;
+            new_sp_row.standing_penalty := 2;
+            RETURN NEXT new_sp_row;
+        END IF;
+    END IF;
+
+    -- Start over for max out
+    SELECT INTO tmp_org * FROM actor.org_unit WHERE id = context_org;
+
+    -- Fail if the user has too many checked out items
+    LOOP
+        tmp_grp := user_object.profile;
+        LOOP
+            SELECT * INTO max_items_out FROM permission.grp_penalty_threshold WHERE grp = tmp_grp AND penalty = 3 AND org_unit = tmp_org.id;
+
+            IF max_items_out.threshold IS NULL THEN
+                SELECT parent INTO tmp_grp FROM permission.grp_tree WHERE id = tmp_grp;
+            ELSE
+                EXIT;
+            END IF;
+
+            IF tmp_grp IS NULL THEN
+                EXIT;
+            END IF;
+        END LOOP;
+
+        IF max_items_out.threshold IS NOT NULL OR tmp_org.parent_ou IS NULL THEN
+            EXIT;
+        END IF;
+
+        SELECT INTO tmp_org * FROM actor.org_unit WHERE id = tmp_org.parent_ou;
+
+    END LOOP;
+
+
+    -- Fail if the user has too many items checked out
+    IF max_items_out.threshold IS NOT NULL THEN
+
+        FOR existing_sp_row IN
+                SELECT  *
+                  FROM  actor.usr_standing_penalty
+                  WHERE usr = match_user
+                        AND org_unit = max_items_out.org_unit
+                        AND (stop_date IS NULL or stop_date > NOW())
+                        AND standing_penalty = 3
+                LOOP
+            RETURN NEXT existing_sp_row;
+        END LOOP;
+
+        SELECT  INTO items_out COUNT(*)
+          FROM  action.circulation circ
+                JOIN  actor.org_unit_full_path( max_items_out.org_unit ) fp ON (circ.circ_lib = fp.id)
+          WHERE circ.usr = match_user
+                AND circ.checkin_time IS NULL
+                AND (circ.stop_fines IN ('MAXFINES','LONGOVERDUE') OR circ.stop_fines IS NULL);
+
+           IF items_out >= max_items_out.threshold::INT THEN
+            new_sp_row.usr := match_user;
+            new_sp_row.org_unit := max_items_out.org_unit;
+            new_sp_row.standing_penalty := 3;
+            RETURN NEXT new_sp_row;
+           END IF;
+    END IF;
+
+    -- Start over for collections warning
+    SELECT INTO tmp_org * FROM actor.org_unit WHERE id = context_org;
+
+    -- Fail if the user has a collections-level fine balance
+    LOOP
+        tmp_grp := user_object.profile;
+        LOOP
+            SELECT * INTO max_fines FROM permission.grp_penalty_threshold WHERE grp = tmp_grp AND penalty = 4 AND org_unit = tmp_org.id;
+
+            IF max_fines.threshold IS NULL THEN
+                SELECT parent INTO tmp_grp FROM permission.grp_tree WHERE id = tmp_grp;
+            ELSE
+                EXIT;
+            END IF;
+
+            IF tmp_grp IS NULL THEN
+                EXIT;
+            END IF;
+        END LOOP;
+
+        IF max_fines.threshold IS NOT NULL OR tmp_org.parent_ou IS NULL THEN
+            EXIT;
+        END IF;
+
+        SELECT * INTO tmp_org FROM actor.org_unit WHERE id = tmp_org.parent_ou;
+
+    END LOOP;
+
+    IF max_fines.threshold IS NOT NULL THEN
+
+        FOR existing_sp_row IN
+                SELECT  *
+                  FROM  actor.usr_standing_penalty
+                  WHERE usr = match_user
+                        AND org_unit = max_fines.org_unit
+                        AND (stop_date IS NULL or stop_date > NOW())
+                        AND standing_penalty = 4
+                LOOP
+            RETURN NEXT existing_sp_row;
+        END LOOP;
+
+        SELECT  SUM(f.balance_owed) INTO current_fines
+          FROM  money.materialized_billable_xact_summary f
+                JOIN (
+                    SELECT  r.id
+                      FROM  booking.reservation r
+                            JOIN  actor.org_unit_full_path( max_fines.org_unit ) fp ON (r.pickup_lib = fp.id)
+                      WHERE usr = match_user
+                            AND xact_finish IS NULL
+                                UNION ALL
+                    SELECT  g.id
+                      FROM  money.grocery g
+                            JOIN  actor.org_unit_full_path( max_fines.org_unit ) fp ON (g.billing_location = fp.id)
+                      WHERE usr = match_user
+                            AND xact_finish IS NULL
+                                UNION ALL
+                    SELECT  circ.id
+                      FROM  action.circulation circ
+                            JOIN  actor.org_unit_full_path( max_fines.org_unit ) fp ON (circ.circ_lib = fp.id)
+                      WHERE usr = match_user
+                            AND xact_finish IS NULL ) l USING (id);
+
+        IF current_fines >= max_fines.threshold THEN
+            new_sp_row.usr := match_user;
+            new_sp_row.org_unit := max_fines.org_unit;
+            new_sp_row.standing_penalty := 4;
+            RETURN NEXT new_sp_row;
+        END IF;
+    END IF;
+
+    -- Start over for in collections
+    SELECT INTO tmp_org * FROM actor.org_unit WHERE id = context_org;
+
+    -- Remove the in-collections penalty if the user has paid down enough
+    -- This penalty is different, because this code is not responsible for creating 
+    -- new in-collections penalties, only for removing them
+    LOOP
+        tmp_grp := user_object.profile;
+        LOOP
+            SELECT * INTO max_fines FROM permission.grp_penalty_threshold WHERE grp = tmp_grp AND penalty = 30 AND org_unit = tmp_org.id;
+
+            IF max_fines.threshold IS NULL THEN
+                SELECT parent INTO tmp_grp FROM permission.grp_tree WHERE id = tmp_grp;
+            ELSE
+                EXIT;
+            END IF;
+
+            IF tmp_grp IS NULL THEN
+                EXIT;
+            END IF;
+        END LOOP;
+
+        IF max_fines.threshold IS NOT NULL OR tmp_org.parent_ou IS NULL THEN
+            EXIT;
+        END IF;
+
+        SELECT * INTO tmp_org FROM actor.org_unit WHERE id = tmp_org.parent_ou;
+
+    END LOOP;
+
+    IF max_fines.threshold IS NOT NULL THEN
+
+        -- first, see if the user had paid down to the threshold
+        SELECT  SUM(f.balance_owed) INTO current_fines
+          FROM  money.materialized_billable_xact_summary f
+                JOIN (
+                    SELECT  r.id
+                      FROM  booking.reservation r
+                            JOIN  actor.org_unit_full_path( max_fines.org_unit ) fp ON (r.pickup_lib = fp.id)
+                      WHERE usr = match_user
+                            AND xact_finish IS NULL
+                                UNION ALL
+                    SELECT  g.id
+                      FROM  money.grocery g
+                            JOIN  actor.org_unit_full_path( max_fines.org_unit ) fp ON (g.billing_location = fp.id)
+                      WHERE usr = match_user
+                            AND xact_finish IS NULL
+                                UNION ALL
+                    SELECT  circ.id
+                      FROM  action.circulation circ
+                            JOIN  actor.org_unit_full_path( max_fines.org_unit ) fp ON (circ.circ_lib = fp.id)
+                      WHERE usr = match_user
+                            AND xact_finish IS NULL ) l USING (id);
+
+        IF current_fines IS NULL OR current_fines <= max_fines.threshold THEN
+            -- patron has paid down enough
+
+            SELECT INTO tmp_penalty * FROM config.standing_penalty WHERE id = 30;
+
+            IF tmp_penalty.org_depth IS NOT NULL THEN
+
+                -- since this code is not responsible for applying the penalty, it can't 
+                -- guarantee the current context org will match the org at which the penalty 
+                --- was applied.  search up the org tree until we hit the configured penalty depth
+                SELECT INTO tmp_org * FROM actor.org_unit WHERE id = context_org;
+                SELECT INTO tmp_depth depth FROM actor.org_unit_type WHERE id = tmp_org.ou_type;
+
+                WHILE tmp_depth >= tmp_penalty.org_depth LOOP
+
+                    FOR existing_sp_row IN
+                            SELECT  *
+                            FROM  actor.usr_standing_penalty
+                            WHERE usr = match_user
+                                    AND org_unit = tmp_org.id
+                                    AND (stop_date IS NULL or stop_date > NOW())
+                                    AND standing_penalty = 30 
+                            LOOP
+
+                        -- Penalty exists, return it for removal
+                        RETURN NEXT existing_sp_row;
+                    END LOOP;
+
+                    IF tmp_org.parent_ou IS NULL THEN
+                        EXIT;
+                    END IF;
+
+                    SELECT * INTO tmp_org FROM actor.org_unit WHERE id = tmp_org.parent_ou;
+                    SELECT INTO tmp_depth depth FROM actor.org_unit_type WHERE id = tmp_org.ou_type;
+                END LOOP;
+
+            ELSE
+
+                -- no penalty depth is defined, look for exact matches
+
+                FOR existing_sp_row IN
+                        SELECT  *
+                        FROM  actor.usr_standing_penalty
+                        WHERE usr = match_user
+                                AND org_unit = max_fines.org_unit
+                                AND (stop_date IS NULL or stop_date > NOW())
+                                AND standing_penalty = 30 
+                        LOOP
+                    -- Penalty exists, return it for removal
+                    RETURN NEXT existing_sp_row;
+                END LOOP;
+            END IF;
+    
+        END IF;
+
+    END IF;
+
+    RETURN;
+END;
+$func$ LANGUAGE plpgsql;
+
+-- Create a default row in acq.fiscal_calendar
+-- Add a column in actor.org_unit to point to it
+
+INSERT INTO acq.fiscal_calendar ( id, name ) VALUES ( 1, 'Default' );
+
+ALTER TABLE actor.org_unit
+ADD COLUMN fiscal_calendar INT NOT NULL
+	REFERENCES acq.fiscal_calendar( id )
+	DEFERRABLE INITIALLY DEFERRED
+	DEFAULT 1;
+
+ALTER TABLE auditor.actor_org_unit_history
+	ADD COLUMN fiscal_calendar INT;
+
+DROP VIEW auditor.actor_org_unit_lifecycle;
+
+SELECT auditor.create_auditor_lifecycle( 'actor', 'org_unit' );
+
+ALTER TABLE acq.funding_source_credit
+ADD COLUMN deadline_date TIMESTAMPTZ;
+
+ALTER TABLE acq.funding_source_credit
+ADD COLUMN effective_date TIMESTAMPTZ NOT NULL DEFAULT now();
+
+INSERT INTO config.standing_penalty (id,name,label) VALUES (30,'PATRON_IN_COLLECTIONS','Patron has been referred to a collections agency');
+
+CREATE TABLE acq.fund_transfer (
+	id               SERIAL         PRIMARY KEY,
+	src_fund         INT            NOT NULL REFERENCES acq.fund( id )
+	                                DEFERRABLE INITIALLY DEFERRED,
+	src_amount       NUMERIC        NOT NULL,
+	dest_fund        INT            REFERENCES acq.fund( id )
+	                                DEFERRABLE INITIALLY DEFERRED,
+	dest_amount      NUMERIC,
+	transfer_time    TIMESTAMPTZ    NOT NULL DEFAULT now(),
+	transfer_user    INT            NOT NULL REFERENCES actor.usr( id )
+	                                DEFERRABLE INITIALLY DEFERRED,
+	note             TEXT,
+    funding_source_credit INTEGER   NOT NULL
+	                                REFERENCES acq.funding_source_credit(id)
+	                                DEFERRABLE INITIALLY DEFERRED
+);
+
+CREATE INDEX acqftr_usr_idx
+ON acq.fund_transfer( transfer_user );
+
+COMMENT ON TABLE acq.fund_transfer IS $$
+/*
+ * Copyright (C) 2009  Georgia Public Library Service
+ * Scott McKellar <scott at esilibrary.com>
+ *
+ * Fund Transfer
+ *
+ * Each row represents the transfer of money from a source fund
+ * to a destination fund.  There should be corresponding entries
+ * in acq.fund_allocation.  The purpose of acq.fund_transfer is
+ * to record how much money moved from which fund to which other
+ * fund.
+ * 
+ * The presence of two amount fields, rather than one, reflects
+ * the possibility that the two funds are denominated in different
+ * currencies.  If they use the same currency type, the two
+ * amounts should be the same.
+ *
+ * ****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+$$;
+
+CREATE TABLE acq.claim_event_type (
+	id             SERIAL           PRIMARY KEY,
+	org_unit       INT              NOT NULL REFERENCES actor.org_unit(id)
+	                                         DEFERRABLE INITIALLY DEFERRED,
+	code           TEXT             NOT NULL,
+	description    TEXT             NOT NULL,
+	library_initiated BOOL          NOT NULL DEFAULT FALSE,
+	CONSTRAINT event_type_once_per_org UNIQUE ( org_unit, code )
+);
+
+CREATE TABLE acq.claim_event (
+	id             BIGSERIAL        PRIMARY KEY,
+	type           INT              NOT NULL REFERENCES acq.claim_event_type
+	                                         DEFERRABLE INITIALLY DEFERRED,
+	claim          SERIAL           NOT NULL REFERENCES acq.claim
+	                                         DEFERRABLE INITIALLY DEFERRED,
+	event_date     TIMESTAMPTZ      NOT NULL DEFAULT now(),
+	creator        INT              NOT NULL REFERENCES actor.usr
+	                                         DEFERRABLE INITIALLY DEFERRED,
+	note           TEXT
+);
+
+CREATE INDEX claim_event_claim_date_idx ON acq.claim_event( claim, event_date );
+
+CREATE OR REPLACE FUNCTION actor.usr_purge_data(
+	src_usr  IN INTEGER,
+	dest_usr IN INTEGER
+) RETURNS VOID AS $$
+DECLARE
+	suffix TEXT;
+	renamable_row RECORD;
+BEGIN
+
+	UPDATE actor.usr SET
+		active = FALSE,
+		card = NULL,
+		mailing_address = NULL,
+		billing_address = NULL
+	WHERE id = src_usr;
+
+	-- acq.*
+	UPDATE acq.fund_allocation SET allocator = dest_usr WHERE allocator = src_usr;
+	UPDATE acq.lineitem SET creator = dest_usr WHERE creator = src_usr;
+	UPDATE acq.lineitem SET editor = dest_usr WHERE editor = src_usr;
+	UPDATE acq.lineitem SET selector = dest_usr WHERE selector = src_usr;
+	UPDATE acq.lineitem_note SET creator = dest_usr WHERE creator = src_usr;
+	UPDATE acq.lineitem_note SET editor = dest_usr WHERE editor = src_usr;
+	DELETE FROM acq.lineitem_usr_attr_definition WHERE usr = src_usr;
+
+	-- Update with a rename to avoid collisions
+	FOR renamable_row in
+		SELECT id, name
+		FROM   acq.picklist
+		WHERE  owner = src_usr
+	LOOP
+		suffix := ' (' || src_usr || ')';
+		LOOP
+			BEGIN
+				UPDATE  acq.picklist
+				SET     owner = dest_usr, name = name || suffix
+				WHERE   id = renamable_row.id;
+			EXCEPTION WHEN unique_violation THEN
+				suffix := suffix || ' ';
+				CONTINUE;
+			END;
+			EXIT;
+		END LOOP;
+	END LOOP;
+
+	UPDATE acq.picklist SET creator = dest_usr WHERE creator = src_usr;
+	UPDATE acq.picklist SET editor = dest_usr WHERE editor = src_usr;
+	UPDATE acq.po_note SET creator = dest_usr WHERE creator = src_usr;
+	UPDATE acq.po_note SET editor = dest_usr WHERE editor = src_usr;
+	UPDATE acq.purchase_order SET owner = dest_usr WHERE owner = src_usr;
+	UPDATE acq.purchase_order SET creator = dest_usr WHERE creator = src_usr;
+	UPDATE acq.purchase_order SET editor = dest_usr WHERE editor = src_usr;
+	UPDATE acq.claim_event SET creator = dest_usr WHERE creator = src_usr;
+
+	-- action.*
+	DELETE FROM action.circulation WHERE usr = src_usr;
+	UPDATE action.circulation SET circ_staff = dest_usr WHERE circ_staff = src_usr;
+	UPDATE action.circulation SET checkin_staff = dest_usr WHERE checkin_staff = src_usr;
+	UPDATE action.hold_notification SET notify_staff = dest_usr WHERE notify_staff = src_usr;
+	UPDATE action.hold_request SET fulfillment_staff = dest_usr WHERE fulfillment_staff = src_usr;
+	UPDATE action.hold_request SET requestor = dest_usr WHERE requestor = src_usr;
+	DELETE FROM action.hold_request WHERE usr = src_usr;
+	UPDATE action.in_house_use SET staff = dest_usr WHERE staff = src_usr;
+	UPDATE action.non_cat_in_house_use SET staff = dest_usr WHERE staff = src_usr;
+	DELETE FROM action.non_cataloged_circulation WHERE patron = src_usr;
+	UPDATE action.non_cataloged_circulation SET staff = dest_usr WHERE staff = src_usr;
+	DELETE FROM action.survey_response WHERE usr = src_usr;
+	UPDATE action.fieldset SET owner = dest_usr WHERE owner = src_usr;
+
+	-- actor.*
+	DELETE FROM actor.card WHERE usr = src_usr;
+	DELETE FROM actor.stat_cat_entry_usr_map WHERE target_usr = src_usr;
+
+	-- The following update is intended to avoid transient violations of a foreign
+	-- key constraint, whereby actor.usr_address references itself.  It may not be
+	-- necessary, but it does no harm.
+	UPDATE actor.usr_address SET replaces = NULL
+		WHERE usr = src_usr AND replaces IS NOT NULL;
+	DELETE FROM actor.usr_address WHERE usr = src_usr;
+	DELETE FROM actor.usr_note WHERE usr = src_usr;
+	UPDATE actor.usr_note SET creator = dest_usr WHERE creator = src_usr;
+	DELETE FROM actor.usr_org_unit_opt_in WHERE usr = src_usr;
+	UPDATE actor.usr_org_unit_opt_in SET staff = dest_usr WHERE staff = src_usr;
+	DELETE FROM actor.usr_setting WHERE usr = src_usr;
+	DELETE FROM actor.usr_standing_penalty WHERE usr = src_usr;
+	UPDATE actor.usr_standing_penalty SET staff = dest_usr WHERE staff = src_usr;
+
+	-- asset.*
+	UPDATE asset.call_number SET creator = dest_usr WHERE creator = src_usr;
+	UPDATE asset.call_number SET editor = dest_usr WHERE editor = src_usr;
+	UPDATE asset.call_number_note SET creator = dest_usr WHERE creator = src_usr;
+	UPDATE asset.copy SET creator = dest_usr WHERE creator = src_usr;
+	UPDATE asset.copy SET editor = dest_usr WHERE editor = src_usr;
+	UPDATE asset.copy_note SET creator = dest_usr WHERE creator = src_usr;
+
+	-- auditor.*
+	DELETE FROM auditor.actor_usr_address_history WHERE id = src_usr;
+	DELETE FROM auditor.actor_usr_history WHERE id = src_usr;
+	UPDATE auditor.asset_call_number_history SET creator = dest_usr WHERE creator = src_usr;
+	UPDATE auditor.asset_call_number_history SET editor  = dest_usr WHERE editor  = src_usr;
+	UPDATE auditor.asset_copy_history SET creator = dest_usr WHERE creator = src_usr;
+	UPDATE auditor.asset_copy_history SET editor  = dest_usr WHERE editor  = src_usr;
+	UPDATE auditor.biblio_record_entry_history SET creator = dest_usr WHERE creator = src_usr;
+	UPDATE auditor.biblio_record_entry_history SET editor  = dest_usr WHERE editor  = src_usr;
+
+	-- biblio.*
+	UPDATE biblio.record_entry SET creator = dest_usr WHERE creator = src_usr;
+	UPDATE biblio.record_entry SET editor = dest_usr WHERE editor = src_usr;
+	UPDATE biblio.record_note SET creator = dest_usr WHERE creator = src_usr;
+	UPDATE biblio.record_note SET editor = dest_usr WHERE editor = src_usr;
+
+	-- container.*
+	-- Update buckets with a rename to avoid collisions
+	FOR renamable_row in
+		SELECT id, name
+		FROM   container.biblio_record_entry_bucket
+		WHERE  owner = src_usr
+	LOOP
+		suffix := ' (' || src_usr || ')';
+		LOOP
+			BEGIN
+				UPDATE  container.biblio_record_entry_bucket
+				SET     owner = dest_usr, name = name || suffix
+				WHERE   id = renamable_row.id;
+			EXCEPTION WHEN unique_violation THEN
+				suffix := suffix || ' ';
+				CONTINUE;
+			END;
+			EXIT;
+		END LOOP;
+	END LOOP;
+
+	FOR renamable_row in
+		SELECT id, name
+		FROM   container.call_number_bucket
+		WHERE  owner = src_usr
+	LOOP
+		suffix := ' (' || src_usr || ')';
+		LOOP
+			BEGIN
+				UPDATE  container.call_number_bucket
+				SET     owner = dest_usr, name = name || suffix
+				WHERE   id = renamable_row.id;
+			EXCEPTION WHEN unique_violation THEN
+				suffix := suffix || ' ';
+				CONTINUE;
+			END;
+			EXIT;
+		END LOOP;
+	END LOOP;
+
+	FOR renamable_row in
+		SELECT id, name
+		FROM   container.copy_bucket
+		WHERE  owner = src_usr
+	LOOP
+		suffix := ' (' || src_usr || ')';
+		LOOP
+			BEGIN
+				UPDATE  container.copy_bucket
+				SET     owner = dest_usr, name = name || suffix
+				WHERE   id = renamable_row.id;
+			EXCEPTION WHEN unique_violation THEN
+				suffix := suffix || ' ';
+				CONTINUE;
+			END;
+			EXIT;
+		END LOOP;
+	END LOOP;
+
+	FOR renamable_row in
+		SELECT id, name
+		FROM   container.user_bucket
+		WHERE  owner = src_usr
+	LOOP
+		suffix := ' (' || src_usr || ')';
+		LOOP
+			BEGIN
+				UPDATE  container.user_bucket
+				SET     owner = dest_usr, name = name || suffix
+				WHERE   id = renamable_row.id;
+			EXCEPTION WHEN unique_violation THEN
+				suffix := suffix || ' ';
+				CONTINUE;
+			END;
+			EXIT;
+		END LOOP;
+	END LOOP;
+
+	DELETE FROM container.user_bucket_item WHERE target_user = src_usr;
+
+	-- money.*
+	DELETE FROM money.billable_xact WHERE usr = src_usr;
+	DELETE FROM money.collections_tracker WHERE usr = src_usr;
+	UPDATE money.collections_tracker SET collector = dest_usr WHERE collector = src_usr;
+
+	-- permission.*
+	DELETE FROM permission.usr_grp_map WHERE usr = src_usr;
+	DELETE FROM permission.usr_object_perm_map WHERE usr = src_usr;
+	DELETE FROM permission.usr_perm_map WHERE usr = src_usr;
+	DELETE FROM permission.usr_work_ou_map WHERE usr = src_usr;
+
+	-- reporter.*
+	-- Update with a rename to avoid collisions
+	BEGIN
+		FOR renamable_row in
+			SELECT id, name
+			FROM   reporter.output_folder
+			WHERE  owner = src_usr
+		LOOP
+			suffix := ' (' || src_usr || ')';
+			LOOP
+				BEGIN
+					UPDATE  reporter.output_folder
+					SET     owner = dest_usr, name = name || suffix
+					WHERE   id = renamable_row.id;
+				EXCEPTION WHEN unique_violation THEN
+					suffix := suffix || ' ';
+					CONTINUE;
+				END;
+				EXIT;
+			END LOOP;
+		END LOOP;
+	EXCEPTION WHEN undefined_table THEN
+		-- do nothing
+	END;
+
+	BEGIN
+		UPDATE reporter.report SET owner = dest_usr WHERE owner = src_usr;
+	EXCEPTION WHEN undefined_table THEN
+		-- do nothing
+	END;
+
+	-- Update with a rename to avoid collisions
+	BEGIN
+		FOR renamable_row in
+			SELECT id, name
+			FROM   reporter.report_folder
+			WHERE  owner = src_usr
+		LOOP
+			suffix := ' (' || src_usr || ')';
+			LOOP
+				BEGIN
+					UPDATE  reporter.report_folder
+					SET     owner = dest_usr, name = name || suffix
+					WHERE   id = renamable_row.id;
+				EXCEPTION WHEN unique_violation THEN
+					suffix := suffix || ' ';
+					CONTINUE;
+				END;
+				EXIT;
+			END LOOP;
+		END LOOP;
+	EXCEPTION WHEN undefined_table THEN
+		-- do nothing
+	END;
+
+	BEGIN
+		UPDATE reporter.schedule SET runner = dest_usr WHERE runner = src_usr;
+	EXCEPTION WHEN undefined_table THEN
+		-- do nothing
+	END;
+
+	BEGIN
+		UPDATE reporter.template SET owner = dest_usr WHERE owner = src_usr;
+	EXCEPTION WHEN undefined_table THEN
+		-- do nothing
+	END;
+
+	-- Update with a rename to avoid collisions
+	BEGIN
+		FOR renamable_row in
+			SELECT id, name
+			FROM   reporter.template_folder
+			WHERE  owner = src_usr
+		LOOP
+			suffix := ' (' || src_usr || ')';
+			LOOP
+				BEGIN
+					UPDATE  reporter.template_folder
+					SET     owner = dest_usr, name = name || suffix
+					WHERE   id = renamable_row.id;
+				EXCEPTION WHEN unique_violation THEN
+					suffix := suffix || ' ';
+					CONTINUE;
+				END;
+				EXIT;
+			END LOOP;
+		END LOOP;
+	EXCEPTION WHEN undefined_table THEN
+	-- do nothing
+	END;
+
+	-- vandelay.*
+	-- Update with a rename to avoid collisions
+	FOR renamable_row in
+		SELECT id, name
+		FROM   vandelay.queue
+		WHERE  owner = src_usr
+	LOOP
+		suffix := ' (' || src_usr || ')';
+		LOOP
+			BEGIN
+				UPDATE  vandelay.queue
+				SET     owner = dest_usr, name = name || suffix
+				WHERE   id = renamable_row.id;
+			EXCEPTION WHEN unique_violation THEN
+				suffix := suffix || ' ';
+				CONTINUE;
+			END;
+			EXIT;
+		END LOOP;
+	END LOOP;
+
+END;
+$$ LANGUAGE plpgsql;
+
+-- INSERT INTO config.copy_status (id,name) VALUES (15,oils_i18n_gettext(15, 'On reservation shelf', 'ccs', 'name'));
+
+ALTER TABLE acq.fund
+ADD COLUMN rollover BOOL NOT NULL DEFAULT FALSE;
+
+ALTER TABLE acq.fund
+	ADD COLUMN propagate BOOLEAN NOT NULL DEFAULT TRUE;
+
+-- A fund can't roll over if it doesn't propagate from one year to the next
+
+ALTER TABLE acq.fund
+	ADD CONSTRAINT acq_fund_rollover_implies_propagate CHECK
+	( propagate OR NOT rollover );
+
+ALTER TABLE acq.fund
+	ADD COLUMN active BOOL NOT NULL DEFAULT TRUE;
+
+ALTER TABLE acq.fund
+    ADD COLUMN balance_warning_percent INT
+    CONSTRAINT balance_warning_percent_limit
+        CHECK( balance_warning_percent <= 100 );
+
+ALTER TABLE acq.fund
+    ADD COLUMN balance_stop_percent INT
+    CONSTRAINT balance_stop_percent_limit
+        CHECK( balance_stop_percent <= 100 );
+
+CREATE VIEW acq.ordered_funding_source_credit AS
+	SELECT
+		CASE WHEN deadline_date IS NULL THEN
+			2
+		ELSE
+			1
+		END AS sort_priority,
+		CASE WHEN deadline_date IS NULL THEN
+			effective_date
+		ELSE
+			deadline_date
+		END AS sort_date,
+		id,
+		funding_source,
+		amount,
+		note
+	FROM
+		acq.funding_source_credit;
+
+COMMENT ON VIEW acq.ordered_funding_source_credit IS $$
+/*
+ * Copyright (C) 2009  Georgia Public Library Service
+ * Scott McKellar <scott at gmail.com>
+ *
+ * The acq.ordered_funding_source_credit view is a prioritized
+ * ordering of funding source credits.  When ordered by the first
+ * three columns, this view defines the order in which the various
+ * credits are to be tapped for spending, subject to the allocations
+ * in the acq.fund_allocation table.
+ *
+ * The first column reflects the principle that we should spend
+ * money with deadlines before spending money without deadlines.
+ *
+ * The second column reflects the principle that we should spend the
+ * oldest money first.  For money with deadlines, that means that we
+ * spend first from the credit with the earliest deadline.  For
+ * money without deadlines, we spend first from the credit with the
+ * earliest effective date.  
+ *
+ * The third column is a tie breaker to ensure a consistent
+ * ordering.
+ *
+ * ****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+$$;
+
+CREATE OR REPLACE VIEW money.billable_xact_summary_location_view AS
+	SELECT * FROM money.materialized_billable_xact_summary;
+
+CREATE TABLE config.marc21_rec_type_map (
+    code        TEXT    PRIMARY KEY,
+    type_val    TEXT    NOT NULL,
+    blvl_val    TEXT    NOT NULL
+);
+
+CREATE TABLE config.marc21_ff_pos_map (
+    id          SERIAL  PRIMARY KEY,
+    fixed_field TEXT    NOT NULL,
+    tag         TEXT    NOT NULL,
+    rec_type    TEXT    NOT NULL,
+    start_pos   INT     NOT NULL,
+    length      INT     NOT NULL,
+    default_val TEXT    NOT NULL DEFAULT ' '
+);
+
+CREATE TABLE config.marc21_physical_characteristic_type_map (
+    ptype_key   TEXT    PRIMARY KEY,
+    label       TEXT    NOT NULL -- I18N
+);
+
+CREATE TABLE config.marc21_physical_characteristic_subfield_map (
+    id          SERIAL  PRIMARY KEY,
+    ptype_key   TEXT    NOT NULL REFERENCES config.marc21_physical_characteristic_type_map (ptype_key) ON DELETE CASCADE ON UPDATE CASCADE,
+    subfield    TEXT    NOT NULL,
+    start_pos   INT     NOT NULL,
+    length      INT     NOT NULL,
+    label       TEXT    NOT NULL -- I18N
+);
+
+CREATE TABLE config.marc21_physical_characteristic_value_map (
+    id              SERIAL  PRIMARY KEY,
+    value           TEXT    NOT NULL,
+    ptype_subfield  INT     NOT NULL REFERENCES config.marc21_physical_characteristic_subfield_map (id),
+    label           TEXT    NOT NULL -- I18N
+);
+
+----------------------------------
+-- MARC21 record structure data --
+----------------------------------
+
+-- Record type map
+INSERT INTO config.marc21_rec_type_map (code, type_val, blvl_val) VALUES ('BKS','at','acdm');
+INSERT INTO config.marc21_rec_type_map (code, type_val, blvl_val) VALUES ('SER','a','bsi');
+INSERT INTO config.marc21_rec_type_map (code, type_val, blvl_val) VALUES ('VIS','gkro','abcdmsi');
+INSERT INTO config.marc21_rec_type_map (code, type_val, blvl_val) VALUES ('MIX','p','cdi');
+INSERT INTO config.marc21_rec_type_map (code, type_val, blvl_val) VALUES ('MAP','ef','abcdmsi');
+INSERT INTO config.marc21_rec_type_map (code, type_val, blvl_val) VALUES ('SCO','cd','abcdmsi');
+INSERT INTO config.marc21_rec_type_map (code, type_val, blvl_val) VALUES ('REC','ij','abcdmsi');
+INSERT INTO config.marc21_rec_type_map (code, type_val, blvl_val) VALUES ('COM','m','abcdmsi');
+
+------ Physical Characteristics
+
+-- Map
+INSERT INTO config.marc21_physical_characteristic_type_map (ptype_key, label) VALUES ('a','Map');
+INSERT INTO config.marc21_physical_characteristic_subfield_map (ptype_key,subfield,start_pos,length,label) VALUES ('a','b','1','1','SMD');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('d',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Atlas');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('g',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Diagram');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('j',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Map');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('k',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Profile');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('q',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Model');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('r',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Remote-sensing image');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('s',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Section');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('u',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Unspecified');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('y',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'View');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('z',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Other');
+INSERT INTO config.marc21_physical_characteristic_subfield_map (ptype_key,subfield,start_pos,length,label) VALUES ('a','d','3','1','Color');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('a',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'One color');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('c',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Multicolored');
+INSERT INTO config.marc21_physical_characteristic_subfield_map (ptype_key,subfield,start_pos,length,label) VALUES ('a','e','4','1','Physical medium');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('a',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Paper');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('b',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Wood');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('c',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Stone');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('d',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Metal');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('e',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Synthetics');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('f',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Skins');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('g',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Textile');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('p',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Plaster');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('q',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Flexible base photographic medium, positive');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('r',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Flexible base photographic medium, negative');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('s',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Non-flexible base photographic medium, positive');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('t',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Non-flexible base photographic medium, negative');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('u',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Unknown');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('y',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Other photographic medium');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('z',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Other');
+INSERT INTO config.marc21_physical_characteristic_subfield_map (ptype_key,subfield,start_pos,length,label) VALUES ('a','f','5','1','Type of reproduction');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('f',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Facsimile');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('n',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Not applicable');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('u',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Unknown');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('z',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Other');
+INSERT INTO config.marc21_physical_characteristic_subfield_map (ptype_key,subfield,start_pos,length,label) VALUES ('a','g','6','1','Production/reproduction details');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('a',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Photocopy, blueline print');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('b',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Photocopy');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('c',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Pre-production');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('d',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Film');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('u',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Unknown');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('z',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Other');
+INSERT INTO config.marc21_physical_characteristic_subfield_map (ptype_key,subfield,start_pos,length,label) VALUES ('a','h','7','1','Positive/negative');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('a',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Positive');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('b',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Negative');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('m',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Mixed');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('n',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Not applicable');
+
+-- Electronic Resource
+INSERT INTO config.marc21_physical_characteristic_type_map (ptype_key, label) VALUES ('c','Electronic Resource');
+INSERT INTO config.marc21_physical_characteristic_subfield_map (ptype_key,subfield,start_pos,length,label) VALUES ('c','b','1','1','SMD');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('a',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Tape Cartridge');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('b',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Chip cartridge');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('c',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Computer optical disk cartridge');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('f',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Tape cassette');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('h',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Tape reel');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('j',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Magnetic disk');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('m',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Magneto-optical disk');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('o',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Optical disk');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('r',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Remote');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('u',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Unspecified');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('z',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Other');
+INSERT INTO config.marc21_physical_characteristic_subfield_map (ptype_key,subfield,start_pos,length,label) VALUES ('c','d','3','1','Color');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('a',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'One color');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('b',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Black-and-white');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('c',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Multicolored');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('g',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Gray scale');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('m',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Mixed');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('n',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Not applicable');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('u',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Unknown');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('z',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Other');
+INSERT INTO config.marc21_physical_characteristic_subfield_map (ptype_key,subfield,start_pos,length,label) VALUES ('c','e','4','1','Dimensions');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('a',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'3 1/2 in.');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('e',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'12 in.');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('g',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'4 3/4 in. or 12 cm.');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('i',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'1 1/8 x 2 3/8 in.');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('j',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'3 7/8 x 2 1/2 in.');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('n',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Not applicable');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('o',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'5 1/4 in.');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('u',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Unknown');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('v',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'8 in.');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('z',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Other');
+INSERT INTO config.marc21_physical_characteristic_subfield_map (ptype_key,subfield,start_pos,length,label) VALUES ('c','f','5','1','Sound');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES (' ',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'No sound (Silent)');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('a',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Sound');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('u',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Unknown');
+INSERT INTO config.marc21_physical_characteristic_subfield_map (ptype_key,subfield,start_pos,length,label) VALUES ('c','g','6','3','Image bit depth');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('---',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Unknown');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('mmm',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Multiple');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('nnn',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Not applicable');
+INSERT INTO config.marc21_physical_characteristic_subfield_map (ptype_key,subfield,start_pos,length,label) VALUES ('c','h','9','1','File formats');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('a',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'One file format');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('m',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Multiple file formats');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('u',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Unknown');
+INSERT INTO config.marc21_physical_characteristic_subfield_map (ptype_key,subfield,start_pos,length,label) VALUES ('c','i','10','1','Quality assurance target(s)');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('a',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Absent');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('n',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Not applicable');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('p',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Present');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('u',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Unknown');
+INSERT INTO config.marc21_physical_characteristic_subfield_map (ptype_key,subfield,start_pos,length,label) VALUES ('c','j','11','1','Antecedent/Source');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('a',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'File reproduced from original');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('b',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'File reproduced from microform');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('c',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'File reproduced from electronic resource');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('d',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'File reproduced from an intermediate (not microform)');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('m',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Mixed');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('n',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Not applicable');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('u',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Unknown');
+INSERT INTO config.marc21_physical_characteristic_subfield_map (ptype_key,subfield,start_pos,length,label) VALUES ('c','k','12','1','Level of compression');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('a',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Uncompressed');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('b',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Lossless');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('d',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Lossy');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('m',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Mixed');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('u',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Unknown');
+INSERT INTO config.marc21_physical_characteristic_subfield_map (ptype_key,subfield,start_pos,length,label) VALUES ('c','l','13','1','Reformatting quality');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('a',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Access');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('n',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Not applicable');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('p',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Preservation');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('r',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Replacement');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('u',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Unknown');
+
+-- Globe
+INSERT INTO config.marc21_physical_characteristic_type_map (ptype_key, label) VALUES ('d','Globe');
+INSERT INTO config.marc21_physical_characteristic_subfield_map (ptype_key,subfield,start_pos,length,label) VALUES ('d','b','1','1','SMD');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('a',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Celestial globe');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('b',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Planetary or lunar globe');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('c',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Terrestrial globe');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('e',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Earth moon globe');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('u',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Unspecified');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('z',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Other');
+INSERT INTO config.marc21_physical_characteristic_subfield_map (ptype_key,subfield,start_pos,length,label) VALUES ('d','d','3','1','Color');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('a',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'One color');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('c',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Multicolored');
+INSERT INTO config.marc21_physical_characteristic_subfield_map (ptype_key,subfield,start_pos,length,label) VALUES ('d','e','4','1','Physical medium');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('a',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Paper');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('b',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Wood');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('c',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Stone');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('d',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Metal');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('e',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Synthetics');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('f',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Skins');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('g',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Textile');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('p',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Plaster');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('u',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Unknown');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('z',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Other');
+INSERT INTO config.marc21_physical_characteristic_subfield_map (ptype_key,subfield,start_pos,length,label) VALUES ('d','f','5','1','Type of reproduction');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('f',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Facsimile');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('n',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Not applicable');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('u',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Unknown');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('z',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Other');
+
+-- Tactile Material
+INSERT INTO config.marc21_physical_characteristic_type_map (ptype_key, label) VALUES ('f','Tactile Material');
+INSERT INTO config.marc21_physical_characteristic_subfield_map (ptype_key,subfield,start_pos,length,label) VALUES ('f','b','1','1','SMD');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('a',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Moon');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('b',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Braille');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('c',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Combination');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('d',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Tactile, with no writing system');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('u',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Unspecified');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('z',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Other');
+INSERT INTO config.marc21_physical_characteristic_subfield_map (ptype_key,subfield,start_pos,length,label) VALUES ('f','d','3','2','Class of braille writing');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('a',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Literary braille');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('b',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Format code braille');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('c',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Mathematics and scientific braille');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('d',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Computer braille');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('e',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Music braille');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('m',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Multiple braille types');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('n',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Not applicable');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('u',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Unknown');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('z',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Other');
+INSERT INTO config.marc21_physical_characteristic_subfield_map (ptype_key,subfield,start_pos,length,label) VALUES ('f','e','4','1','Level of contraction');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('a',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Uncontracted');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('b',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Contracted');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('m',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Combination');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('n',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Not applicable');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('u',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Unknown');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('z',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Other');
+INSERT INTO config.marc21_physical_characteristic_subfield_map (ptype_key,subfield,start_pos,length,label) VALUES ('f','f','6','3','Braille music format');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('a',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Bar over bar');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('b',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Bar by bar');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('c',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Line over line');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('d',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Paragraph');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('e',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Single line');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('f',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Section by section');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('g',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Line by line');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('h',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Open score');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('i',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Spanner short form scoring');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('j',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Short form scoring');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('k',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Outline');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('l',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Vertical score');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('n',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Not applicable');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('u',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Unknown');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('z',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Other');
+INSERT INTO config.marc21_physical_characteristic_subfield_map (ptype_key,subfield,start_pos,length,label) VALUES ('f','g','9','1','Special physical characteristics');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('a',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Print/braille');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('b',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Jumbo or enlarged braille');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('n',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Not applicable');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('u',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Unknown');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('z',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Other');
+
+-- Projected Graphic
+INSERT INTO config.marc21_physical_characteristic_type_map (ptype_key, label) VALUES ('g','Projected Graphic');
+INSERT INTO config.marc21_physical_characteristic_subfield_map (ptype_key,subfield,start_pos,length,label) VALUES ('g','b','1','1','SMD');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('c',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Film cartridge');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('d',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Filmstrip');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('f',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Film filmstrip type');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('o',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Filmstrip roll');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('s',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Slide');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('t',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Transparency');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('z',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Other');
+INSERT INTO config.marc21_physical_characteristic_subfield_map (ptype_key,subfield,start_pos,length,label) VALUES ('g','d','3','1','Color');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('b',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Black-and-white');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('c',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Multicolored');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('h',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Hand-colored');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('m',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Mixed');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('n',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Not applicable');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('u',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Unknown');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('z',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Other');
+INSERT INTO config.marc21_physical_characteristic_subfield_map (ptype_key,subfield,start_pos,length,label) VALUES ('g','e','4','1','Base of emulsion');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('d',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Glass');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('e',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Synthetics');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('j',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Safety film');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('k',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Film base, other than safety film');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('m',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Mixed collection');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('o',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Paper');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('u',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Unknown');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('z',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Other');
+INSERT INTO config.marc21_physical_characteristic_subfield_map (ptype_key,subfield,start_pos,length,label) VALUES ('g','f','5','1','Sound on medium or separate');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('a',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Sound on medium');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('b',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Sound separate from medium');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('u',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Unknown');
+INSERT INTO config.marc21_physical_characteristic_subfield_map (ptype_key,subfield,start_pos,length,label) VALUES ('g','g','6','1','Medium for sound');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('a',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Optical sound track on motion picture film');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('b',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Magnetic sound track on motion picture film');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('c',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Magnetic audio tape in cartridge');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('d',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Sound disc');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('e',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Magnetic audio tape on reel');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('f',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Magnetic audio tape in cassette');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('g',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Optical and magnetic sound track on film');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('h',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Videotape');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('i',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Videodisc');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('u',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Unknown');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('z',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Other');
+INSERT INTO config.marc21_physical_characteristic_subfield_map (ptype_key,subfield,start_pos,length,label) VALUES ('g','h','7','1','Dimensions');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('a',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Standard 8 mm.');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('b',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Super 8 mm./single 8 mm.');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('c',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'9.5 mm.');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('d',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'16 mm.');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('e',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'28 mm.');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('f',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'35 mm.');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('g',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'70 mm.');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('j',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'2 x 2 in. (5 x 5 cm.)');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('k',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'2 1/4 x 2 1/4 in. (6 x 6 cm.)');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('s',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'4 x 5 in. (10 x 13 cm.)');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('t',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'5 x 7 in. (13 x 18 cm.)');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('u',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Unknown');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('v',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'8 x 10 in. (21 x 26 cm.)');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('w',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'9 x 9 in. (23 x 23 cm.)');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('x',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'10 x 10 in. (26 x 26 cm.)');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('y',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'7 x 7 in. (18 x 18 cm.)');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('z',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Other');
+INSERT INTO config.marc21_physical_characteristic_subfield_map (ptype_key,subfield,start_pos,length,label) VALUES ('g','i','8','1','Secondary support material');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('c',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Cardboard');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('d',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Glass');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('e',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Synthetics');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('h',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'metal');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('j',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Metal and glass');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('k',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Synthetics and glass');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('m',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Mixed collection');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('u',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Unknown');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('z',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Other');
+
+-- Microform
+INSERT INTO config.marc21_physical_characteristic_type_map (ptype_key, label) VALUES ('h','Microform');
+INSERT INTO config.marc21_physical_characteristic_subfield_map (ptype_key,subfield,start_pos,length,label) VALUES ('h','b','1','1','SMD');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('a',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Aperture card');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('b',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Microfilm cartridge');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('c',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Microfilm cassette');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('d',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Microfilm reel');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('e',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Microfiche');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('f',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Microfiche cassette');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('g',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Microopaque');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('u',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Unspecified');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('z',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Other');
+INSERT INTO config.marc21_physical_characteristic_subfield_map (ptype_key,subfield,start_pos,length,label) VALUES ('h','d','3','1','Positive/negative');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('a',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Positive');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('b',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Negative');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('m',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Mixed');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('u',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Unknown');
+INSERT INTO config.marc21_physical_characteristic_subfield_map (ptype_key,subfield,start_pos,length,label) VALUES ('h','e','4','1','Dimensions');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('a',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'8 mm.');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('e',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'16 mm.');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('f',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'35 mm.');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('g',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'70mm.');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('h',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'105 mm.');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('l',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'3 x 5 in. (8 x 13 cm.)');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('m',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'4 x 6 in. (11 x 15 cm.)');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('o',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'6 x 9 in. (16 x 23 cm.)');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('p',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'3 1/4 x 7 3/8 in. (9 x 19 cm.)');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('u',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Unknown');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('z',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Other');
+INSERT INTO config.marc21_physical_characteristic_subfield_map (ptype_key,subfield,start_pos,length,label) VALUES ('h','f','5','4','Reduction ratio range/Reduction ratio');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('a',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Low (1-16x)');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('b',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Normal (16-30x)');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('c',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'High (31-60x)');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('d',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Very high (61-90x)');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('e',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Ultra (90x-)');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('u',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Unknown');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('v',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Reduction ratio varies');
+INSERT INTO config.marc21_physical_characteristic_subfield_map (ptype_key,subfield,start_pos,length,label) VALUES ('h','g','9','1','Color');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('b',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Black-and-white');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('c',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Multicolored');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('m',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Mixed');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('u',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Unknown');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('z',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Other');
+INSERT INTO config.marc21_physical_characteristic_subfield_map (ptype_key,subfield,start_pos,length,label) VALUES ('h','h','10','1','Emulsion on film');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('a',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Silver halide');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('b',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Diazo');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('c',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Vesicular');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('m',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Mixed');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('n',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Not applicable');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('u',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Unknown');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('z',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Other');
+INSERT INTO config.marc21_physical_characteristic_subfield_map (ptype_key,subfield,start_pos,length,label) VALUES ('h','i','11','1','Quality assurance target(s)');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('a',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'1st gen. master');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('b',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Printing master');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('c',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Service copy');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('m',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Mixed generation');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('u',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Unknown');
+INSERT INTO config.marc21_physical_characteristic_subfield_map (ptype_key,subfield,start_pos,length,label) VALUES ('h','j','12','1','Base of film');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('a',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Safety base, undetermined');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('c',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Safety base, acetate undetermined');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('d',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Safety base, diacetate');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('l',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Nitrate base');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('m',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Mixed base');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('n',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Not applicable');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('p',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Safety base, polyester');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('r',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Safety base, mixed');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('t',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Safety base, triacetate');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('u',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Unknown');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('z',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Other');
+
+-- Non-projected Graphic
+INSERT INTO config.marc21_physical_characteristic_type_map (ptype_key, label) VALUES ('k','Non-projected Graphic');
+INSERT INTO config.marc21_physical_characteristic_subfield_map (ptype_key,subfield,start_pos,length,label) VALUES ('k','b','1','1','SMD');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('c',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Collage');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('d',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Drawing');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('e',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Painting');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('f',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Photo-mechanical print');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('g',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Photonegative');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('h',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Photoprint');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('i',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Picture');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('j',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Print');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('l',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Technical drawing');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('n',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Chart');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('o',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Flash/activity card');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('u',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Unspecified');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('z',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Other');
+INSERT INTO config.marc21_physical_characteristic_subfield_map (ptype_key,subfield,start_pos,length,label) VALUES ('k','d','3','1','Color');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('a',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'One color');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('b',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Black-and-white');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('c',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Multicolored');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('h',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Hand-colored');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('m',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Mixed');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('u',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Unknown');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('z',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Other');
+INSERT INTO config.marc21_physical_characteristic_subfield_map (ptype_key,subfield,start_pos,length,label) VALUES ('k','e','4','1','Primary support material');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('a',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Canvas');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('b',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Bristol board');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('c',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Cardboard/illustration board');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('d',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Glass');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('e',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Synthetics');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('f',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Skins');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('g',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Textile');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('h',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Metal');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('m',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Mixed collection');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('o',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Paper');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('p',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Plaster');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('q',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Hardboard');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('r',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Porcelain');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('s',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Stone');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('t',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Wood');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('u',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Unknown');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('z',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Other');
+INSERT INTO config.marc21_physical_characteristic_subfield_map (ptype_key,subfield,start_pos,length,label) VALUES ('k','f','5','1','Secondary support material');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('a',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Canvas');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('b',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Bristol board');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('c',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Cardboard/illustration board');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('d',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Glass');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('e',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Synthetics');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('f',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Skins');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('g',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Textile');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('h',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Metal');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('m',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Mixed collection');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('o',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Paper');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('p',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Plaster');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('q',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Hardboard');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('r',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Porcelain');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('s',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Stone');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('t',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Wood');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('u',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Unknown');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('z',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Other');
+
+-- Motion Picture
+INSERT INTO config.marc21_physical_characteristic_type_map (ptype_key, label) VALUES ('m','Motion Picture');
+INSERT INTO config.marc21_physical_characteristic_subfield_map (ptype_key,subfield,start_pos,length,label) VALUES ('m','b','1','1','SMD');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('a',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Film cartridge');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('f',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Film cassette');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('r',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Film reel');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('u',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Unspecified');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('z',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Other');
+INSERT INTO config.marc21_physical_characteristic_subfield_map (ptype_key,subfield,start_pos,length,label) VALUES ('m','d','3','1','Color');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('b',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Black-and-white');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('c',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Multicolored');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('h',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Hand-colored');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('m',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Mixed');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('u',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Unknown');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('z',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Other');
+INSERT INTO config.marc21_physical_characteristic_subfield_map (ptype_key,subfield,start_pos,length,label) VALUES ('m','e','4','1','Motion picture presentation format');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('a',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Standard sound aperture, reduced frame');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('b',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Nonanamorphic (wide-screen)');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('c',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'3D');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('d',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Anamorphic (wide-screen)');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('e',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Other-wide screen format');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('f',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Standard. silent aperture, full frame');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('u',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Unknown');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('z',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Other');
+INSERT INTO config.marc21_physical_characteristic_subfield_map (ptype_key,subfield,start_pos,length,label) VALUES ('m','f','5','1','Sound on medium or separate');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('a',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Sound on medium');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('b',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Sound separate from medium');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('u',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Unknown');
+INSERT INTO config.marc21_physical_characteristic_subfield_map (ptype_key,subfield,start_pos,length,label) VALUES ('m','g','6','1','Medium for sound');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('a',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Optical sound track on motion picture film');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('b',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Magnetic sound track on motion picture film');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('c',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Magnetic audio tape in cartridge');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('d',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Sound disc');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('e',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Magnetic audio tape on reel');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('f',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Magnetic audio tape in cassette');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('g',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Optical and magnetic sound track on film');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('h',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Videotape');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('i',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Videodisc');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('u',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Unknown');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('z',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Other');
+INSERT INTO config.marc21_physical_characteristic_subfield_map (ptype_key,subfield,start_pos,length,label) VALUES ('m','h','7','1','Dimensions');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('a',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Standard 8 mm.');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('b',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Super 8 mm./single 8 mm.');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('c',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'9.5 mm.');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('d',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'16 mm.');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('e',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'28 mm.');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('f',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'35 mm.');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('g',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'70 mm.');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('u',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Unknown');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('z',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Other');
+INSERT INTO config.marc21_physical_characteristic_subfield_map (ptype_key,subfield,start_pos,length,label) VALUES ('m','i','8','1','Configuration of playback channels');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('k',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Mixed');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('m',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Monaural');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('n',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Not applicable');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('q',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Multichannel, surround or quadraphonic');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('s',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Stereophonic');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('u',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Unknown');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('z',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Other');
+INSERT INTO config.marc21_physical_characteristic_subfield_map (ptype_key,subfield,start_pos,length,label) VALUES ('m','j','9','1','Production elements');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('a',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Work print');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('b',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Trims');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('c',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Outtakes');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('d',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Rushes');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('e',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Mixing tracks');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('f',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Title bands/inter-title rolls');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('g',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Production rolls');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('n',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Not applicable');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('z',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Other');
+
+-- Remote-sensing Image
+INSERT INTO config.marc21_physical_characteristic_type_map (ptype_key, label) VALUES ('r','Remote-sensing Image');
+INSERT INTO config.marc21_physical_characteristic_subfield_map (ptype_key,subfield,start_pos,length,label) VALUES ('r','b','1','1','SMD');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('u',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Unspecified');
+INSERT INTO config.marc21_physical_characteristic_subfield_map (ptype_key,subfield,start_pos,length,label) VALUES ('r','d','3','1','Altitude of sensor');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('a',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Surface');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('b',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Airborne');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('c',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Spaceborne');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('n',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Not applicable');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('u',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Unknown');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('z',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Other');
+INSERT INTO config.marc21_physical_characteristic_subfield_map (ptype_key,subfield,start_pos,length,label) VALUES ('r','e','4','1','Attitude of sensor');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('a',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Low oblique');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('b',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'High oblique');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('c',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Vertical');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('n',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Not applicable');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('u',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Unknown');
+INSERT INTO config.marc21_physical_characteristic_subfield_map (ptype_key,subfield,start_pos,length,label) VALUES ('r','f','5','1','Cloud cover');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('0',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'0-09%');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('1',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'10-19%');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('2',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'20-29%');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('3',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'30-39%');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('4',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'40-49%');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('5',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'50-59%');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('6',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'60-69%');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('7',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'70-79%');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('8',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'80-89%');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('9',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'90-100%');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('n',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Not applicable');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('u',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Unknown');
+INSERT INTO config.marc21_physical_characteristic_subfield_map (ptype_key,subfield,start_pos,length,label) VALUES ('r','g','6','1','Platform construction type');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('a',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Balloon');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('b',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Aircraft-low altitude');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('c',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Aircraft-medium altitude');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('d',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Aircraft-high altitude');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('e',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Manned spacecraft');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('f',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Unmanned spacecraft');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('g',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Land-based remote-sensing device');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('h',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Water surface-based remote-sensing device');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('i',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Submersible remote-sensing device');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('n',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Not applicable');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('u',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Unknown');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('z',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Other');
+INSERT INTO config.marc21_physical_characteristic_subfield_map (ptype_key,subfield,start_pos,length,label) VALUES ('r','h','7','1','Platform use category');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('a',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Meteorological');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('b',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Surface observing');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('c',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Space observing');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('m',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Mixed uses');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('n',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Not applicable');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('u',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Unknown');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('z',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Other');
+INSERT INTO config.marc21_physical_characteristic_subfield_map (ptype_key,subfield,start_pos,length,label) VALUES ('r','i','8','1','Sensor type');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('a',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Active');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('b',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Passive');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('u',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Unknown');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('z',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Other');
+INSERT INTO config.marc21_physical_characteristic_subfield_map (ptype_key,subfield,start_pos,length,label) VALUES ('r','j','9','2','Data type');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('aa',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Visible light');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('da',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Near infrared');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('db',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Middle infrared');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('dc',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Far infrared');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('dd',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Thermal infrared');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('de',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Shortwave infrared (SWIR)');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('df',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Reflective infrared');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('dv',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Combinations');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('dz',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Other infrared data');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('ga',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Sidelooking airborne radar (SLAR)');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('gb',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Synthetic aperture radar (SAR-single frequency)');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('gc',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'SAR-multi-frequency (multichannel)');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('gd',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'SAR-like polarization');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('ge',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'SAR-cross polarization');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('gf',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Infometric SAR');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('gg',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Polarmetric SAR');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('gu',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Passive microwave mapping');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('gz',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Other microwave data');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('ja',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Far ultraviolet');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('jb',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Middle ultraviolet');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('jc',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Near ultraviolet');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('jv',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Ultraviolet combinations');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('jz',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Other ultraviolet data');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('ma',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Multi-spectral, multidata');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('mb',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Multi-temporal');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('mm',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Combination of various data types');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('nn',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Not applicable');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('pa',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Sonar-water depth');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('pb',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Sonar-bottom topography images, sidescan');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('pc',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Sonar-bottom topography, near-surface');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('pd',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Sonar-bottom topography, near-bottom');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('pe',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Seismic surveys');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('pz',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Other acoustical data');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('ra',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Gravity anomales (general)');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('rb',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Free-air');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('rc',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Bouger');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('rd',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Isostatic');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('sa',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Magnetic field');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('ta',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Radiometric surveys');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('uu',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Unknown');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('zz',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Other');
+
+-- Sound Recording
+INSERT INTO config.marc21_physical_characteristic_type_map (ptype_key, label) VALUES ('s','Sound Recording');
+INSERT INTO config.marc21_physical_characteristic_subfield_map (ptype_key,subfield,start_pos,length,label) VALUES ('s','b','1','1','SMD');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('d',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Sound disc');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('e',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Cylinder');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('g',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Sound cartridge');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('i',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Sound-track film');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('q',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Roll');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('s',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Sound cassette');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('t',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Sound-tape reel');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('u',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Unspecified');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('w',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Wire recording');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('z',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Other');
+INSERT INTO config.marc21_physical_characteristic_subfield_map (ptype_key,subfield,start_pos,length,label) VALUES ('s','d','3','1','Speed');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('a',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'16 rpm');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('b',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'33 1/3 rpm');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('c',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'45 rpm');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('d',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'78 rpm');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('e',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'8 rpm');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('f',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'1.4 mps');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('h',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'120 rpm');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('i',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'160 rpm');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('k',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'15/16 ips');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('l',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'1 7/8 ips');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('m',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'3 3/4 ips');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('o',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'7 1/2 ips');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('p',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'15 ips');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('r',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'30 ips');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('u',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Unknown');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('z',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Other');
+INSERT INTO config.marc21_physical_characteristic_subfield_map (ptype_key,subfield,start_pos,length,label) VALUES ('s','e','4','1','Configuration of playback channels');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('m',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Monaural');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('q',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Quadraphonic');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('s',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Stereophonic');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('u',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Unknown');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('z',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Other');
+INSERT INTO config.marc21_physical_characteristic_subfield_map (ptype_key,subfield,start_pos,length,label) VALUES ('s','f','5','1','Groove width or pitch');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('m',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Microgroove/fine');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('n',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Not applicable');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('s',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Coarse/standard');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('u',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Unknown');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('z',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Other');
+INSERT INTO config.marc21_physical_characteristic_subfield_map (ptype_key,subfield,start_pos,length,label) VALUES ('s','g','6','1','Dimensions');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('a',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'3 in.');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('b',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'5 in.');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('c',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'7 in.');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('d',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'10 in.');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('e',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'12 in.');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('f',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'16 in.');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('g',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'4 3/4 in. (12 cm.)');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('j',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'3 7/8 x 2 1/2 in.');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('n',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Not applicable');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('o',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'5 1/4 x 3 7/8 in.');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('s',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'2 3/4 x 4 in.');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('u',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Unknown');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('z',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Other');
+INSERT INTO config.marc21_physical_characteristic_subfield_map (ptype_key,subfield,start_pos,length,label) VALUES ('s','h','7','1','Tape width');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('l',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'1/8 in.');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('m',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'1/4in.');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('n',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Not applicable');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('o',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'1/2 in.');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('p',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'1 in.');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('u',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Unknown');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('z',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Other');
+INSERT INTO config.marc21_physical_characteristic_subfield_map (ptype_key,subfield,start_pos,length,label) VALUES ('s','i','8','1','Tape configuration ');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('a',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Full (1) track');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('b',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Half (2) track');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('c',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Quarter (4) track');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('d',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'8 track');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('e',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'12 track');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('f',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'16 track');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('n',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Not applicable');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('u',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Unknown');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('z',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Other');
+INSERT INTO config.marc21_physical_characteristic_subfield_map (ptype_key,subfield,start_pos,length,label) VALUES ('s','m','12','1','Special playback');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('a',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'NAB standard');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('b',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'CCIR standard');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('c',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Dolby-B encoded, standard Dolby');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('d',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'dbx encoded');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('e',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Digital recording');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('f',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Dolby-A encoded');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('g',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Dolby-C encoded');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('h',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'CX encoded');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('n',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Not applicable');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('u',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Unknown');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('z',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Other');
+INSERT INTO config.marc21_physical_characteristic_subfield_map (ptype_key,subfield,start_pos,length,label) VALUES ('s','n','13','1','Capture and storage');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('a',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Acoustical capture, direct storage');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('b',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Direct storage, not acoustical');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('d',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Digital storage');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('e',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Analog electrical storage');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('u',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Unknown');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('z',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Other');
+
+-- Videorecording
+INSERT INTO config.marc21_physical_characteristic_type_map (ptype_key, label) VALUES ('v','Videorecording');
+INSERT INTO config.marc21_physical_characteristic_subfield_map (ptype_key,subfield,start_pos,length,label) VALUES ('v','b','1','1','SMD');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('c',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Videocartridge');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('d',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Videodisc');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('f',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Videocassette');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('r',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Videoreel');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('u',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Unspecified');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('z',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Other');
+INSERT INTO config.marc21_physical_characteristic_subfield_map (ptype_key,subfield,start_pos,length,label) VALUES ('v','d','3','1','Color');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('b',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Black-and-white');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('c',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Multicolored');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('m',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Mixed');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('n',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Not applicable');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('u',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Unknown');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('z',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Other');
+INSERT INTO config.marc21_physical_characteristic_subfield_map (ptype_key,subfield,start_pos,length,label) VALUES ('v','e','4','1','Videorecording format');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('a',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Beta');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('b',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'VHS');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('c',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'U-matic');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('d',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'EIAJ');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('e',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Type C');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('f',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Quadruplex');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('g',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Laserdisc');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('h',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'CED');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('i',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Betacam');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('j',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Betacam SP');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('k',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Super-VHS');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('m',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'M-II');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('o',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'D-2');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('p',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'8 mm.');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('q',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Hi-8 mm.');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('u',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Unknown');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('v',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'DVD');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('z',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Other');
+INSERT INTO config.marc21_physical_characteristic_subfield_map (ptype_key,subfield,start_pos,length,label) VALUES ('v','f','5','1','Sound on medium or separate');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('a',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Sound on medium');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('b',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Sound separate from medium');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('u',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Unknown');
+INSERT INTO config.marc21_physical_characteristic_subfield_map (ptype_key,subfield,start_pos,length,label) VALUES ('v','g','6','1','Medium for sound');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('a',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Optical sound track on motion picture film');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('b',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Magnetic sound track on motion picture film');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('c',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Magnetic audio tape in cartridge');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('d',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Sound disc');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('e',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Magnetic audio tape on reel');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('f',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Magnetic audio tape in cassette');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('g',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Optical and magnetic sound track on motion picture film');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('h',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Videotape');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('i',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Videodisc');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('u',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Unknown');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('z',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Other');
+INSERT INTO config.marc21_physical_characteristic_subfield_map (ptype_key,subfield,start_pos,length,label) VALUES ('v','h','7','1','Dimensions');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('a',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'8 mm.');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('m',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'1/4 in.');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('o',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'1/2 in.');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('p',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'1 in.');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('q',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'2 in.');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('r',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'3/4 in.');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('u',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Unknown');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('z',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Other');
+INSERT INTO config.marc21_physical_characteristic_subfield_map (ptype_key,subfield,start_pos,length,label) VALUES ('v','i','8','1','Configuration of playback channel');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('k',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Mixed');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('m',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Monaural');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('n',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Not applicable');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('q',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Multichannel, surround or quadraphonic');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('s',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Stereophonic');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('u',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Unknown');
+INSERT INTO config.marc21_physical_characteristic_value_map (value,ptype_subfield,label) VALUES ('z',CURRVAL('config.marc21_physical_characteristic_subfield_map_id_seq'),'Other');
+
+-- Fixed Field position data -- 0-based!
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Alph', '006', 'SER', 16, 1, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Alph', '008', 'SER', 33, 1, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Audn', '006', 'BKS', 5, 1, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Audn', '006', 'COM', 5, 1, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Audn', '006', 'REC', 5, 1, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Audn', '006', 'SCO', 5, 1, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Audn', '006', 'SER', 5, 1, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Audn', '006', 'VIS', 5, 1, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Audn', '008', 'BKS', 22, 1, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Audn', '008', 'COM', 22, 1, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Audn', '008', 'REC', 22, 1, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Audn', '008', 'SCO', 22, 1, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Audn', '008', 'SER', 22, 1, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Audn', '008', 'VIS', 22, 1, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('BLvl', 'ldr', 'BKS', 7, 1, 'm');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('BLvl', 'ldr', 'COM', 7, 1, 'm');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('BLvl', 'ldr', 'MAP', 7, 1, 'm');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('BLvl', 'ldr', 'MIX', 7, 1, 'c');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('BLvl', 'ldr', 'REC', 7, 1, 'm');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('BLvl', 'ldr', 'SCO', 7, 1, 'm');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('BLvl', 'ldr', 'SER', 7, 1, 's');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('BLvl', 'ldr', 'VIS', 7, 1, 'm');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Biog', '006', 'BKS', 17, 1, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Biog', '008', 'BKS', 34, 1, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Conf', '006', 'BKS', 7, 4, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Conf', '006', 'SER', 8, 3, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Conf', '008', 'BKS', 24, 4, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Conf', '008', 'SER', 25, 3, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Ctrl', 'ldr', 'BKS', 8, 1, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Ctrl', 'ldr', 'COM', 8, 1, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Ctrl', 'ldr', 'MAP', 8, 1, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Ctrl', 'ldr', 'MIX', 8, 1, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Ctrl', 'ldr', 'REC', 8, 1, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Ctrl', 'ldr', 'SCO', 8, 1, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Ctrl', 'ldr', 'SER', 8, 1, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Ctrl', 'ldr', 'VIS', 8, 1, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Ctry', '008', 'BKS', 15, 3, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Ctry', '008', 'COM', 15, 3, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Ctry', '008', 'MAP', 15, 3, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Ctry', '008', 'MIX', 15, 3, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Ctry', '008', 'REC', 15, 3, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Ctry', '008', 'SCO', 15, 3, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Ctry', '008', 'SER', 15, 3, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Ctry', '008', 'VIS', 15, 3, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Date1', '008', 'BKS', 7, 4, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Date1', '008', 'COM', 7, 4, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Date1', '008', 'MAP', 7, 4, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Date1', '008', 'MIX', 7, 4, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Date1', '008', 'REC', 7, 4, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Date1', '008', 'SCO', 7, 4, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Date1', '008', 'SER', 7, 4, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Date1', '008', 'VIS', 7, 4, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Date2', '008', 'BKS', 11, 4, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Date2', '008', 'COM', 11, 4, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Date2', '008', 'MAP', 11, 4, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Date2', '008', 'MIX', 11, 4, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Date2', '008', 'REC', 11, 4, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Date2', '008', 'SCO', 11, 4, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Date2', '008', 'SER', 11, 4, '9');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Date2', '008', 'VIS', 11, 4, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Desc', 'ldr', 'BKS', 18, 1, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Desc', 'ldr', 'COM', 18, 1, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Desc', 'ldr', 'MAP', 18, 1, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Desc', 'ldr', 'MIX', 18, 1, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Desc', 'ldr', 'REC', 18, 1, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Desc', 'ldr', 'SCO', 18, 1, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Desc', 'ldr', 'SER', 18, 1, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Desc', 'ldr', 'VIS', 18, 1, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('DtSt', '008', 'BKS', 6, 1, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('DtSt', '008', 'COM', 6, 1, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('DtSt', '008', 'MAP', 6, 1, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('DtSt', '008', 'MIX', 6, 1, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('DtSt', '008', 'REC', 6, 1, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('DtSt', '008', 'SCO', 6, 1, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('DtSt', '008', 'SER', 6, 1, 'c');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('DtSt', '008', 'VIS', 6, 1, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('ELvl', 'ldr', 'BKS', 17, 1, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('ELvl', 'ldr', 'COM', 17, 1, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('ELvl', 'ldr', 'MAP', 17, 1, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('ELvl', 'ldr', 'MIX', 17, 1, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('ELvl', 'ldr', 'REC', 17, 1, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('ELvl', 'ldr', 'SCO', 17, 1, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('ELvl', 'ldr', 'SER', 17, 1, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('ELvl', 'ldr', 'VIS', 17, 1, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Fest', '006', 'BKS', 13, 1, '0');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Fest', '008', 'BKS', 30, 1, '0');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Form', '006', 'BKS', 6, 1, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Form', '006', 'MAP', 12, 1, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Form', '006', 'MIX', 6, 1, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Form', '006', 'REC', 6, 1, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Form', '006', 'SCO', 6, 1, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Form', '006', 'SER', 6, 1, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Form', '006', 'VIS', 12, 1, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Form', '008', 'BKS', 23, 1, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Form', '008', 'MAP', 29, 1, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Form', '008', 'MIX', 23, 1, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Form', '008', 'REC', 23, 1, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Form', '008', 'SCO', 23, 1, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Form', '008', 'SER', 23, 1, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Form', '008', 'VIS', 29, 1, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('GPub', '006', 'BKS', 11, 1, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('GPub', '006', 'COM', 11, 1, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('GPub', '006', 'MAP', 11, 1, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('GPub', '006', 'SER', 11, 1, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('GPub', '006', 'VIS', 11, 1, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('GPub', '008', 'BKS', 28, 1, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('GPub', '008', 'COM', 28, 1, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('GPub', '008', 'MAP', 28, 1, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('GPub', '008', 'SER', 28, 1, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('GPub', '008', 'VIS', 28, 1, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Ills', '006', 'BKS', 1, 4, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Ills', '008', 'BKS', 18, 4, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Indx', '006', 'BKS', 14, 1, '0');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Indx', '006', 'MAP', 14, 1, '0');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Indx', '008', 'BKS', 31, 1, '0');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Indx', '008', 'MAP', 31, 1, '0');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Lang', '008', 'BKS', 35, 3, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Lang', '008', 'COM', 35, 3, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Lang', '008', 'MAP', 35, 3, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Lang', '008', 'MIX', 35, 3, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Lang', '008', 'REC', 35, 3, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Lang', '008', 'SCO', 35, 3, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Lang', '008', 'SER', 35, 3, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Lang', '008', 'VIS', 35, 3, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('LitF', '006', 'BKS', 16, 1, '0');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('LitF', '008', 'BKS', 33, 1, '0');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('MRec', '008', 'BKS', 38, 1, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('MRec', '008', 'COM', 38, 1, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('MRec', '008', 'MAP', 38, 1, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('MRec', '008', 'MIX', 38, 1, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('MRec', '008', 'REC', 38, 1, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('MRec', '008', 'SCO', 38, 1, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('MRec', '008', 'SER', 38, 1, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('MRec', '008', 'VIS', 38, 1, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('S/L', '006', 'SER', 17, 1, '0');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('S/L', '008', 'SER', 34, 1, '0');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('TMat', '006', 'VIS', 16, 1, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('TMat', '008', 'VIS', 33, 1, ' ');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Type', 'ldr', 'BKS', 6, 1, 'a');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Type', 'ldr', 'COM', 6, 1, 'm');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Type', 'ldr', 'MAP', 6, 1, 'e');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Type', 'ldr', 'MIX', 6, 1, 'p');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Type', 'ldr', 'REC', 6, 1, 'i');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Type', 'ldr', 'SCO', 6, 1, 'c');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Type', 'ldr', 'SER', 6, 1, 'a');
+INSERT INTO config.marc21_ff_pos_map (fixed_field, tag, rec_type,start_pos, length, default_val) VALUES ('Type', 'ldr', 'VIS', 6, 1, 'g');
+
+CREATE OR REPLACE FUNCTION biblio.marc21_record_type( rid BIGINT ) RETURNS config.marc21_rec_type_map AS $func$
+DECLARE
+	ldr         RECORD;
+	tval        TEXT;
+	tval_rec    RECORD;
+	bval        TEXT;
+	bval_rec    RECORD;
+    retval      config.marc21_rec_type_map%ROWTYPE;
+BEGIN
+    SELECT * INTO ldr FROM metabib.full_rec WHERE record = rid AND tag = 'LDR' LIMIT 1;
+
+    IF ldr.id IS NULL THEN
+        SELECT * INTO retval FROM config.marc21_rec_type_map WHERE code = 'BKS';
+        RETURN retval;
+    END IF;
+
+    SELECT * INTO tval_rec FROM config.marc21_ff_pos_map WHERE fixed_field = 'Type' LIMIT 1; -- They're all the same
+    SELECT * INTO bval_rec FROM config.marc21_ff_pos_map WHERE fixed_field = 'BLvl' LIMIT 1; -- They're all the same
+
+
+    tval := SUBSTRING( ldr.value, tval_rec.start_pos + 1, tval_rec.length );
+    bval := SUBSTRING( ldr.value, bval_rec.start_pos + 1, bval_rec.length );
+
+    -- RAISE NOTICE 'type %, blvl %, ldr %', tval, bval, ldr.value;
+
+    SELECT * INTO retval FROM config.marc21_rec_type_map WHERE type_val LIKE '%' || tval || '%' AND blvl_val LIKE '%' || bval || '%';
+
+
+    IF retval.code IS NULL THEN
+        SELECT * INTO retval FROM config.marc21_rec_type_map WHERE code = 'BKS';
+    END IF;
+
+    RETURN retval;
+END;
+$func$ LANGUAGE PLPGSQL;
+
+CREATE OR REPLACE FUNCTION biblio.marc21_extract_fixed_field( rid BIGINT, ff TEXT ) RETURNS TEXT AS $func$
+DECLARE
+    rtype       TEXT;
+    ff_pos      RECORD;
+    tag_data    RECORD;
+    val         TEXT;
+BEGIN
+    rtype := (biblio.marc21_record_type( rid )).code;
+    FOR ff_pos IN SELECT * FROM config.marc21_ff_pos_map WHERE fixed_field = ff AND rec_type = rtype ORDER BY tag DESC LOOP
+        FOR tag_data IN SELECT * FROM metabib.full_rec WHERE tag = UPPER(ff_pos.tag) AND record = rid LOOP
+            val := SUBSTRING( tag_data.value, ff_pos.start_pos + 1, ff_pos.length );
+            RETURN val;
+        END LOOP;
+        val := REPEAT( ff_pos.default_val, ff_pos.length );
+        RETURN val;
+    END LOOP;
+
+    RETURN NULL;
+END;
+$func$ LANGUAGE PLPGSQL;
+
+CREATE TYPE biblio.marc21_physical_characteristics AS ( id INT, record BIGINT, ptype TEXT, subfield INT, value INT );
+CREATE OR REPLACE FUNCTION biblio.marc21_physical_characteristics( rid BIGINT ) RETURNS SETOF biblio.marc21_physical_characteristics AS $func$
+DECLARE
+    rowid   INT := 0;
+    _007    RECORD;
+    ptype   config.marc21_physical_characteristic_type_map%ROWTYPE;
+    psf     config.marc21_physical_characteristic_subfield_map%ROWTYPE;
+    pval    config.marc21_physical_characteristic_value_map%ROWTYPE;
+    retval  biblio.marc21_physical_characteristics%ROWTYPE;
+BEGIN
+
+    SELECT * INTO _007 FROM metabib.full_rec WHERE record = rid AND tag = '007' LIMIT 1;
+
+    IF _007.id IS NOT NULL THEN
+        SELECT * INTO ptype FROM config.marc21_physical_characteristic_type_map WHERE ptype_key = SUBSTRING( _007.value, 1, 1 );
+
+        IF ptype.ptype_key IS NOT NULL THEN
+            FOR psf IN SELECT * FROM config.marc21_physical_characteristic_subfield_map WHERE ptype_key = ptype.ptype_key LOOP
+                SELECT * INTO pval FROM config.marc21_physical_characteristic_value_map WHERE ptype_subfield = psf.id AND value = SUBSTRING( _007.value, psf.start_pos + 1, psf.length );
+
+                IF pval.id IS NOT NULL THEN
+                    rowid := rowid + 1;
+                    retval.id := rowid;
+                    retval.record := rid;
+                    retval.ptype := ptype.ptype_key;
+                    retval.subfield := psf.id;
+                    retval.value := pval.id;
+                    RETURN NEXT retval;
+                END IF;
+
+            END LOOP;
+        END IF;
+    END IF;
+
+    RETURN;
+END;
+$func$ LANGUAGE PLPGSQL;
+
+DROP VIEW IF EXISTS money.open_usr_circulation_summary;
+DROP VIEW IF EXISTS money.open_usr_summary;
+DROP VIEW IF EXISTS money.open_billable_xact_summary;
+
+-- The view should supply defaults for numeric (amount) columns
+CREATE OR REPLACE VIEW money.billable_xact_summary AS
+    SELECT  xact.id,
+        xact.usr,
+        xact.xact_start,
+        xact.xact_finish,
+        COALESCE(credit.amount, 0.0::numeric) AS total_paid,
+        credit.payment_ts AS last_payment_ts,
+        credit.note AS last_payment_note,
+        credit.payment_type AS last_payment_type,
+        COALESCE(debit.amount, 0.0::numeric) AS total_owed,
+        debit.billing_ts AS last_billing_ts,
+        debit.note AS last_billing_note,
+        debit.billing_type AS last_billing_type,
+        COALESCE(debit.amount, 0.0::numeric) - COALESCE(credit.amount, 0.0::numeric) AS balance_owed,
+        p.relname AS xact_type
+      FROM  money.billable_xact xact
+        JOIN pg_class p ON xact.tableoid = p.oid
+        LEFT JOIN (
+            SELECT  billing.xact,
+                sum(billing.amount) AS amount,
+                max(billing.billing_ts) AS billing_ts,
+                last(billing.note) AS note,
+                last(billing.billing_type) AS billing_type
+              FROM  money.billing
+              WHERE billing.voided IS FALSE
+              GROUP BY billing.xact
+            ) debit ON xact.id = debit.xact
+        LEFT JOIN (
+            SELECT  payment_view.xact,
+                sum(payment_view.amount) AS amount,
+                max(payment_view.payment_ts) AS payment_ts,
+                last(payment_view.note) AS note,
+                last(payment_view.payment_type) AS payment_type
+              FROM  money.payment_view
+              WHERE payment_view.voided IS FALSE
+              GROUP BY payment_view.xact
+            ) credit ON xact.id = credit.xact
+      ORDER BY debit.billing_ts, credit.payment_ts;
+
+CREATE OR REPLACE VIEW money.open_billable_xact_summary AS 
+    SELECT * FROM money.billable_xact_summary_location_view
+    WHERE xact_finish IS NULL;
+
+CREATE OR REPLACE VIEW money.open_usr_circulation_summary AS
+    SELECT 
+        usr,
+        SUM(total_paid) AS total_paid,
+        SUM(total_owed) AS total_owed,
+        SUM(balance_owed) AS balance_owed
+    FROM  money.materialized_billable_xact_summary
+    WHERE xact_type = 'circulation' AND xact_finish IS NULL
+    GROUP BY usr;
+
+CREATE OR REPLACE VIEW money.usr_summary AS
+    SELECT 
+        usr, 
+        sum(total_paid) AS total_paid, 
+        sum(total_owed) AS total_owed, 
+        sum(balance_owed) AS balance_owed
+    FROM money.materialized_billable_xact_summary
+    GROUP BY usr;
+
+CREATE OR REPLACE VIEW money.open_usr_summary AS
+    SELECT 
+        usr, 
+        sum(total_paid) AS total_paid, 
+        sum(total_owed) AS total_owed, 
+        sum(balance_owed) AS balance_owed
+    FROM money.materialized_billable_xact_summary
+    WHERE xact_finish IS NULL
+    GROUP BY usr;
+
+-- CREATE RULE protect_mfhd_delete AS ON DELETE TO serial.record_entry DO INSTEAD UPDATE serial.record_entry SET deleted = true WHERE old.id = serial.record_entry.id;
+
+CREATE TABLE config.biblio_fingerprint (
+	id			SERIAL	PRIMARY KEY,
+	name		TEXT	NOT NULL, 
+	xpath		TEXT	NOT NULL,
+    first_word  BOOL    NOT NULL DEFAULT FALSE,
+	format		TEXT	NOT NULL DEFAULT 'marcxml'
+);
+
+INSERT INTO config.biblio_fingerprint (name, xpath, format)
+    VALUES (
+        'Title',
+        '//marc:datafield[@tag="700"]/marc:subfield[@code="t"]|' ||
+            '//marc:datafield[@tag="240"]/marc:subfield[@code="a"]|' ||
+            '//marc:datafield[@tag="242"]/marc:subfield[@code="a"]|' ||
+            '//marc:datafield[@tag="246"]/marc:subfield[@code="a"]|' ||
+            '//marc:datafield[@tag="245"]/marc:subfield[@code="a"]',
+        'marcxml'
+    );
+
+INSERT INTO config.biblio_fingerprint (name, xpath, format, first_word)
+    VALUES (
+        'Author',
+        '//marc:datafield[@tag="700" and ./*[@code="t"]]/marc:subfield[@code="a"]|'
+            '//marc:datafield[@tag="100"]/marc:subfield[@code="a"]|'
+            '//marc:datafield[@tag="110"]/marc:subfield[@code="a"]|'
+            '//marc:datafield[@tag="111"]/marc:subfield[@code="a"]|'
+            '//marc:datafield[@tag="260"]/marc:subfield[@code="b"]',
+        'marcxml',
+        TRUE
+    );
+
+CREATE OR REPLACE FUNCTION biblio.extract_quality ( marc TEXT, best_lang TEXT, best_type TEXT ) RETURNS INT AS $func$
+DECLARE
+    qual        INT;
+    ldr         TEXT;
+    tval        TEXT;
+    tval_rec    RECORD;
+    bval        TEXT;
+    bval_rec    RECORD;
+    type_map    RECORD;
+    ff_pos      RECORD;
+    ff_tag_data TEXT;
+BEGIN
+
+    IF marc IS NULL OR marc = '' THEN
+        RETURN NULL;
+    END IF;
+
+    -- First, the count of tags
+    qual := ARRAY_UPPER(oils_xpath('*[local-name()="datafield"]', marc), 1);
+
+    -- now go through a bunch of pain to get the record type
+    IF best_type IS NOT NULL THEN
+        ldr := (oils_xpath('//*[local-name()="leader"]/text()', marc))[1];
+
+        IF ldr IS NOT NULL THEN
+            SELECT * INTO tval_rec FROM config.marc21_ff_pos_map WHERE fixed_field = 'Type' LIMIT 1; -- They're all the same
+            SELECT * INTO bval_rec FROM config.marc21_ff_pos_map WHERE fixed_field = 'BLvl' LIMIT 1; -- They're all the same
+
+
+            tval := SUBSTRING( ldr, tval_rec.start_pos + 1, tval_rec.length );
+            bval := SUBSTRING( ldr, bval_rec.start_pos + 1, bval_rec.length );
+
+            -- RAISE NOTICE 'type %, blvl %, ldr %', tval, bval, ldr;
+
+            SELECT * INTO type_map FROM config.marc21_rec_type_map WHERE type_val LIKE '%' || tval || '%' AND blvl_val LIKE '%' || bval || '%';
+
+            IF type_map.code IS NOT NULL THEN
+                IF best_type = type_map.code THEN
+                    qual := qual + qual / 2;
+                END IF;
+
+                FOR ff_pos IN SELECT * FROM config.marc21_ff_pos_map WHERE fixed_field = 'Lang' AND rec_type = type_map.code ORDER BY tag DESC LOOP
+                    ff_tag_data := SUBSTRING((oils_xpath('//*[@tag="' || ff_pos.tag || '"]/text()',marc))[1], ff_pos.start_pos + 1, ff_pos.length);
+                    IF ff_tag_data = best_lang THEN
+                            qual := qual + 100;
+                    END IF;
+                END LOOP;
+            END IF;
+        END IF;
+    END IF;
+
+    -- Now look for some quality metrics
+    -- DCL record?
+    IF ARRAY_UPPER(oils_xpath('//*[@tag="040"]/*[@code="a" and contains(.,"DLC")]', marc), 1) = 1 THEN
+        qual := qual + 10;
+    END IF;
+
+    -- From OCLC?
+    IF (oils_xpath('//*[@tag="003"]/text()', marc))[1] ~* E'oclo?c' THEN
+        qual := qual + 10;
+    END IF;
+
+    RETURN qual;
+
+END;
+$func$ LANGUAGE PLPGSQL;
+
+CREATE OR REPLACE FUNCTION biblio.extract_fingerprint ( marc text ) RETURNS TEXT AS $func$
+DECLARE
+    idx     config.biblio_fingerprint%ROWTYPE;
+    xfrm        config.xml_transform%ROWTYPE;
+    prev_xfrm   TEXT;
+    transformed_xml TEXT;
+    xml_node    TEXT;
+    xml_node_list   TEXT[];
+    raw_text    TEXT;
+    output_text TEXT := '';
+BEGIN
+
+    IF marc IS NULL OR marc = '' THEN
+        RETURN NULL;
+    END IF;
+
+    -- Loop over the indexing entries
+    FOR idx IN SELECT * FROM config.biblio_fingerprint ORDER BY format, id LOOP
+
+        SELECT INTO xfrm * from config.xml_transform WHERE name = idx.format;
+
+        -- See if we can skip the XSLT ... it's expensive
+        IF prev_xfrm IS NULL OR prev_xfrm <> xfrm.name THEN
+            -- Can't skip the transform
+            IF xfrm.xslt <> '---' THEN
+                transformed_xml := oils_xslt_process(marc,xfrm.xslt);
+            ELSE
+                transformed_xml := marc;
+            END IF;
+
+            prev_xfrm := xfrm.name;
+        END IF;
+
+        raw_text := COALESCE(
+            naco_normalize(
+                ARRAY_TO_STRING(
+                    oils_xpath(
+                        '//text()',
+                        (oils_xpath(
+                            idx.xpath,
+                            transformed_xml,
+                            ARRAY[ARRAY[xfrm.prefix, xfrm.namespace_uri]]
+                        ))[1]
+                    ),
+                    ''
+                )
+            ),
+            ''
+        );
+
+        raw_text := REGEXP_REPLACE(raw_text, E'\\[.+?\\]', E'');
+        raw_text := REGEXP_REPLACE(raw_text, E'\\mthe\\M|\\man?d?d\\M', E'', 'g'); -- arg! the pain!
+
+        IF idx.first_word IS TRUE THEN
+            raw_text := REGEXP_REPLACE(raw_text, E'^(\\w+).*?$', E'\\1');
+        END IF;
+
+        output_text := output_text || REGEXP_REPLACE(raw_text, E'\\s+', '', 'g');
+
+    END LOOP;
+
+    RETURN output_text;
+
+END;
+$func$ LANGUAGE PLPGSQL;
+
+-- BEFORE UPDATE OR INSERT trigger for biblio.record_entry
+CREATE OR REPLACE FUNCTION biblio.fingerprint_trigger () RETURNS TRIGGER AS $func$
+BEGIN
+
+    -- For TG_ARGV, first param is language (like 'eng'), second is record type (like 'BKS')
+
+    IF NEW.deleted IS TRUE THEN -- we don't much care, then, do we?
+        RETURN NEW;
+    END IF;
+
+    NEW.fingerprint := biblio.extract_fingerprint(NEW.marc);
+    NEW.quality := biblio.extract_quality(NEW.marc, TG_ARGV[0], TG_ARGV[1]);
+
+    RETURN NEW;
+
+END;
+$func$ LANGUAGE PLPGSQL;
+
+CREATE TABLE config.internal_flag (
+    name    TEXT    PRIMARY KEY,
+    value   TEXT,
+    enabled BOOL    NOT NULL DEFAULT FALSE
+);
+INSERT INTO config.internal_flag (name) VALUES ('ingest.metarecord_mapping.skip_on_insert');
+INSERT INTO config.internal_flag (name) VALUES ('ingest.reingest.force_on_same_marc');
+INSERT INTO config.internal_flag (name) VALUES ('ingest.reingest.skip_located_uri');
+INSERT INTO config.internal_flag (name) VALUES ('ingest.disable_located_uri');
+INSERT INTO config.internal_flag (name) VALUES ('ingest.disable_metabib_full_rec');
+INSERT INTO config.internal_flag (name) VALUES ('ingest.disable_metabib_rec_descriptor');
+INSERT INTO config.internal_flag (name) VALUES ('ingest.disable_metabib_field_entry');
+INSERT INTO config.internal_flag (name) VALUES ('ingest.disable_authority_linking');
+
+CREATE TABLE authority.bib_linking (
+    id          BIGSERIAL   PRIMARY KEY,
+    bib         BIGINT      NOT NULL REFERENCES biblio.record_entry (id),
+    authority   BIGINT      NOT NULL REFERENCES authority.record_entry (id)
+);
+CREATE INDEX authority_bl_bib_idx ON authority.bib_linking ( bib );
+CREATE UNIQUE INDEX authority_bl_bib_authority_once_idx ON authority.bib_linking ( authority, bib );
+
+CREATE OR REPLACE FUNCTION public.remove_paren_substring( TEXT ) RETURNS TEXT AS $func$
+    SELECT regexp_replace($1, $$\([^)]+\)$$, '', 'g');
+$func$ LANGUAGE SQL STRICT IMMUTABLE;
+
+CREATE OR REPLACE FUNCTION biblio.map_authority_linking (bibid BIGINT, marc TEXT) RETURNS BIGINT AS $func$
+    DELETE FROM authority.bib_linking WHERE bib = $1;
+    INSERT INTO authority.bib_linking (bib, authority)
+        SELECT  y.bib,
+                y.authority
+          FROM (    SELECT  DISTINCT $1 AS bib,
+                            BTRIM(remove_paren_substring(txt))::BIGINT AS authority
+                      FROM  explode_array(oils_xpath('//*[@code="0"]/text()',$2)) x(txt)
+                      WHERE BTRIM(remove_paren_substring(txt)) ~ $re$^\d+$$re$
+                ) y JOIN authority.record_entry r ON r.id = y.authority;
+    SELECT $1;
+$func$ LANGUAGE SQL;
+
+CREATE OR REPLACE FUNCTION metabib.reingest_metabib_rec_descriptor( bib_id BIGINT ) RETURNS VOID AS $func$
+BEGIN
+    DELETE FROM metabib.rec_descriptor WHERE record = bib_id;
+    INSERT INTO metabib.rec_descriptor (record, item_type, item_form, bib_level, control_type, enc_level, audience, lit_form, type_mat, cat_form, pub_status, item_lang, vr_format, date1, date2)
+        SELECT  bib_id,
+                biblio.marc21_extract_fixed_field( bib_id, 'Type' ),
+                biblio.marc21_extract_fixed_field( bib_id, 'Form' ),
+                biblio.marc21_extract_fixed_field( bib_id, 'BLvl' ),
+                biblio.marc21_extract_fixed_field( bib_id, 'Ctrl' ),
+                biblio.marc21_extract_fixed_field( bib_id, 'ELvl' ),
+                biblio.marc21_extract_fixed_field( bib_id, 'Audn' ),
+                biblio.marc21_extract_fixed_field( bib_id, 'LitF' ),
+                biblio.marc21_extract_fixed_field( bib_id, 'TMat' ),
+                biblio.marc21_extract_fixed_field( bib_id, 'Desc' ),
+                biblio.marc21_extract_fixed_field( bib_id, 'DtSt' ),
+                biblio.marc21_extract_fixed_field( bib_id, 'Lang' ),
+                (   SELECT  v.value
+                      FROM  biblio.marc21_physical_characteristics( bib_id) p
+                            JOIN config.marc21_physical_characteristic_subfield_map s ON (s.id = p.subfield)
+                            JOIN config.marc21_physical_characteristic_value_map v ON (v.id = p.value)
+                      WHERE p.ptype = 'v' AND s.subfield = 'e'    ),
+                biblio.marc21_extract_fixed_field( bib_id, 'Date1'),
+                biblio.marc21_extract_fixed_field( bib_id, 'Date2');
+
+    RETURN;
+END;
+$func$ LANGUAGE PLPGSQL;
+
+CREATE TABLE config.metabib_class (
+    name    TEXT    PRIMARY KEY,
+    label   TEXT    NOT NULL UNIQUE
+);
+
+INSERT INTO config.metabib_class ( name, label ) VALUES ( 'keyword', oils_i18n_gettext('keyword', 'Keyword', 'cmc', 'label') );
+INSERT INTO config.metabib_class ( name, label ) VALUES ( 'title', oils_i18n_gettext('title', 'Title', 'cmc', 'label') );
+INSERT INTO config.metabib_class ( name, label ) VALUES ( 'author', oils_i18n_gettext('author', 'Author', 'cmc', 'label') );
+INSERT INTO config.metabib_class ( name, label ) VALUES ( 'subject', oils_i18n_gettext('subject', 'Subject', 'cmc', 'label') );
+INSERT INTO config.metabib_class ( name, label ) VALUES ( 'series', oils_i18n_gettext('series', 'Series', 'cmc', 'label') );
+
+CREATE TABLE metabib.facet_entry (
+        id              BIGSERIAL       PRIMARY KEY,
+        source          BIGINT          NOT NULL,
+        field           INT             NOT NULL,
+        value           TEXT            NOT NULL
+);
+
+CREATE OR REPLACE FUNCTION metabib.reingest_metabib_field_entries( bib_id BIGINT ) RETURNS VOID AS $func$
+DECLARE
+    fclass          RECORD;
+    ind_data        metabib.field_entry_template%ROWTYPE;
+BEGIN
+    FOR fclass IN SELECT * FROM config.metabib_class LOOP
+        -- RAISE NOTICE 'Emptying out %', fclass.name;
+        EXECUTE $$DELETE FROM metabib.$$ || fclass.name || $$_field_entry WHERE source = $$ || bib_id;
+    END LOOP;
+
+    DELETE FROM metabib.facet_entry WHERE source = bib_id;
+
+    FOR ind_data IN SELECT * FROM biblio.extract_metabib_field_entry( bib_id ) LOOP
+        IF ind_data.field < 0 THEN
+            ind_data.field = -1 * ind_data.field;
+            INSERT INTO metabib.facet_entry (field, source, value)
+                VALUES (ind_data.field, ind_data.source, ind_data.value);
+        ELSE
+            EXECUTE $$
+                INSERT INTO metabib.$$ || ind_data.field_class || $$_field_entry (field, source, value)
+                    VALUES ($$ ||
+                        quote_literal(ind_data.field) || $$, $$ ||
+                        quote_literal(ind_data.source) || $$, $$ ||
+                        quote_literal(ind_data.value) ||
+                    $$);$$;
+        END IF;
+
+    END LOOP;
+
+    RETURN;
+END;
+$func$ LANGUAGE PLPGSQL;
+
+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       TEXT;
+    uri_owner_id    INT;
+    uri_id          INT;
+    uri_cn_id       INT;
+    uri_map_id      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];
+            CONTINUE WHEN uri_href IS NULL;
+
+            uri_label   := (oils_xpath('//*[@code="y"]/text()|//*[@code="3"]/text()|//*[@code="u"]/text()',uri_xml))[1];
+            CONTINUE WHEN uri_label IS NULL;
+
+            uri_owner   := (oils_xpath('//*[@code="9"]/text()|//*[@code="w"]/text()|//*[@code="n"]/text()',uri_xml))[1];
+            CONTINUE WHEN uri_owner IS NULL;
+
+            uri_use     := (oils_xpath('//*[@code="z"]/text()|//*[@code="2"]/text()|//*[@code="n"]/text()',uri_xml))[1];
+
+            uri_owner := REGEXP_REPLACE(uri_owner, $re$^.*?\((\w+)\).*$$re$, E'\\1');
+
+            SELECT id INTO uri_owner_id FROM actor.org_unit WHERE shortname = uri_owner;
+            CONTINUE WHEN NOT FOUND;
+
+            -- now we look for a matching uri
+            SELECT id INTO uri_id FROM asset.uri WHERE label = uri_label AND href = uri_href AND use_restriction = uri_use AND active;
+            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;
+
+            -- 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);
+            END IF;
+
+        END LOOP;
+    END IF;
+
+    RETURN;
+END;
+$func$ LANGUAGE PLPGSQL;
+
+CREATE OR REPLACE FUNCTION metabib.remap_metarecord_for_bib( bib_id BIGINT, fp TEXT ) RETURNS BIGINT AS $func$
+DECLARE
+    source_count    INT;
+    old_mr          BIGINT;
+    tmp_mr          metabib.metarecord%ROWTYPE;
+    deleted_mrs     BIGINT[];
+BEGIN
+
+    DELETE FROM metabib.metarecord_source_map WHERE source = bib_id; -- Rid ourselves of the search-estimate-killing linkage
+
+    FOR tmp_mr IN SELECT  m.* FROM  metabib.metarecord m JOIN metabib.metarecord_source_map s ON (s.metarecord = m.id) WHERE s.source = bib_id LOOP
+
+        IF old_mr IS NULL AND fp = tmp_mr.fingerprint THEN -- Find the first fingerprint-matching
+            old_mr := tmp_mr.id;
+        ELSE
+            SELECT COUNT(*) INTO source_count FROM metabib.metarecord_source_map WHERE metarecord = tmp_mr.id;
+            IF source_count = 0 THEN -- No other records
+                deleted_mrs := ARRAY_APPEND(deleted_mrs, tmp_mr.id);
+                DELETE FROM metabib.metarecord WHERE id = tmp_mr.id;
+            END IF;
+        END IF;
+
+    END LOOP;
+
+    IF old_mr IS NULL THEN -- we found no suitable, preexisting MR based on old source maps
+        SELECT id INTO old_mr FROM metabib.metarecord WHERE fingerprint = fp; -- is there one for our current fingerprint?
+        IF old_mr IS NULL THEN -- nope, create one and grab its id
+            INSERT INTO metabib.metarecord ( fingerprint, master_record ) VALUES ( fp, bib_id );
+            SELECT id INTO old_mr FROM metabib.metarecord WHERE fingerprint = fp;
+        ELSE -- indeed there is. update it with a null cache and recalcualated master record
+            UPDATE  metabib.metarecord
+              SET   mods = NULL,
+                    master_record = ( SELECT id FROM biblio.record_entry WHERE fingerprint = fp ORDER BY quality DESC LIMIT 1)
+              WHERE id = old_mr;
+        END IF;
+    ELSE -- there was one we already attached to, update its mods cache and master_record
+        UPDATE  metabib.metarecord
+          SET   mods = NULL,
+                master_record = ( SELECT id FROM biblio.record_entry WHERE fingerprint = fp ORDER BY quality DESC LIMIT 1)
+          WHERE id = old_mr;
+    END IF;
+
+    INSERT INTO metabib.metarecord_source_map (metarecord, source) VALUES (old_mr, bib_id); -- new source mapping
+
+    IF ARRAY_UPPER(deleted_mrs,1) > 0 THEN
+        UPDATE action.hold_request SET target = old_mr WHERE target IN ( SELECT explode_array(deleted_mrs) ) AND hold_type = 'M'; -- if we had to delete any MRs above, make sure their holds are moved
+    END IF;
+
+    RETURN old_mr;
+
+END;
+$func$ LANGUAGE PLPGSQL;
+
+CREATE OR REPLACE FUNCTION metabib.reingest_metabib_full_rec( bib_id BIGINT ) RETURNS VOID AS $func$
+BEGIN
+    DELETE FROM metabib.real_full_rec WHERE record = bib_id;
+    INSERT INTO metabib.real_full_rec (record, tag, ind1, ind2, subfield, value)
+        SELECT record, tag, ind1, ind2, subfield, value FROM biblio.flatten_marc( bib_id );
+
+    RETURN;
+END;
+$func$ LANGUAGE PLPGSQL;
+
+-- AFTER UPDATE OR INSERT trigger for biblio.record_entry
+CREATE OR REPLACE FUNCTION biblio.indexing_ingest_or_delete () RETURNS TRIGGER AS $func$
+BEGIN
+
+    IF NEW.deleted IS TRUE THEN -- If this bib is deleted
+        DELETE FROM metabib.metarecord_source_map WHERE source = NEW.id; -- Rid ourselves of the search-estimate-killing linkage
+        DELETE FROM authority.bib_linking WHERE bib = NEW.id; -- Avoid updating fields in bibs that are no longer visible
+        RETURN NEW; -- and we're done
+    END IF;
+
+    IF TG_OP = 'UPDATE' THEN -- re-ingest?
+        PERFORM * FROM config.internal_flag WHERE name = 'ingest.reingest.force_on_same_marc' AND enabled;
+
+        IF NOT FOUND AND OLD.marc = NEW.marc THEN -- don't do anything if the MARC didn't change
+            RETURN NEW;
+        END IF;
+    END IF;
+
+    -- Record authority linking
+    PERFORM * FROM config.internal_flag WHERE name = 'ingest.disable_authority_linking' AND enabled;
+    IF NOT FOUND THEN
+        PERFORM biblio.map_authority_linking( NEW.id, NEW.marc );
+    END IF;
+
+    -- Flatten and insert the mfr data
+    PERFORM * FROM config.internal_flag WHERE name = 'ingest.disable_metabib_full_rec' AND enabled;
+    IF NOT FOUND THEN
+        PERFORM metabib.reingest_metabib_full_rec(NEW.id);
+        PERFORM * FROM config.internal_flag WHERE name = 'ingest.disable_metabib_rec_descriptor' AND enabled;
+        IF NOT FOUND THEN
+            PERFORM metabib.reingest_metabib_rec_descriptor(NEW.id);
+        END IF;
+    END IF;
+
+    -- Gather and insert the field entry data
+    PERFORM metabib.reingest_metabib_field_entries(NEW.id);
+
+    -- Located URI magic
+    IF TG_OP = 'INSERT' THEN
+        PERFORM * FROM config.internal_flag WHERE name = 'ingest.disable_located_uri' AND enabled;
+        IF NOT FOUND THEN
+            PERFORM biblio.extract_located_uris( NEW.id, NEW.marc, NEW.editor );
+        END IF;
+    ELSE
+        PERFORM * FROM config.internal_flag WHERE name = 'ingest.disable_located_uri' AND enabled;
+        IF NOT FOUND THEN
+            PERFORM biblio.extract_located_uris( NEW.id, NEW.marc, NEW.editor );
+        END IF;
+    END IF;
+
+    -- (re)map metarecord-bib linking
+    IF TG_OP = 'INSERT' THEN -- if not deleted and performing an insert, check for the flag
+        PERFORM * FROM config.internal_flag WHERE name = 'ingest.metarecord_mapping.skip_on_insert' AND enabled;
+        IF NOT FOUND THEN
+            PERFORM metabib.remap_metarecord_for_bib( NEW.id, NEW.fingerprint );
+        END IF;
+    ELSE -- we're doing an update, and we're not deleted, remap
+        PERFORM metabib.remap_metarecord_for_bib( NEW.id, NEW.fingerprint );
+    END IF;
+
+    RETURN NEW;
+END;
+$func$ LANGUAGE PLPGSQL;
+
+CREATE TRIGGER fingerprint_tgr BEFORE INSERT OR UPDATE ON biblio.record_entry FOR EACH ROW EXECUTE PROCEDURE biblio.fingerprint_trigger ('eng','BKS');
+CREATE TRIGGER aaa_indexing_ingest_or_delete AFTER INSERT OR UPDATE ON biblio.record_entry FOR EACH ROW EXECUTE PROCEDURE biblio.indexing_ingest_or_delete ();
+
+DROP TRIGGER IF EXISTS zzz_update_materialized_simple_rec_delete_tgr ON biblio.record_entry;
+
+CREATE OR REPLACE FUNCTION oils_xpath_table ( key TEXT, document_field TEXT, relation_name TEXT, xpaths TEXT, criteria TEXT )
+RETURNS SETOF RECORD AS $func$
+DECLARE
+    xpath_list  TEXT[];
+    select_list TEXT[];
+    where_list  TEXT[];
+    q           TEXT;
+    out_record  RECORD;
+    empty_test  RECORD;
+BEGIN
+    xpath_list := STRING_TO_ARRAY( xpaths, '|' );
+
+    select_list := ARRAY_APPEND( select_list, key || '::INT AS key' );
+
+    FOR i IN 1 .. ARRAY_UPPER(xpath_list,1) LOOP
+        select_list := ARRAY_APPEND(
+            select_list,
+            $sel$
+            EXPLODE_ARRAY(
+                COALESCE(
+                    NULLIF(
+                        oils_xpath(
+                            $sel$ ||
+                                quote_literal(
+                                    CASE
+                                        WHEN xpath_list[i] ~ $re$/[^/[]*@[^/]+$$re$ OR xpath_list[i] ~ $re$text\(\)$$re$ THEN xpath_list[i]
+                                        ELSE xpath_list[i] || '//text()'
+                                    END
+                                ) ||
+                            $sel$,
+                            $sel$ || document_field || $sel$
+                        ),
+                       '{}'::TEXT[]
+                    ),
+                    '{NULL}'::TEXT[]
+                )
+            ) AS c_$sel$ || i
+        );
+        where_list := ARRAY_APPEND(
+            where_list,
+            'c_' || i || ' IS NOT NULL'
+        );
+    END LOOP;
+
+    q := $q$
+SELECT * FROM (
+    SELECT $q$ || ARRAY_TO_STRING( select_list, ', ' ) || $q$ FROM $q$ || relation_name || $q$ WHERE ($q$ || criteria || $q$)
+)x WHERE $q$ || ARRAY_TO_STRING( where_list, ' AND ' );
+    -- RAISE NOTICE 'query: %', q;
+
+    FOR out_record IN EXECUTE q LOOP
+        RETURN NEXT out_record;
+    END LOOP;
+
+    RETURN;
+END;
+$func$ LANGUAGE PLPGSQL;
+
+CREATE OR REPLACE FUNCTION vandelay.ingest_items ( import_id BIGINT, attr_def_id BIGINT ) RETURNS SETOF vandelay.import_item AS $$
+DECLARE
+
+    owning_lib      TEXT;
+    circ_lib        TEXT;
+    call_number     TEXT;
+    copy_number     TEXT;
+    status          TEXT;
+    location        TEXT;
+    circulate       TEXT;
+    deposit         TEXT;
+    deposit_amount  TEXT;
+    ref             TEXT;
+    holdable        TEXT;
+    price           TEXT;
+    barcode         TEXT;
+    circ_modifier   TEXT;
+    circ_as_type    TEXT;
+    alert_message   TEXT;
+    opac_visible    TEXT;
+    pub_note        TEXT;
+    priv_note       TEXT;
+
+    attr_def        RECORD;
+    tmp_attr_set    RECORD;
+    attr_set        vandelay.import_item%ROWTYPE;
+
+    xpath           TEXT;
+
+BEGIN
+
+    SELECT * INTO attr_def FROM vandelay.import_item_attr_definition WHERE id = attr_def_id;
+
+    IF FOUND THEN
+
+        attr_set.definition := attr_def.id; 
+    
+        -- Build the combined XPath
+    
+        owning_lib :=
+            CASE
+                WHEN attr_def.owning_lib IS NULL THEN 'null()'
+                WHEN LENGTH( attr_def.owning_lib ) = 1 THEN '//*[@tag="' || attr_def.tag || '"]/*[@code="' || attr_def.owning_lib || '"]'
+                ELSE '//*[@tag="' || attr_def.tag || '"]/*' || attr_def.owning_lib
+            END;
+    
+        circ_lib :=
+            CASE
+                WHEN attr_def.circ_lib IS NULL THEN 'null()'
+                WHEN LENGTH( attr_def.circ_lib ) = 1 THEN '//*[@tag="' || attr_def.tag || '"]/*[@code="' || attr_def.circ_lib || '"]'
+                ELSE '//*[@tag="' || attr_def.tag || '"]/*' || attr_def.circ_lib
+            END;
+    
+        call_number :=
+            CASE
+                WHEN attr_def.call_number IS NULL THEN 'null()'
+                WHEN LENGTH( attr_def.call_number ) = 1 THEN '//*[@tag="' || attr_def.tag || '"]/*[@code="' || attr_def.call_number || '"]'
+                ELSE '//*[@tag="' || attr_def.tag || '"]/*' || attr_def.call_number
+            END;
+    
+        copy_number :=
+            CASE
+                WHEN attr_def.copy_number IS NULL THEN 'null()'
+                WHEN LENGTH( attr_def.copy_number ) = 1 THEN '//*[@tag="' || attr_def.tag || '"]/*[@code="' || attr_def.copy_number || '"]'
+                ELSE '//*[@tag="' || attr_def.tag || '"]/*' || attr_def.copy_number
+            END;
+    
+        status :=
+            CASE
+                WHEN attr_def.status IS NULL THEN 'null()'
+                WHEN LENGTH( attr_def.status ) = 1 THEN '//*[@tag="' || attr_def.tag || '"]/*[@code="' || attr_def.status || '"]'
+                ELSE '//*[@tag="' || attr_def.tag || '"]/*' || attr_def.status
+            END;
+    
+        location :=
+            CASE
+                WHEN attr_def.location IS NULL THEN 'null()'
+                WHEN LENGTH( attr_def.location ) = 1 THEN '//*[@tag="' || attr_def.tag || '"]/*[@code="' || attr_def.location || '"]'
+                ELSE '//*[@tag="' || attr_def.tag || '"]/*' || attr_def.location
+            END;
+    
+        circulate :=
+            CASE
+                WHEN attr_def.circulate IS NULL THEN 'null()'
+                WHEN LENGTH( attr_def.circulate ) = 1 THEN '//*[@tag="' || attr_def.tag || '"]/*[@code="' || attr_def.circulate || '"]'
+                ELSE '//*[@tag="' || attr_def.tag || '"]/*' || attr_def.circulate
+            END;
+    
+        deposit :=
+            CASE
+                WHEN attr_def.deposit IS NULL THEN 'null()'
+                WHEN LENGTH( attr_def.deposit ) = 1 THEN '//*[@tag="' || attr_def.tag || '"]/*[@code="' || attr_def.deposit || '"]'
+                ELSE '//*[@tag="' || attr_def.tag || '"]/*' || attr_def.deposit
+            END;
+    
+        deposit_amount :=
+            CASE
+                WHEN attr_def.deposit_amount IS NULL THEN 'null()'
+                WHEN LENGTH( attr_def.deposit_amount ) = 1 THEN '//*[@tag="' || attr_def.tag || '"]/*[@code="' || attr_def.deposit_amount || '"]'
+                ELSE '//*[@tag="' || attr_def.tag || '"]/*' || attr_def.deposit_amount
+            END;
+    
+        ref :=
+            CASE
+                WHEN attr_def.ref IS NULL THEN 'null()'
+                WHEN LENGTH( attr_def.ref ) = 1 THEN '//*[@tag="' || attr_def.tag || '"]/*[@code="' || attr_def.ref || '"]'
+                ELSE '//*[@tag="' || attr_def.tag || '"]/*' || attr_def.ref
+            END;
+    
+        holdable :=
+            CASE
+                WHEN attr_def.holdable IS NULL THEN 'null()'
+                WHEN LENGTH( attr_def.holdable ) = 1 THEN '//*[@tag="' || attr_def.tag || '"]/*[@code="' || attr_def.holdable || '"]'
+                ELSE '//*[@tag="' || attr_def.tag || '"]/*' || attr_def.holdable
+            END;
+    
+        price :=
+            CASE
+                WHEN attr_def.price IS NULL THEN 'null()'
+                WHEN LENGTH( attr_def.price ) = 1 THEN '//*[@tag="' || attr_def.tag || '"]/*[@code="' || attr_def.price || '"]'
+                ELSE '//*[@tag="' || attr_def.tag || '"]/*' || attr_def.price
+            END;
+    
+        barcode :=
+            CASE
+                WHEN attr_def.barcode IS NULL THEN 'null()'
+                WHEN LENGTH( attr_def.barcode ) = 1 THEN '//*[@tag="' || attr_def.tag || '"]/*[@code="' || attr_def.barcode || '"]'
+                ELSE '//*[@tag="' || attr_def.tag || '"]/*' || attr_def.barcode
+            END;
+    
+        circ_modifier :=
+            CASE
+                WHEN attr_def.circ_modifier IS NULL THEN 'null()'
+                WHEN LENGTH( attr_def.circ_modifier ) = 1 THEN '//*[@tag="' || attr_def.tag || '"]/*[@code="' || attr_def.circ_modifier || '"]'
+                ELSE '//*[@tag="' || attr_def.tag || '"]/*' || attr_def.circ_modifier
+            END;
+    
+        circ_as_type :=
+            CASE
+                WHEN attr_def.circ_as_type IS NULL THEN 'null()'
+                WHEN LENGTH( attr_def.circ_as_type ) = 1 THEN '//*[@tag="' || attr_def.tag || '"]/*[@code="' || attr_def.circ_as_type || '"]'
+                ELSE '//*[@tag="' || attr_def.tag || '"]/*' || attr_def.circ_as_type
+            END;
+    
+        alert_message :=
+            CASE
+                WHEN attr_def.alert_message IS NULL THEN 'null()'
+                WHEN LENGTH( attr_def.alert_message ) = 1 THEN '//*[@tag="' || attr_def.tag || '"]/*[@code="' || attr_def.alert_message || '"]'
+                ELSE '//*[@tag="' || attr_def.tag || '"]/*' || attr_def.alert_message
+            END;
+    
+        opac_visible :=
+            CASE
+                WHEN attr_def.opac_visible IS NULL THEN 'null()'
+                WHEN LENGTH( attr_def.opac_visible ) = 1 THEN '//*[@tag="' || attr_def.tag || '"]/*[@code="' || attr_def.opac_visible || '"]'
+                ELSE '//*[@tag="' || attr_def.tag || '"]/*' || attr_def.opac_visible
+            END;
+
+        pub_note :=
+            CASE
+                WHEN attr_def.pub_note IS NULL THEN 'null()'
+                WHEN LENGTH( attr_def.pub_note ) = 1 THEN '//*[@tag="' || attr_def.tag || '"]/*[@code="' || attr_def.pub_note || '"]'
+                ELSE '//*[@tag="' || attr_def.tag || '"]/*' || attr_def.pub_note
+            END;
+        priv_note :=
+            CASE
+                WHEN attr_def.priv_note IS NULL THEN 'null()'
+                WHEN LENGTH( attr_def.priv_note ) = 1 THEN '//*[@tag="' || attr_def.tag || '"]/*[@code="' || attr_def.priv_note || '"]'
+                ELSE '//*[@tag="' || attr_def.tag || '"]/*' || attr_def.priv_note
+            END;
+    
+    
+        xpath := 
+            owning_lib      || '|' || 
+            circ_lib        || '|' || 
+            call_number     || '|' || 
+            copy_number     || '|' || 
+            status          || '|' || 
+            location        || '|' || 
+            circulate       || '|' || 
+            deposit         || '|' || 
+            deposit_amount  || '|' || 
+            ref             || '|' || 
+            holdable        || '|' || 
+            price           || '|' || 
+            barcode         || '|' || 
+            circ_modifier   || '|' || 
+            circ_as_type    || '|' || 
+            alert_message   || '|' || 
+            pub_note        || '|' || 
+            priv_note       || '|' || 
+            opac_visible;
+
+        -- RAISE NOTICE 'XPath: %', xpath;
+        
+        FOR tmp_attr_set IN
+                SELECT  *
+                  FROM  oils_xpath_table( 'id', 'marc', 'vandelay.queued_bib_record', xpath, 'id = ' || import_id )
+                            AS t( id INT, ol TEXT, clib TEXT, cn TEXT, cnum TEXT, cs TEXT, cl TEXT, circ TEXT,
+                                  dep TEXT, dep_amount TEXT, r TEXT, hold TEXT, pr TEXT, bc TEXT, circ_mod TEXT,
+                                  circ_as TEXT, amessage TEXT, note TEXT, pnote TEXT, opac_vis TEXT )
+        LOOP
+    
+            tmp_attr_set.pr = REGEXP_REPLACE(tmp_attr_set.pr, E'[^0-9\\.]', '', 'g');
+            tmp_attr_set.dep_amount = REGEXP_REPLACE(tmp_attr_set.dep_amount, E'[^0-9\\.]', '', 'g');
+
+            tmp_attr_set.pr := NULLIF( tmp_attr_set.pr, '' );
+            tmp_attr_set.dep_amount := NULLIF( tmp_attr_set.dep_amount, '' );
+    
+            SELECT id INTO attr_set.owning_lib FROM actor.org_unit WHERE shortname = UPPER(tmp_attr_set.ol); -- INT
+            SELECT id INTO attr_set.circ_lib FROM actor.org_unit WHERE shortname = UPPER(tmp_attr_set.clib); -- INT
+            SELECT id INTO attr_set.status FROM config.copy_status WHERE LOWER(name) = LOWER(tmp_attr_set.cs); -- INT
+    
+            SELECT  id INTO attr_set.location
+              FROM  asset.copy_location
+              WHERE LOWER(name) = LOWER(tmp_attr_set.cl)
+                    AND asset.copy_location.owning_lib = COALESCE(attr_set.owning_lib, attr_set.circ_lib); -- INT
+    
+            attr_set.circulate      :=
+                LOWER( SUBSTRING( tmp_attr_set.circ, 1, 1)) IN ('t','y','1')
+                OR LOWER(tmp_attr_set.circ) = 'circulating'; -- BOOL
+
+            attr_set.deposit        :=
+                LOWER( SUBSTRING( tmp_attr_set.dep, 1, 1 ) ) IN ('t','y','1')
+                OR LOWER(tmp_attr_set.dep) = 'deposit'; -- BOOL
+
+            attr_set.holdable       :=
+                LOWER( SUBSTRING( tmp_attr_set.hold, 1, 1 ) ) IN ('t','y','1')
+                OR LOWER(tmp_attr_set.hold) = 'holdable'; -- BOOL
+
+            attr_set.opac_visible   :=
+                LOWER( SUBSTRING( tmp_attr_set.opac_vis, 1, 1 ) ) IN ('t','y','1')
+                OR LOWER(tmp_attr_set.opac_vis) = 'visible'; -- BOOL
+
+            attr_set.ref            :=
+                LOWER( SUBSTRING( tmp_attr_set.r, 1, 1 ) ) IN ('t','y','1')
+                OR LOWER(tmp_attr_set.r) = 'reference'; -- BOOL
+    
+            attr_set.copy_number    := tmp_attr_set.cnum::INT; -- INT,
+            attr_set.deposit_amount := tmp_attr_set.dep_amount::NUMERIC(6,2); -- NUMERIC(6,2),
+            attr_set.price          := tmp_attr_set.pr::NUMERIC(8,2); -- NUMERIC(8,2),
+    
+            attr_set.call_number    := tmp_attr_set.cn; -- TEXT
+            attr_set.barcode        := tmp_attr_set.bc; -- TEXT,
+            attr_set.circ_modifier  := tmp_attr_set.circ_mod; -- TEXT,
+            attr_set.circ_as_type   := tmp_attr_set.circ_as; -- TEXT,
+            attr_set.alert_message  := tmp_attr_set.amessage; -- TEXT,
+            attr_set.pub_note       := tmp_attr_set.note; -- TEXT,
+            attr_set.priv_note      := tmp_attr_set.pnote; -- TEXT,
+            attr_set.alert_message  := tmp_attr_set.amessage; -- TEXT,
+    
+            RETURN NEXT attr_set;
+    
+        END LOOP;
+    
+    END IF;
+
+    RETURN;
+
+END;
+$$ LANGUAGE PLPGSQL;
+
+CREATE OR REPLACE FUNCTION vandelay.ingest_bib_items ( ) RETURNS TRIGGER AS $func$
+DECLARE
+    attr_def    BIGINT;
+    item_data   vandelay.import_item%ROWTYPE;
+BEGIN
+
+    SELECT item_attr_def INTO attr_def FROM vandelay.bib_queue WHERE id = NEW.queue;
+
+    FOR item_data IN SELECT * FROM vandelay.ingest_items( NEW.id::BIGINT, attr_def ) LOOP
+        INSERT INTO vandelay.import_item (
+            record,
+            definition,
+            owning_lib,
+            circ_lib,
+            call_number,
+            copy_number,
+            status,
+            location,
+            circulate,
+            deposit,
+            deposit_amount,
+            ref,
+            holdable,
+            price,
+            barcode,
+            circ_modifier,
+            circ_as_type,
+            alert_message,
+            pub_note,
+            priv_note,
+            opac_visible
+        ) VALUES (
+            NEW.id,
+            item_data.definition,
+            item_data.owning_lib,
+            item_data.circ_lib,
+            item_data.call_number,
+            item_data.copy_number,
+            item_data.status,
+            item_data.location,
+            item_data.circulate,
+            item_data.deposit,
+            item_data.deposit_amount,
+            item_data.ref,
+            item_data.holdable,
+            item_data.price,
+            item_data.barcode,
+            item_data.circ_modifier,
+            item_data.circ_as_type,
+            item_data.alert_message,
+            item_data.pub_note,
+            item_data.priv_note,
+            item_data.opac_visible
+        );
+    END LOOP;
+
+    RETURN NULL;
+END;
+$func$ LANGUAGE PLPGSQL;
+
+CREATE OR REPLACE FUNCTION acq.create_acq_seq     ( sch TEXT, tbl TEXT ) RETURNS BOOL AS $creator$
+BEGIN
+    EXECUTE $$
+        CREATE SEQUENCE acq.$$ || sch || $$_$$ || tbl || $$_pkey_seq;
+    $$;
+	RETURN TRUE;
+END;
+$creator$ LANGUAGE 'plpgsql';
+
+CREATE OR REPLACE FUNCTION acq.create_acq_history ( sch TEXT, tbl TEXT ) RETURNS BOOL AS $creator$
+BEGIN
+    EXECUTE $$
+        CREATE TABLE acq.$$ || sch || $$_$$ || tbl || $$_history (
+            audit_id	BIGINT				PRIMARY KEY,
+            audit_time	TIMESTAMP WITH TIME ZONE	NOT NULL,
+            audit_action	TEXT				NOT NULL,
+            LIKE $$ || sch || $$.$$ || tbl || $$
+        );
+    $$;
+	RETURN TRUE;
+END;
+$creator$ LANGUAGE 'plpgsql';
+
+CREATE OR REPLACE FUNCTION acq.create_acq_func    ( sch TEXT, tbl TEXT ) RETURNS BOOL AS $creator$
+BEGIN
+    EXECUTE $$
+        CREATE OR REPLACE FUNCTION acq.audit_$$ || sch || $$_$$ || tbl || $$_func ()
+        RETURNS TRIGGER AS $func$
+        BEGIN
+            INSERT INTO acq.$$ || sch || $$_$$ || tbl || $$_history
+                SELECT	nextval('acq.$$ || sch || $$_$$ || tbl || $$_pkey_seq'),
+                    now(),
+                    SUBSTR(TG_OP,1,1),
+                    OLD.*;
+            RETURN NULL;
+        END;
+        $func$ LANGUAGE 'plpgsql';
+    $$;
+	RETURN TRUE;
+END;
+$creator$ LANGUAGE 'plpgsql';
+
+CREATE OR REPLACE FUNCTION acq.create_acq_update_trigger ( sch TEXT, tbl TEXT ) RETURNS BOOL AS $creator$
+BEGIN
+    EXECUTE $$
+        CREATE TRIGGER audit_$$ || sch || $$_$$ || tbl || $$_update_trigger
+            AFTER UPDATE OR DELETE ON $$ || sch || $$.$$ || tbl || $$ FOR EACH ROW
+            EXECUTE PROCEDURE acq.audit_$$ || sch || $$_$$ || tbl || $$_func ();
+    $$;
+	RETURN TRUE;
+END;
+$creator$ LANGUAGE 'plpgsql';
+
+CREATE OR REPLACE FUNCTION acq.create_acq_lifecycle     ( sch TEXT, tbl TEXT ) RETURNS BOOL AS $creator$
+BEGIN
+    EXECUTE $$
+        CREATE OR REPLACE VIEW acq.$$ || sch || $$_$$ || tbl || $$_lifecycle AS
+            SELECT	-1, now() as audit_time, '-' as audit_action, *
+              FROM	$$ || sch || $$.$$ || tbl || $$
+                UNION ALL
+            SELECT	*
+              FROM	acq.$$ || sch || $$_$$ || tbl || $$_history;
+    $$;
+	RETURN TRUE;
+END;
+$creator$ LANGUAGE 'plpgsql';
+
+-- The main event
+
+CREATE OR REPLACE FUNCTION acq.create_acq_auditor ( sch TEXT, tbl TEXT ) RETURNS BOOL AS $creator$
+BEGIN
+    PERFORM acq.create_acq_seq(sch, tbl);
+    PERFORM acq.create_acq_history(sch, tbl);
+    PERFORM acq.create_acq_func(sch, tbl);
+    PERFORM acq.create_acq_update_trigger(sch, tbl);
+    PERFORM acq.create_acq_lifecycle(sch, tbl);
+    RETURN TRUE;
+END;
+$creator$ LANGUAGE 'plpgsql';
+
+SELECT acq.create_acq_auditor ( 'acq', 'purchase_order' );
+CREATE INDEX acq_po_hist_id_idx            ON acq.acq_purchase_order_history( id );
+
+SELECT acq.create_acq_auditor ( 'acq', 'lineitem' );
+CREATE INDEX acq_lineitem_hist_id_idx            ON acq.acq_lineitem_history( id );
+
+CREATE OR REPLACE VIEW acq.fund_debit_total AS
+    SELECT  fund.id AS fund,
+            fund_debit.encumbrance AS encumbrance,
+            SUM( COALESCE( fund_debit.amount, 0 ) ) AS amount
+      FROM acq.fund AS fund
+			LEFT JOIN acq.fund_debit AS fund_debit
+				ON ( fund.id = fund_debit.fund )
+      GROUP BY 1,2;
+
+CREATE TABLE acq.debit_attribution (
+	id                     INT         NOT NULL PRIMARY KEY,
+	fund_debit             INT         NOT NULL
+	                                   REFERENCES acq.fund_debit
+	                                   DEFERRABLE INITIALLY DEFERRED,
+    debit_amount           NUMERIC     NOT NULL,
+	funding_source_credit  INT         REFERENCES acq.funding_source_credit
+	                                   DEFERRABLE INITIALLY DEFERRED,
+    credit_amount          NUMERIC
+);
+
+CREATE INDEX acq_attribution_debit_idx
+	ON acq.debit_attribution( fund_debit );
+
+CREATE INDEX acq_attribution_credit_idx
+	ON acq.debit_attribution( funding_source_credit );
+
+CREATE OR REPLACE FUNCTION acq.attribute_debits() RETURNS VOID AS $$
+/*
+Function to attribute expenditures and encumbrances to funding source credits,
+and thereby to funding sources.
+
+Read the debits in chonological order, attributing each one to one or
+more funding source credits.  Constraints:
+
+1. Don't attribute more to a credit than the amount of the credit.
+
+2. For a given fund, don't attribute more to a funding source than the
+source has allocated to that fund.
+
+3. Attribute debits to credits with deadlines before attributing them to
+credits without deadlines.  Otherwise attribute to the earliest credits
+first, based on the deadline date when present, or on the effective date
+when there is no deadline.  Use funding_source_credit.id as a tie-breaker.
+This ordering is defined by an ORDER BY clause on the view
+acq.ordered_funding_source_credit.
+
+Start by truncating the table acq.debit_attribution.  Then insert a row
+into that table for each attribution.  If a debit cannot be fully
+attributed, insert a row for the unattributable balance, with the 
+funding_source_credit and credit_amount columns NULL.
+*/
+DECLARE
+	curr_fund_source_bal RECORD;
+	seqno                INT;     -- sequence num for credits applicable to a fund
+	fund_credit          RECORD;  -- current row in temp t_fund_credit table
+	fc                   RECORD;  -- used for loading t_fund_credit table
+	sc                   RECORD;  -- used for loading t_fund_credit table
+	--
+	-- Used exclusively in the main loop:
+	--
+	deb                 RECORD;   -- current row from acq.fund_debit table
+	curr_credit_bal     RECORD;   -- current row from temp t_credit table
+	debit_balance       NUMERIC;  -- amount left to attribute for current debit
+	conv_debit_balance  NUMERIC;  -- debit balance in currency of the fund
+	attr_amount         NUMERIC;  -- amount being attributed, in currency of debit
+	conv_attr_amount    NUMERIC;  -- amount being attributed, in currency of source
+	conv_cred_balance   NUMERIC;  -- credit_balance in the currency of the fund
+	conv_alloc_balance  NUMERIC;  -- allocated balance in the currency of the fund
+	attrib_count        INT;      -- populates id of acq.debit_attribution
+BEGIN
+	--
+	-- Load a temporary table.  For each combination of fund and funding source,
+	-- load an entry with the total amount allocated to that fund by that source.
+	-- This sum may reflect transfers as well as original allocations.  We will
+	-- reduce this balance whenever we attribute debits to it.
+	--
+	CREATE TEMP TABLE t_fund_source_bal
+	ON COMMIT DROP AS
+		SELECT
+			fund AS fund,
+			funding_source AS source,
+			sum( amount ) AS balance
+		FROM
+			acq.fund_allocation
+		GROUP BY
+			fund,
+			funding_source
+		HAVING
+			sum( amount ) > 0;
+	--
+	CREATE INDEX t_fund_source_bal_idx
+		ON t_fund_source_bal( fund, source );
+	-------------------------------------------------------------------------------
+	--
+	-- Load another temporary table.  For each fund, load zero or more
+	-- funding source credits from which that fund can get money.
+	--
+	CREATE TEMP TABLE t_fund_credit (
+		fund        INT,
+		seq         INT,
+		credit      INT
+	) ON COMMIT DROP;
+	--
+	FOR fc IN
+		SELECT DISTINCT fund
+		FROM acq.fund_allocation
+		ORDER BY fund
+	LOOP                  -- Loop over the funds
+		seqno := 1;
+		FOR sc IN
+			SELECT
+				ofsc.id
+			FROM
+				acq.ordered_funding_source_credit AS ofsc
+			WHERE
+				ofsc.funding_source IN
+				(
+					SELECT funding_source
+					FROM acq.fund_allocation
+					WHERE fund = fc.fund
+				)
+    		ORDER BY
+    		    ofsc.sort_priority,
+    		    ofsc.sort_date,
+    		    ofsc.id
+		LOOP                        -- Add each credit to the list
+			INSERT INTO t_fund_credit (
+				fund,
+				seq,
+				credit
+			) VALUES (
+				fc.fund,
+				seqno,
+				sc.id
+			);
+			--RAISE NOTICE 'Fund % credit %', fc.fund, sc.id;
+			seqno := seqno + 1;
+		END LOOP;     -- Loop over credits for a given fund
+	END LOOP;         -- Loop over funds
+	--
+	CREATE INDEX t_fund_credit_idx
+		ON t_fund_credit( fund, seq );
+	-------------------------------------------------------------------------------
+	--
+	-- Load yet another temporary table.  This one is a list of funding source
+	-- credits, with their balances.  We shall reduce those balances as we
+	-- attribute debits to them.
+	--
+	CREATE TEMP TABLE t_credit
+	ON COMMIT DROP AS
+        SELECT
+            fsc.id AS credit,
+            fsc.funding_source AS source,
+            fsc.amount AS balance,
+            fs.currency_type AS currency_type
+        FROM
+            acq.funding_source_credit AS fsc,
+            acq.funding_source fs
+        WHERE
+            fsc.funding_source = fs.id
+			AND fsc.amount > 0;
+	--
+	CREATE INDEX t_credit_idx
+		ON t_credit( credit );
+	--
+	-------------------------------------------------------------------------------
+	--
+	-- Now that we have loaded the lookup tables: loop through the debits,
+	-- attributing each one to one or more funding source credits.
+	-- 
+	truncate table acq.debit_attribution;
+	--
+	attrib_count := 0;
+	FOR deb in
+		SELECT
+			fd.id,
+			fd.fund,
+			fd.amount,
+			f.currency_type,
+			fd.encumbrance
+		FROM
+			acq.fund_debit fd,
+			acq.fund f
+		WHERE
+			fd.fund = f.id
+		ORDER BY
+			fd.id
+	LOOP
+		--RAISE NOTICE 'Debit %, fund %', deb.id, deb.fund;
+		--
+		debit_balance := deb.amount;
+		--
+		-- Loop over the funding source credits that are eligible
+		-- to pay for this debit
+		--
+		FOR fund_credit IN
+			SELECT
+				credit
+			FROM
+				t_fund_credit
+			WHERE
+				fund = deb.fund
+			ORDER BY
+				seq
+		LOOP
+			--RAISE NOTICE '   Examining credit %', fund_credit.credit;
+			--
+			-- Look up the balance for this credit.  If it's zero, then
+			-- it's not useful, so treat it as if you didn't find it.
+			-- (Actually there shouldn't be any zero balances in the table,
+			-- but we check just to make sure.)
+			--
+			SELECT *
+			INTO curr_credit_bal
+			FROM t_credit
+			WHERE
+				credit = fund_credit.credit
+				AND balance > 0;
+			--
+			IF curr_credit_bal IS NULL THEN
+				--
+				-- This credit is exhausted; try the next one.
+				--
+				CONTINUE;
+			END IF;
+			--
+			--
+			-- At this point we have an applicable credit with some money left.
+			-- Now see if the relevant funding_source has any money left.
+			--
+			-- Look up the balance of the allocation for this combination of
+			-- fund and source.  If you find such an entry, but it has a zero
+			-- balance, then it's not useful, so treat it as unfound.
+			-- (Actually there shouldn't be any zero balances in the table,
+			-- but we check just to make sure.)
+			--
+			SELECT *
+			INTO curr_fund_source_bal
+			FROM t_fund_source_bal
+			WHERE
+				fund = deb.fund
+				AND source = curr_credit_bal.source
+				AND balance > 0;
+			--
+			IF curr_fund_source_bal IS NULL THEN
+				--
+				-- This fund/source doesn't exist or is already exhausted,
+				-- so we can't use this credit.  Go on to the next one.
+				--
+				CONTINUE;
+			END IF;
+			--
+			-- Convert the available balances to the currency of the fund
+			--
+			conv_alloc_balance := curr_fund_source_bal.balance * acq.exchange_ratio(
+				curr_credit_bal.currency_type, deb.currency_type );
+			conv_cred_balance := curr_credit_bal.balance * acq.exchange_ratio(
+				curr_credit_bal.currency_type, deb.currency_type );
+			--
+			-- Determine how much we can attribute to this credit: the minimum
+			-- of the debit amount, the fund/source balance, and the
+			-- credit balance
+			--
+			--RAISE NOTICE '   deb bal %', debit_balance;
+			--RAISE NOTICE '      source % balance %', curr_credit_bal.source, conv_alloc_balance;
+			--RAISE NOTICE '      credit % balance %', curr_credit_bal.credit, conv_cred_balance;
+			--
+			conv_attr_amount := NULL;
+			attr_amount := debit_balance;
+			--
+			IF attr_amount > conv_alloc_balance THEN
+				attr_amount := conv_alloc_balance;
+				conv_attr_amount := curr_fund_source_bal.balance;
+			END IF;
+			IF attr_amount > conv_cred_balance THEN
+				attr_amount := conv_cred_balance;
+				conv_attr_amount := curr_credit_bal.balance;
+			END IF;
+			--
+			-- If we're attributing all of one of the balances, then that's how
+			-- much we will deduct from the balances, and we already captured
+			-- that amount above.  Otherwise we must convert the amount of the
+			-- attribution from the currency of the fund back to the currency of
+			-- the funding source.
+			--
+			IF conv_attr_amount IS NULL THEN
+				conv_attr_amount := attr_amount * acq.exchange_ratio(
+					deb.currency_type, curr_credit_bal.currency_type );
+			END IF;
+			--
+			-- Insert a row to record the attribution
+			--
+			attrib_count := attrib_count + 1;
+			INSERT INTO acq.debit_attribution (
+				id,
+				fund_debit,
+				debit_amount,
+				funding_source_credit,
+				credit_amount
+			) VALUES (
+				attrib_count,
+				deb.id,
+				attr_amount,
+				curr_credit_bal.credit,
+				conv_attr_amount
+			);
+			--
+			-- Subtract the attributed amount from the various balances
+			--
+			debit_balance := debit_balance - attr_amount;
+			curr_fund_source_bal.balance := curr_fund_source_bal.balance - conv_attr_amount;
+			--
+			IF curr_fund_source_bal.balance <= 0 THEN
+				--
+				-- This allocation is exhausted.  Delete it so
+				-- that we don't waste time looking at it again.
+				--
+				DELETE FROM t_fund_source_bal
+				WHERE
+					fund = curr_fund_source_bal.fund
+					AND source = curr_fund_source_bal.source;
+			ELSE
+				UPDATE t_fund_source_bal
+				SET balance = balance - conv_attr_amount
+				WHERE
+					fund = curr_fund_source_bal.fund
+					AND source = curr_fund_source_bal.source;
+			END IF;
+			--
+			IF curr_credit_bal.balance <= 0 THEN
+				--
+				-- This funding source credit is exhausted.  Delete it
+				-- so that we don't waste time looking at it again.
+				--
+				--DELETE FROM t_credit
+				--WHERE
+				--	credit = curr_credit_bal.credit;
+				--
+				DELETE FROM t_fund_credit
+				WHERE
+					credit = curr_credit_bal.credit;
+			ELSE
+				UPDATE t_credit
+				SET balance = curr_credit_bal.balance
+				WHERE
+					credit = curr_credit_bal.credit;
+			END IF;
+			--
+			-- Are we done with this debit yet?
+			--
+			IF debit_balance <= 0 THEN
+				EXIT;       -- We've fully attributed this debit; stop looking at credits.
+			END IF;
+		END LOOP;       -- End loop over credits
+		--
+		IF debit_balance <> 0 THEN
+			--
+			-- We weren't able to attribute this debit, or at least not
+			-- all of it.  Insert a row for the unattributed balance.
+			--
+			attrib_count := attrib_count + 1;
+			INSERT INTO acq.debit_attribution (
+				id,
+				fund_debit,
+				debit_amount,
+				funding_source_credit,
+				credit_amount
+			) VALUES (
+				attrib_count,
+				deb.id,
+				debit_balance,
+				NULL,
+				NULL
+			);
+		END IF;
+	END LOOP;   -- End of loop over debits
+END;
+$$ LANGUAGE 'plpgsql';
+
+CREATE OR REPLACE FUNCTION extract_marc_field ( TEXT, BIGINT, TEXT, TEXT ) RETURNS TEXT AS $$
+DECLARE
+    query TEXT;
+    output TEXT;
+BEGIN
+    query := $q$
+        SELECT  regexp_replace(
+                    oils_xpath_string(
+                        $q$ || quote_literal($3) || $q$,
+                        marc,
+                        ' '
+                    ),
+                    $q$ || quote_literal($4) || $q$,
+                    '',
+                    'g')
+          FROM  $q$ || $1 || $q$
+          WHERE id = $q$ || $2;
+
+    EXECUTE query INTO output;
+
+    -- RAISE NOTICE 'query: %, output; %', query, output;
+
+    RETURN output;
+END;
+$$ LANGUAGE PLPGSQL IMMUTABLE;
+
+CREATE OR REPLACE FUNCTION extract_marc_field ( TEXT, BIGINT, TEXT ) RETURNS TEXT AS $$
+    SELECT extract_marc_field($1,$2,$3,'');
+$$ LANGUAGE SQL IMMUTABLE;
+
+CREATE OR REPLACE FUNCTION asset.merge_record_assets( target_record BIGINT, source_record BIGINT ) RETURNS INT AS $func$
+DECLARE
+    moved_objects INT := 0;
+    source_cn     asset.call_number%ROWTYPE;
+    target_cn     asset.call_number%ROWTYPE;
+    metarec       metabib.metarecord%ROWTYPE;
+    hold          action.hold_request%ROWTYPE;
+    ser_rec       serial.record_entry%ROWTYPE;
+    uri_count     INT := 0;
+    counter       INT := 0;
+    uri_datafield TEXT;
+    uri_text      TEXT := '';
+BEGIN
+
+    -- move any 856 entries on records that have at least one MARC-mapped URI entry
+    SELECT  INTO uri_count COUNT(*)
+      FROM  asset.uri_call_number_map m
+            JOIN asset.call_number cn ON (m.call_number = cn.id)
+      WHERE cn.record = source_record;
+
+    IF uri_count > 0 THEN
+
+        SELECT  COUNT(*) INTO counter
+          FROM  oils_xpath_table(
+                    'id',
+                    'marc',
+                    'biblio.record_entry',
+                    '//*[@tag="856"]',
+                    'id=' || source_record
+                ) as t(i int,c text);
+
+        FOR i IN 1 .. counter LOOP
+            SELECT  '<datafield xmlns="http://www.loc.gov/MARC21/slim"' ||
+                        ' tag="856"' || 
+                        ' ind1="' || FIRST(ind1) || '"'  || 
+                        ' ind2="' || FIRST(ind2) || '">' || 
+                        array_to_string(
+                            array_accum(
+                                '<subfield code="' || subfield || '">' ||
+                                regexp_replace(
+                                    regexp_replace(
+                                        regexp_replace(data,'&','&amp;','g'),
+                                        '>', '&gt;', 'g'
+                                    ),
+                                    '<', '&lt;', 'g'
+                                ) || '</subfield>'
+                            ), ''
+                        ) || '</datafield>' INTO uri_datafield
+              FROM  oils_xpath_table(
+                        'id',
+                        'marc',
+                        'biblio.record_entry',
+                        '//*[@tag="856"][position()=' || i || ']/@ind1|' || 
+                        '//*[@tag="856"][position()=' || i || ']/@ind2|' || 
+                        '//*[@tag="856"][position()=' || i || ']/*/@code|' ||
+                        '//*[@tag="856"][position()=' || i || ']/*[@code]',
+                        'id=' || source_record
+                    ) as t(id int,ind1 text, ind2 text,subfield text,data text);
+
+            uri_text := uri_text || uri_datafield;
+        END LOOP;
+
+        IF uri_text <> '' THEN
+            UPDATE  biblio.record_entry
+              SET   marc = regexp_replace(marc,'(</[^>]*record>)', uri_text || E'\\1')
+              WHERE id = target_record;
+        END IF;
+
+    END IF;
+
+    -- Find and move metarecords to the target record
+    SELECT  INTO metarec *
+      FROM  metabib.metarecord
+      WHERE master_record = source_record;
+
+    IF FOUND THEN
+        UPDATE  metabib.metarecord
+          SET   master_record = target_record,
+            mods = NULL
+          WHERE id = metarec.id;
+
+        moved_objects := moved_objects + 1;
+    END IF;
+
+    -- Find call numbers attached to the source ...
+    FOR source_cn IN SELECT * FROM asset.call_number WHERE record = source_record LOOP
+
+        SELECT  INTO target_cn *
+          FROM  asset.call_number
+          WHERE label = source_cn.label
+            AND owning_lib = source_cn.owning_lib
+            AND record = target_record;
+
+        -- ... and if there's a conflicting one on the target ...
+        IF FOUND THEN
+
+            -- ... move the copies to that, and ...
+            UPDATE  asset.copy
+              SET   call_number = target_cn.id
+              WHERE call_number = source_cn.id;
+
+            -- ... move V holds to the move-target call number
+            FOR hold IN SELECT * FROM action.hold_request WHERE target = source_cn.id AND hold_type = 'V' LOOP
+
+                UPDATE  action.hold_request
+                  SET   target = target_cn.id
+                  WHERE id = hold.id;
+
+                moved_objects := moved_objects + 1;
+            END LOOP;
+
+        -- ... if not ...
+        ELSE
+            -- ... just move the call number to the target record
+            UPDATE  asset.call_number
+              SET   record = target_record
+              WHERE id = source_cn.id;
+        END IF;
+
+        moved_objects := moved_objects + 1;
+    END LOOP;
+
+    -- Find T holds targeting the source record ...
+    FOR hold IN SELECT * FROM action.hold_request WHERE target = source_record AND hold_type = 'T' LOOP
+
+        -- ... and move them to the target record
+        UPDATE  action.hold_request
+          SET   target = target_record
+          WHERE id = hold.id;
+
+        moved_objects := moved_objects + 1;
+    END LOOP;
+
+    -- Find serial records targeting the source record ...
+    FOR ser_rec IN SELECT * FROM serial.record_entry WHERE record = source_record LOOP
+        -- ... and move them to the target record
+        UPDATE  serial.record_entry
+          SET   record = target_record
+          WHERE id = ser_rec.id;
+
+        moved_objects := moved_objects + 1;
+    END LOOP;
+
+    -- Finally, "delete" the source record
+    DELETE FROM biblio.record_entry WHERE id = source_record;
+
+    -- That's all, folks!
+    RETURN moved_objects;
+END;
+$func$ LANGUAGE plpgsql;
+
+CREATE OR REPLACE FUNCTION acq.transfer_fund(
+	old_fund   IN INT,
+	old_amount IN NUMERIC,     -- in currency of old fund
+	new_fund   IN INT,
+	new_amount IN NUMERIC,     -- in currency of new fund
+	user_id    IN INT,
+	xfer_note  IN TEXT         -- to be recorded in acq.fund_transfer
+	-- ,funding_source_in IN INT  -- if user wants to specify a funding source (see notes)
+) RETURNS VOID AS $$
+/* -------------------------------------------------------------------------------
+
+Function to transfer money from one fund to another.
+
+A transfer is represented as a pair of entries in acq.fund_allocation, with a
+negative amount for the old (losing) fund and a positive amount for the new
+(gaining) fund.  In some cases there may be more than one such pair of entries
+in order to pull the money from different funding sources, or more specifically
+from different funding source credits.  For each such pair there is also an
+entry in acq.fund_transfer.
+
+Since funding_source is a non-nullable column in acq.fund_allocation, we must
+choose a funding source for the transferred money to come from.  This choice
+must meet two constraints, so far as possible:
+
+1. The amount transferred from a given funding source must not exceed the
+amount allocated to the old fund by the funding source.  To that end we
+compare the amount being transferred to the amount allocated.
+
+2. We shouldn't transfer money that has already been spent or encumbered, as
+defined by the funding attribution process.  We attribute expenses to the
+oldest funding source credits first.  In order to avoid transferring that
+attributed money, we reverse the priority, transferring from the newest funding
+source credits first.  There can be no guarantee that this approach will
+avoid overcommitting a fund, but no other approach can do any better.
+
+In this context the age of a funding source credit is defined by the
+deadline_date for credits with deadline_dates, and by the effective_date for
+credits without deadline_dates, with the proviso that credits with deadline_dates
+are all considered "older" than those without.
+
+----------
+
+In the signature for this function, there is one last parameter commented out,
+named "funding_source_in".  Correspondingly, the WHERE clause for the query
+driving the main loop has an OR clause commented out, which references the
+funding_source_in parameter.
+
+If these lines are uncommented, this function will allow the user optionally to
+restrict a fund transfer to a specified funding source.  If the source
+parameter is left NULL, then there will be no such restriction.
+
+------------------------------------------------------------------------------- */ 
+DECLARE
+	same_currency      BOOLEAN;
+	currency_ratio     NUMERIC;
+	old_fund_currency  TEXT;
+	old_remaining      NUMERIC;  -- in currency of old fund
+	new_fund_currency  TEXT;
+	new_fund_active    BOOLEAN;
+	new_remaining      NUMERIC;  -- in currency of new fund
+	curr_old_amt       NUMERIC;  -- in currency of old fund
+	curr_new_amt       NUMERIC;  -- in currency of new fund
+	source_addition    NUMERIC;  -- in currency of funding source
+	source_deduction   NUMERIC;  -- in currency of funding source
+	orig_allocated_amt NUMERIC;  -- in currency of funding source
+	allocated_amt      NUMERIC;  -- in currency of fund
+	source             RECORD;
+BEGIN
+	--
+	-- Sanity checks
+	--
+	IF old_fund IS NULL THEN
+		RAISE EXCEPTION 'acq.transfer_fund: old fund id is NULL';
+	END IF;
+	--
+	IF old_amount IS NULL THEN
+		RAISE EXCEPTION 'acq.transfer_fund: amount to transfer is NULL';
+	END IF;
+	--
+	-- The new fund and its amount must be both NULL or both not NULL.
+	--
+	IF new_fund IS NOT NULL AND new_amount IS NULL THEN
+		RAISE EXCEPTION 'acq.transfer_fund: amount to transfer to receiving fund is NULL';
+	END IF;
+	--
+	IF new_fund IS NULL AND new_amount IS NOT NULL THEN
+		RAISE EXCEPTION 'acq.transfer_fund: receiving fund is NULL, its amount is not NULL';
+	END IF;
+	--
+	IF user_id IS NULL THEN
+		RAISE EXCEPTION 'acq.transfer_fund: user id is NULL';
+	END IF;
+	--
+	-- Initialize the amounts to be transferred, each denominated
+	-- in the currency of its respective fund.  They will be
+	-- reduced on each iteration of the loop.
+	--
+	old_remaining := old_amount;
+	new_remaining := new_amount;
+	--
+	-- RAISE NOTICE 'Transferring % in fund % to % in fund %',
+	--	old_amount, old_fund, new_amount, new_fund;
+	--
+	-- Get the currency types of the old and new funds.
+	--
+	SELECT
+		currency_type
+	INTO
+		old_fund_currency
+	FROM
+		acq.fund
+	WHERE
+		id = old_fund;
+	--
+	IF old_fund_currency IS NULL THEN
+		RAISE EXCEPTION 'acq.transfer_fund: old fund id % is not defined', old_fund;
+	END IF;
+	--
+	IF new_fund IS NOT NULL THEN
+		SELECT
+			currency_type,
+			active
+		INTO
+			new_fund_currency,
+			new_fund_active
+		FROM
+			acq.fund
+		WHERE
+			id = new_fund;
+		--
+		IF new_fund_currency IS NULL THEN
+			RAISE EXCEPTION 'acq.transfer_fund: new fund id % is not defined', new_fund;
+		ELSIF NOT new_fund_active THEN
+			--
+			-- No point in putting money into a fund from whence you can't spend it
+			--
+			RAISE EXCEPTION 'acq.transfer_fund: new fund id % is inactive', new_fund;
+		END IF;
+		--
+		IF new_amount = old_amount THEN
+			same_currency := true;
+			currency_ratio := 1;
+		ELSE
+			--
+			-- We'll have to translate currency between funds.  We presume that
+			-- the calling code has already applied an appropriate exchange rate,
+			-- so we'll apply the same conversion to each sub-transfer.
+			--
+			same_currency := false;
+			currency_ratio := new_amount / old_amount;
+		END IF;
+	END IF;
+	--
+	-- Identify the funding source(s) from which we want to transfer the money.
+	-- The principle is that we want to transfer the newest money first, because
+	-- we spend the oldest money first.  The priority for spending is defined
+	-- by a sort of the view acq.ordered_funding_source_credit.
+	--
+	FOR source in
+		SELECT
+			ofsc.id,
+			ofsc.funding_source,
+			ofsc.amount,
+			ofsc.amount * acq.exchange_ratio( fs.currency_type, old_fund_currency )
+				AS converted_amt,
+			fs.currency_type
+		FROM
+			acq.ordered_funding_source_credit AS ofsc,
+			acq.funding_source fs
+		WHERE
+			ofsc.funding_source = fs.id
+			and ofsc.funding_source IN
+			(
+				SELECT funding_source
+				FROM acq.fund_allocation
+				WHERE fund = old_fund
+			)
+			-- and
+			-- (
+			-- 	ofsc.funding_source = funding_source_in
+			-- 	OR funding_source_in IS NULL
+			-- )
+		ORDER BY
+			ofsc.sort_priority desc,
+			ofsc.sort_date desc,
+			ofsc.id desc
+	LOOP
+		--
+		-- Determine how much money the old fund got from this funding source,
+		-- denominated in the currency types of the source and of the fund.
+		-- This result may reflect transfers from previous iterations.
+		--
+		SELECT
+			COALESCE( sum( amount ), 0 ),
+			COALESCE( sum( amount )
+				* acq.exchange_ratio( source.currency_type, old_fund_currency ), 0 )
+		INTO
+			orig_allocated_amt,     -- in currency of the source
+			allocated_amt           -- in currency of the old fund
+		FROM
+			acq.fund_allocation
+		WHERE
+			fund = old_fund
+			and funding_source = source.funding_source;
+		--	
+		-- Determine how much to transfer from this credit, in the currency
+		-- of the fund.   Begin with the amount remaining to be attributed:
+		--
+		curr_old_amt := old_remaining;
+		--
+		-- Can't attribute more than was allocated from the fund:
+		--
+		IF curr_old_amt > allocated_amt THEN
+			curr_old_amt := allocated_amt;
+		END IF;
+		--
+		-- Can't attribute more than the amount of the current credit:
+		--
+		IF curr_old_amt > source.converted_amt THEN
+			curr_old_amt := source.converted_amt;
+		END IF;
+		--
+		curr_old_amt := trunc( curr_old_amt, 2 );
+		--
+		old_remaining := old_remaining - curr_old_amt;
+		--
+		-- Determine the amount to be deducted, if any,
+		-- from the old allocation.
+		--
+		IF old_remaining > 0 THEN
+			--
+			-- In this case we're using the whole allocation, so use that
+			-- amount directly instead of applying a currency translation
+			-- and thereby inviting round-off errors.
+			--
+			source_deduction := - orig_allocated_amt;
+		ELSE 
+			source_deduction := trunc(
+				( - curr_old_amt ) *
+					acq.exchange_ratio( old_fund_currency, source.currency_type ),
+				2 );
+		END IF;
+		--
+		IF source_deduction <> 0 THEN
+			--
+			-- Insert negative allocation for old fund in fund_allocation,
+			-- converted into the currency of the funding source
+			--
+			INSERT INTO acq.fund_allocation (
+				funding_source,
+				fund,
+				amount,
+				allocator,
+				note
+			) VALUES (
+				source.funding_source,
+				old_fund,
+				source_deduction,
+				user_id,
+				'Transfer to fund ' || new_fund
+			);
+		END IF;
+		--
+		IF new_fund IS NOT NULL THEN
+			--
+			-- Determine how much to add to the new fund, in
+			-- its currency, and how much remains to be added:
+			--
+			IF same_currency THEN
+				curr_new_amt := curr_old_amt;
+			ELSE
+				IF old_remaining = 0 THEN
+					--
+					-- This is the last iteration, so nothing should be left
+					--
+					curr_new_amt := new_remaining;
+					new_remaining := 0;
+				ELSE
+					curr_new_amt := trunc( curr_old_amt * currency_ratio, 2 );
+					new_remaining := new_remaining - curr_new_amt;
+				END IF;
+			END IF;
+			--
+			-- Determine how much to add, if any,
+			-- to the new fund's allocation.
+			--
+			IF old_remaining > 0 THEN
+				--
+				-- In this case we're using the whole allocation, so use that amount
+				-- amount directly instead of applying a currency translation and
+				-- thereby inviting round-off errors.
+				--
+				source_addition := orig_allocated_amt;
+			ELSIF source.currency_type = old_fund_currency THEN
+				--
+				-- In this case we don't need a round trip currency translation,
+				-- thereby inviting round-off errors:
+				--
+				source_addition := curr_old_amt;
+			ELSE 
+				source_addition := trunc(
+					curr_new_amt *
+						acq.exchange_ratio( new_fund_currency, source.currency_type ),
+					2 );
+			END IF;
+			--
+			IF source_addition <> 0 THEN
+				--
+				-- Insert positive allocation for new fund in fund_allocation,
+				-- converted to the currency of the founding source
+				--
+				INSERT INTO acq.fund_allocation (
+					funding_source,
+					fund,
+					amount,
+					allocator,
+					note
+				) VALUES (
+					source.funding_source,
+					new_fund,
+					source_addition,
+					user_id,
+					'Transfer from fund ' || old_fund
+				);
+			END IF;
+		END IF;
+		--
+		IF trunc( curr_old_amt, 2 ) <> 0
+		OR trunc( curr_new_amt, 2 ) <> 0 THEN
+			--
+			-- Insert row in fund_transfer, using amounts in the currency of the funds
+			--
+			INSERT INTO acq.fund_transfer (
+				src_fund,
+				src_amount,
+				dest_fund,
+				dest_amount,
+				transfer_user,
+				note,
+				funding_source_credit
+			) VALUES (
+				old_fund,
+				trunc( curr_old_amt, 2 ),
+				new_fund,
+				trunc( curr_new_amt, 2 ),
+				user_id,
+				xfer_note,
+				source.id
+			);
+		END IF;
+		--
+		if old_remaining <= 0 THEN
+			EXIT;                   -- Nothing more to be transferred
+		END IF;
+	END LOOP;
+END;
+$$ LANGUAGE plpgsql;
+
+CREATE OR REPLACE FUNCTION acq.propagate_funds_by_org_unit(
+	old_year INTEGER,
+	user_id INTEGER,
+	org_unit_id INTEGER
+) RETURNS VOID AS $$
+DECLARE
+--
+new_id      INT;
+old_fund    RECORD;
+org_found   BOOLEAN;
+--
+BEGIN
+	--
+	-- Sanity checks
+	--
+	IF old_year IS NULL THEN
+		RAISE EXCEPTION 'Input year argument is NULL';
+	ELSIF old_year NOT BETWEEN 2008 and 2200 THEN
+		RAISE EXCEPTION 'Input year is out of range';
+	END IF;
+	--
+	IF user_id IS NULL THEN
+		RAISE EXCEPTION 'Input user id argument is NULL';
+	END IF;
+	--
+	IF org_unit_id IS NULL THEN
+		RAISE EXCEPTION 'Org unit id argument is NULL';
+	ELSE
+		SELECT TRUE INTO org_found
+		FROM actor.org_unit
+		WHERE id = org_unit_id;
+		--
+		IF org_found IS NULL THEN
+			RAISE EXCEPTION 'Org unit id is invalid';
+		END IF;
+	END IF;
+	--
+	-- Loop over the applicable funds
+	--
+	FOR old_fund in SELECT * FROM acq.fund
+	WHERE
+		year = old_year
+		AND propagate
+		AND org = org_unit_id
+	LOOP
+		BEGIN
+			INSERT INTO acq.fund (
+				org,
+				name,
+				year,
+				currency_type,
+				code,
+				rollover,
+				propagate,
+				balance_warning_percent,
+				balance_stop_percent
+			) VALUES (
+				old_fund.org,
+				old_fund.name,
+				old_year + 1,
+				old_fund.currency_type,
+				old_fund.code,
+				old_fund.rollover,
+				true,
+				old_fund.balance_warning_percent,
+				old_fund.balance_stop_percent
+			)
+			RETURNING id INTO new_id;
+		EXCEPTION
+			WHEN unique_violation THEN
+				--RAISE NOTICE 'Fund % already propagated', old_fund.id;
+				CONTINUE;
+		END;
+		--RAISE NOTICE 'Propagating fund % to fund %',
+		--	old_fund.code, new_id;
+	END LOOP;
+END;
+$$ LANGUAGE plpgsql;
+
+CREATE OR REPLACE FUNCTION acq.propagate_funds_by_org_tree(
+	old_year INTEGER,
+	user_id INTEGER,
+	org_unit_id INTEGER
+) RETURNS VOID AS $$
+DECLARE
+--
+new_id      INT;
+old_fund    RECORD;
+org_found   BOOLEAN;
+--
+BEGIN
+	--
+	-- Sanity checks
+	--
+	IF old_year IS NULL THEN
+		RAISE EXCEPTION 'Input year argument is NULL';
+	ELSIF old_year NOT BETWEEN 2008 and 2200 THEN
+		RAISE EXCEPTION 'Input year is out of range';
+	END IF;
+	--
+	IF user_id IS NULL THEN
+		RAISE EXCEPTION 'Input user id argument is NULL';
+	END IF;
+	--
+	IF org_unit_id IS NULL THEN
+		RAISE EXCEPTION 'Org unit id argument is NULL';
+	ELSE
+		SELECT TRUE INTO org_found
+		FROM actor.org_unit
+		WHERE id = org_unit_id;
+		--
+		IF org_found IS NULL THEN
+			RAISE EXCEPTION 'Org unit id is invalid';
+		END IF;
+	END IF;
+	--
+	-- Loop over the applicable funds
+	--
+	FOR old_fund in SELECT * FROM acq.fund
+	WHERE
+		year = old_year
+		AND propagate
+		AND org in (
+			SELECT id FROM actor.org_unit_descendants( org_unit_id )
+		)
+	LOOP
+		BEGIN
+			INSERT INTO acq.fund (
+				org,
+				name,
+				year,
+				currency_type,
+				code,
+				rollover,
+				propagate,
+				balance_warning_percent,
+				balance_stop_percent
+			) VALUES (
+				old_fund.org,
+				old_fund.name,
+				old_year + 1,
+				old_fund.currency_type,
+				old_fund.code,
+				old_fund.rollover,
+				true,
+				old_fund.balance_warning_percent,
+				old_fund.balance_stop_percent
+			)
+			RETURNING id INTO new_id;
+		EXCEPTION
+			WHEN unique_violation THEN
+				--RAISE NOTICE 'Fund % already propagated', old_fund.id;
+				CONTINUE;
+		END;
+		--RAISE NOTICE 'Propagating fund % to fund %',
+		--	old_fund.code, new_id;
+	END LOOP;
+END;
+$$ LANGUAGE plpgsql;
+
+CREATE OR REPLACE FUNCTION acq.rollover_funds_by_org_unit(
+	old_year INTEGER,
+	user_id INTEGER,
+	org_unit_id INTEGER
+) RETURNS VOID AS $$
+DECLARE
+--
+new_fund    INT;
+new_year    INT := old_year + 1;
+org_found   BOOL;
+xfer_amount NUMERIC;
+roll_fund   RECORD;
+deb         RECORD;
+detail      RECORD;
+--
+BEGIN
+	--
+	-- Sanity checks
+	--
+	IF old_year IS NULL THEN
+		RAISE EXCEPTION 'Input year argument is NULL';
+    ELSIF old_year NOT BETWEEN 2008 and 2200 THEN
+        RAISE EXCEPTION 'Input year is out of range';
+	END IF;
+	--
+	IF user_id IS NULL THEN
+		RAISE EXCEPTION 'Input user id argument is NULL';
+	END IF;
+	--
+	IF org_unit_id IS NULL THEN
+		RAISE EXCEPTION 'Org unit id argument is NULL';
+	ELSE
+		--
+		-- Validate the org unit
+		--
+		SELECT TRUE
+		INTO org_found
+		FROM actor.org_unit
+		WHERE id = org_unit_id;
+		--
+		IF org_found IS NULL THEN
+			RAISE EXCEPTION 'Org unit id % is invalid', org_unit_id;
+		END IF;
+	END IF;
+	--
+	-- Loop over the propagable funds to identify the details
+	-- from the old fund plus the id of the new one, if it exists.
+	--
+	FOR roll_fund in
+	SELECT
+	    oldf.id AS old_fund,
+	    oldf.org,
+	    oldf.name,
+	    oldf.currency_type,
+	    oldf.code,
+		oldf.rollover,
+	    newf.id AS new_fund_id
+	FROM
+    	acq.fund AS oldf
+    	LEFT JOIN acq.fund AS newf
+        	ON ( oldf.code = newf.code )
+	WHERE
+		    oldf.org = org_unit_id
+ 		and oldf.year = old_year
+		and oldf.propagate
+        and newf.year = new_year
+	LOOP
+		--RAISE NOTICE 'Processing fund %', roll_fund.old_fund;
+		--
+		IF roll_fund.new_fund_id IS NULL THEN
+			--
+			-- The old fund hasn't been propagated yet.  Propagate it now.
+			--
+			INSERT INTO acq.fund (
+				org,
+				name,
+				year,
+				currency_type,
+				code,
+				rollover,
+				propagate,
+				balance_warning_percent,
+				balance_stop_percent
+			) VALUES (
+				roll_fund.org,
+				roll_fund.name,
+				new_year,
+				roll_fund.currency_type,
+				roll_fund.code,
+				true,
+				true,
+				roll_fund.balance_warning_percent,
+				roll_fund.balance_stop_percent
+			)
+			RETURNING id INTO new_fund;
+		ELSE
+			new_fund = roll_fund.new_fund_id;
+		END IF;
+		--
+		-- Determine the amount to transfer
+		--
+		SELECT amount
+		INTO xfer_amount
+		FROM acq.fund_spent_balance
+		WHERE fund = roll_fund.old_fund;
+		--
+		IF xfer_amount <> 0 THEN
+			IF roll_fund.rollover THEN
+				--
+				-- Transfer balance from old fund to new
+				--
+				--RAISE NOTICE 'Transferring % from fund % to %', xfer_amount, roll_fund.old_fund, new_fund;
+				--
+				PERFORM acq.transfer_fund(
+					roll_fund.old_fund,
+					xfer_amount,
+					new_fund,
+					xfer_amount,
+					user_id,
+					'Rollover'
+				);
+			ELSE
+				--
+				-- Transfer balance from old fund to the void
+				--
+				-- RAISE NOTICE 'Transferring % from fund % to the void', xfer_amount, roll_fund.old_fund;
+				--
+				PERFORM acq.transfer_fund(
+					roll_fund.old_fund,
+					xfer_amount,
+					NULL,
+					NULL,
+					user_id,
+					'Rollover'
+				);
+			END IF;
+		END IF;
+		--
+		IF roll_fund.rollover THEN
+			--
+			-- Move any lineitems from the old fund to the new one
+			-- where the associated debit is an encumbrance.
+			--
+			-- Any other tables tying expenditure details to funds should
+			-- receive similar treatment.  At this writing there are none.
+			--
+			UPDATE acq.lineitem_detail
+			SET fund = new_fund
+			WHERE
+    			fund = roll_fund.old_fund -- this condition may be redundant
+    			AND fund_debit in
+    			(
+        			SELECT id
+        			FROM acq.fund_debit
+        			WHERE
+            			fund = roll_fund.old_fund
+            			AND encumbrance
+    			);
+			--
+			-- Move encumbrance debits from the old fund to the new fund
+			--
+			UPDATE acq.fund_debit
+			SET fund = new_fund
+			wHERE
+				fund = roll_fund.old_fund
+				AND encumbrance;
+		END IF;
+		--
+		-- Mark old fund as inactive, now that we've closed it
+		--
+		UPDATE acq.fund
+		SET active = FALSE
+		WHERE id = roll_fund.old_fund;
+	END LOOP;
+END;
+$$ LANGUAGE plpgsql;
+
+CREATE OR REPLACE FUNCTION acq.rollover_funds_by_org_tree(
+	old_year INTEGER,
+	user_id INTEGER,
+	org_unit_id INTEGER
+) RETURNS VOID AS $$
+DECLARE
+--
+new_fund    INT;
+new_year    INT := old_year + 1;
+org_found   BOOL;
+xfer_amount NUMERIC;
+roll_fund   RECORD;
+deb         RECORD;
+detail      RECORD;
+--
+BEGIN
+	--
+	-- Sanity checks
+	--
+	IF old_year IS NULL THEN
+		RAISE EXCEPTION 'Input year argument is NULL';
+    ELSIF old_year NOT BETWEEN 2008 and 2200 THEN
+        RAISE EXCEPTION 'Input year is out of range';
+	END IF;
+	--
+	IF user_id IS NULL THEN
+		RAISE EXCEPTION 'Input user id argument is NULL';
+	END IF;
+	--
+	IF org_unit_id IS NULL THEN
+		RAISE EXCEPTION 'Org unit id argument is NULL';
+	ELSE
+		--
+		-- Validate the org unit
+		--
+		SELECT TRUE
+		INTO org_found
+		FROM actor.org_unit
+		WHERE id = org_unit_id;
+		--
+		IF org_found IS NULL THEN
+			RAISE EXCEPTION 'Org unit id % is invalid', org_unit_id;
+		END IF;
+	END IF;
+	--
+	-- Loop over the propagable funds to identify the details
+	-- from the old fund plus the id of the new one, if it exists.
+	--
+	FOR roll_fund in
+	SELECT
+	    oldf.id AS old_fund,
+	    oldf.org,
+	    oldf.name,
+	    oldf.currency_type,
+	    oldf.code,
+		oldf.rollover,
+	    newf.id AS new_fund_id
+	FROM
+    	acq.fund AS oldf
+    	LEFT JOIN acq.fund AS newf
+        	ON ( oldf.code = newf.code )
+	WHERE
+ 		    oldf.year = old_year
+		AND oldf.propagate
+        AND newf.year = new_year
+		AND oldf.org in (
+			SELECT id FROM actor.org_unit_descendants( org_unit_id )
+		)
+	LOOP
+		--RAISE NOTICE 'Processing fund %', roll_fund.old_fund;
+		--
+		IF roll_fund.new_fund_id IS NULL THEN
+			--
+			-- The old fund hasn't been propagated yet.  Propagate it now.
+			--
+			INSERT INTO acq.fund (
+				org,
+				name,
+				year,
+				currency_type,
+				code,
+				rollover,
+				propagate,
+				balance_warning_percent,
+				balance_stop_percent
+			) VALUES (
+				roll_fund.org,
+				roll_fund.name,
+				new_year,
+				roll_fund.currency_type,
+				roll_fund.code,
+				true,
+				true,
+				roll_fund.balance_warning_percent,
+				roll_fund.balance_stop_percent
+			)
+			RETURNING id INTO new_fund;
+		ELSE
+			new_fund = roll_fund.new_fund_id;
+		END IF;
+		--
+		-- Determine the amount to transfer
+		--
+		SELECT amount
+		INTO xfer_amount
+		FROM acq.fund_spent_balance
+		WHERE fund = roll_fund.old_fund;
+		--
+		IF xfer_amount <> 0 THEN
+			IF roll_fund.rollover THEN
+				--
+				-- Transfer balance from old fund to new
+				--
+				--RAISE NOTICE 'Transferring % from fund % to %', xfer_amount, roll_fund.old_fund, new_fund;
+				--
+				PERFORM acq.transfer_fund(
+					roll_fund.old_fund,
+					xfer_amount,
+					new_fund,
+					xfer_amount,
+					user_id,
+					'Rollover'
+				);
+			ELSE
+				--
+				-- Transfer balance from old fund to the void
+				--
+				-- RAISE NOTICE 'Transferring % from fund % to the void', xfer_amount, roll_fund.old_fund;
+				--
+				PERFORM acq.transfer_fund(
+					roll_fund.old_fund,
+					xfer_amount,
+					NULL,
+					NULL,
+					user_id,
+					'Rollover'
+				);
+			END IF;
+		END IF;
+		--
+		IF roll_fund.rollover THEN
+			--
+			-- Move any lineitems from the old fund to the new one
+			-- where the associated debit is an encumbrance.
+			--
+			-- Any other tables tying expenditure details to funds should
+			-- receive similar treatment.  At this writing there are none.
+			--
+			UPDATE acq.lineitem_detail
+			SET fund = new_fund
+			WHERE
+    			fund = roll_fund.old_fund -- this condition may be redundant
+    			AND fund_debit in
+    			(
+        			SELECT id
+        			FROM acq.fund_debit
+        			WHERE
+            			fund = roll_fund.old_fund
+            			AND encumbrance
+    			);
+			--
+			-- Move encumbrance debits from the old fund to the new fund
+			--
+			UPDATE acq.fund_debit
+			SET fund = new_fund
+			wHERE
+				fund = roll_fund.old_fund
+				AND encumbrance;
+		END IF;
+		--
+		-- Mark old fund as inactive, now that we've closed it
+		--
+		UPDATE acq.fund
+		SET active = FALSE
+		WHERE id = roll_fund.old_fund;
+	END LOOP;
+END;
+$$ LANGUAGE plpgsql;
+
+CREATE OR REPLACE FUNCTION public.remove_commas( TEXT ) RETURNS TEXT AS $$
+    SELECT regexp_replace($1, ',', '', 'g');
+$$ LANGUAGE SQL STRICT IMMUTABLE;
+
+CREATE OR REPLACE FUNCTION public.remove_whitespace( TEXT ) RETURNS TEXT AS $$
+    SELECT regexp_replace(normalize_space($1), E'\\s+', '', 'g');
+$$ LANGUAGE SQL STRICT IMMUTABLE;
+
+CREATE TABLE acq.distribution_formula_application (
+    id BIGSERIAL PRIMARY KEY,
+    creator INT NOT NULL REFERENCES actor.usr(id) DEFERRABLE INITIALLY DEFERRED,
+    create_time TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
+    formula INT NOT NULL
+        REFERENCES acq.distribution_formula(id) DEFERRABLE INITIALLY DEFERRED,
+    lineitem INT NOT NULL
+        REFERENCES acq.lineitem( id )
+		ON DELETE CASCADE
+		DEFERRABLE INITIALLY DEFERRED
+);
+
+CREATE INDEX acqdfa_df_idx
+    ON acq.distribution_formula_application(formula);
+CREATE INDEX acqdfa_li_idx
+    ON acq.distribution_formula_application(lineitem);
+CREATE INDEX acqdfa_creator_idx
+    ON acq.distribution_formula_application(creator);
+
+CREATE TABLE acq.user_request_type (
+    id      SERIAL  PRIMARY KEY,
+    label   TEXT    NOT NULL UNIQUE -- i18n-ize
+);
+
+INSERT INTO acq.user_request_type (id,label) VALUES (1, oils_i18n_gettext('1', 'Books', 'aurt', 'label'));
+INSERT INTO acq.user_request_type (id,label) VALUES (2, oils_i18n_gettext('2', 'Journal/Magazine & Newspaper Articles', 'aurt', 'label'));
+INSERT INTO acq.user_request_type (id,label) VALUES (3, oils_i18n_gettext('3', 'Audiobooks', 'aurt', 'label'));
+INSERT INTO acq.user_request_type (id,label) VALUES (4, oils_i18n_gettext('4', 'Music', 'aurt', 'label'));
+INSERT INTO acq.user_request_type (id,label) VALUES (5, oils_i18n_gettext('5', 'DVDs', 'aurt', 'label'));
+
+SELECT SETVAL('acq.user_request_type_id_seq'::TEXT, 6);
+
+CREATE TABLE acq.cancel_reason (
+	id            SERIAL            PRIMARY KEY,
+	org_unit      INTEGER           NOT NULL REFERENCES actor.org_unit( id )
+	                                DEFERRABLE INITIALLY DEFERRED,
+	label         TEXT              NOT NULL,
+	description   TEXT              NOT NULL,
+	keep_debits   BOOL              NOT NULL DEFAULT FALSE,
+	CONSTRAINT acq_cancel_reason_one_per_org_unit UNIQUE( org_unit, label )
+);
+
+-- Reserve ids 1-999 for stock reasons
+-- Reserve ids 1000-1999 for EDI reasons
+-- 2000+ are available for staff to create
+
+SELECT SETVAL('acq.cancel_reason_id_seq'::TEXT, 2000);
+
+CREATE TABLE acq.user_request (
+    id                  SERIAL  PRIMARY KEY,
+    usr                 INT     NOT NULL REFERENCES actor.usr (id), -- requesting user
+    hold                BOOL    NOT NULL DEFAULT TRUE,
+
+    pickup_lib          INT     NOT NULL REFERENCES actor.org_unit (id), -- pickup lib
+    holdable_formats    TEXT,           -- nullable, for use in hold creation
+    phone_notify        TEXT,
+    email_notify        BOOL    NOT NULL DEFAULT TRUE,
+    lineitem            INT     REFERENCES acq.lineitem (id) ON DELETE CASCADE,
+    eg_bib              BIGINT  REFERENCES biblio.record_entry (id) ON DELETE CASCADE,
+    request_date        TIMESTAMPTZ NOT NULL DEFAULT NOW(), -- when they requested it
+    need_before         TIMESTAMPTZ,    -- don't create holds after this
+    max_fee             TEXT,
+
+    request_type        INT     NOT NULL REFERENCES acq.user_request_type (id), 
+    isxn                TEXT,
+    title               TEXT,
+    volume              TEXT,
+    author              TEXT,
+    article_title       TEXT,
+    article_pages       TEXT,
+    publisher           TEXT,
+    location            TEXT,
+    pubdate             TEXT,
+    mentioned           TEXT,
+    other_info          TEXT,
+	cancel_reason       INT              REFERENCES acq.cancel_reason( id )
+	                                     DEFERRABLE INITIALLY DEFERRED
+);
+
+CREATE TABLE acq.lineitem_alert_text (
+	id               SERIAL         PRIMARY KEY,
+	code             TEXT           UNIQUE NOT NULL,
+	description      TEXT,
+	owning_lib       INT            NOT NULL
+	                                REFERENCES actor.org_unit(id)
+	                                DEFERRABLE INITIALLY DEFERRED,
+	CONSTRAINT alert_one_code_per_org UNIQUE (code, owning_lib)
+);
+
+ALTER TABLE acq.lineitem_note
+	ADD COLUMN alert_text    INT     REFERENCES acq.lineitem_alert_text(id)
+	                                 DEFERRABLE INITIALLY DEFERRED;
+
+-- add ON DELETE CASCADE clause
+
+ALTER TABLE acq.lineitem_note
+	DROP CONSTRAINT lineitem_note_lineitem_fkey;
+
+ALTER TABLE acq.lineitem_note
+	ADD FOREIGN KEY (lineitem) REFERENCES acq.lineitem( id )
+		ON DELETE CASCADE
+		DEFERRABLE INITIALLY DEFERRED;
+
+ALTER TABLE acq.lineitem_note
+	ADD COLUMN vendor_public BOOLEAN NOT NULL DEFAULT FALSE;
+
+CREATE TABLE acq.invoice_method (
+    code    TEXT    PRIMARY KEY,
+    name    TEXT    NOT NULL -- i18n-ize
+);
+INSERT INTO acq.invoice_method (code,name) VALUES ('EDI',oils_i18n_gettext('EDI', 'EDI', 'acqim', 'name'));
+INSERT INTO acq.invoice_method (code,name) VALUES ('PPR',oils_i18n_gettext('PPR', 'Paper', 'acqit', 'name'));
+
+CREATE TABLE acq.invoice_payment_method (
+	code      TEXT     PRIMARY KEY,
+	name      TEXT     NOT NULL
+);
+
+CREATE TABLE acq.invoice (
+    id             SERIAL      PRIMARY KEY,
+    receiver       INT         NOT NULL REFERENCES actor.org_unit (id),
+    provider       INT         NOT NULL REFERENCES acq.provider (id),
+    shipper        INT         NOT NULL REFERENCES acq.provider (id),
+    recv_date      TIMESTAMPTZ NOT NULL DEFAULT NOW(),
+    recv_method    TEXT        NOT NULL REFERENCES acq.invoice_method (code) DEFAULT 'EDI',
+    inv_type       TEXT,       -- A "type" field is desired, but no idea what goes here
+    inv_ident      TEXT        NOT NULL, -- vendor-supplied invoice id/number
+	payment_auth   TEXT,
+	payment_method TEXT        REFERENCES acq.invoice_payment_method (code)
+	                           DEFERRABLE INITIALLY DEFERRED,
+	note           TEXT,
+    complete       BOOL        NOT NULL DEFAULT FALSE,
+    CONSTRAINT inv_ident_once_per_provider UNIQUE(provider, inv_ident)
+);
+
+CREATE TABLE acq.invoice_entry (
+    id              SERIAL      PRIMARY KEY,
+    invoice         INT         NOT NULL REFERENCES acq.invoice (id) ON DELETE CASCADE,
+    purchase_order  INT         REFERENCES acq.purchase_order (id) ON UPDATE CASCADE ON DELETE SET NULL,
+    lineitem        INT         REFERENCES acq.lineitem (id) ON UPDATE CASCADE ON DELETE SET NULL,
+    inv_item_count  INT         NOT NULL, -- How many acqlids did they say they sent
+    phys_item_count INT, -- and how many did staff count
+    note            TEXT,
+    billed_per_item BOOL,
+    cost_billed     NUMERIC(8,2),
+    actual_cost     NUMERIC(8,2),
+	amount_paid     NUMERIC (8,2)
+);
+
+CREATE TABLE acq.invoice_item_type (
+    code    TEXT    PRIMARY KEY,
+    name    TEXT    NOT NULL, -- i18n-ize
+	prorate BOOL    NOT NULL DEFAULT FALSE
+);
+
+INSERT INTO acq.invoice_item_type (code,name) VALUES ('TAX',oils_i18n_gettext('TAX', 'Tax', 'aiit', 'name'));
+INSERT INTO acq.invoice_item_type (code,name) VALUES ('PRO',oils_i18n_gettext('PRO', 'Processing Fee', 'aiit', 'name'));
+INSERT INTO acq.invoice_item_type (code,name) VALUES ('SHP',oils_i18n_gettext('SHP', 'Shipping Charge', 'aiit', 'name'));
+INSERT INTO acq.invoice_item_type (code,name) VALUES ('HND',oils_i18n_gettext('HND', 'Handling Charge', 'aiit', 'name'));
+INSERT INTO acq.invoice_item_type (code,name) VALUES ('ITM',oils_i18n_gettext('ITM', 'Non-library Item', 'aiit', 'name'));
+INSERT INTO acq.invoice_item_type (code,name) VALUES ('SUB',oils_i18n_gettext('SUB', 'Serial Subscription', 'aiit', 'name'));
+
+CREATE TABLE acq.po_item (
+	id              SERIAL      PRIMARY KEY,
+	purchase_order  INT         REFERENCES acq.purchase_order (id)
+	                            ON UPDATE CASCADE ON DELETE SET NULL
+	                            DEFERRABLE INITIALLY DEFERRED,
+	fund_debit      INT         REFERENCES acq.fund_debit (id)
+	                            DEFERRABLE INITIALLY DEFERRED,
+	inv_item_type   TEXT        NOT NULL
+	                            REFERENCES acq.invoice_item_type (code)
+	                            DEFERRABLE INITIALLY DEFERRED,
+	title           TEXT,
+	author          TEXT,
+	note            TEXT,
+	estimated_cost  NUMERIC(8,2),
+	fund            INT         REFERENCES acq.fund (id)
+	                            DEFERRABLE INITIALLY DEFERRED,
+	target          BIGINT
+);
+
+CREATE TABLE acq.invoice_item ( -- for invoice-only debits: taxes/fees/non-bib items/etc
+    id              SERIAL      PRIMARY KEY,
+    invoice         INT         NOT NULL REFERENCES acq.invoice (id) ON UPDATE CASCADE ON DELETE CASCADE,
+    purchase_order  INT         REFERENCES acq.purchase_order (id) ON UPDATE CASCADE ON DELETE SET NULL,
+    fund_debit      INT         REFERENCES acq.fund_debit (id),
+    inv_item_type   TEXT        NOT NULL REFERENCES acq.invoice_item_type (code),
+    title           TEXT,
+    author          TEXT,
+    note            TEXT,
+    cost_billed     NUMERIC(8,2),
+    actual_cost     NUMERIC(8,2),
+    fund            INT         REFERENCES acq.fund (id)
+                                DEFERRABLE INITIALLY DEFERRED,
+    amount_paid     NUMERIC (8,2),
+    po_item         INT         REFERENCES acq.po_item (id)
+                                DEFERRABLE INITIALLY DEFERRED,
+    target          BIGINT
+);
+
+CREATE TABLE acq.edi_message (
+    id               SERIAL          PRIMARY KEY,
+    account          INTEGER         REFERENCES acq.edi_account(id)
+                                     DEFERRABLE INITIALLY DEFERRED,
+    remote_file      TEXT,
+    create_time      TIMESTAMPTZ     NOT NULL DEFAULT now(),
+    translate_time   TIMESTAMPTZ,
+    process_time     TIMESTAMPTZ,
+    error_time       TIMESTAMPTZ,
+    status           TEXT            NOT NULL DEFAULT 'new'
+                                     CONSTRAINT status_value CHECK
+                                     ( status IN (
+                                        'new',          -- needs to be translated
+                                        'translated',   -- needs to be processed
+                                        'trans_error',  -- error in translation step
+                                        'processed',    -- needs to have remote_file deleted
+                                        'proc_error',   -- error in processing step
+                                        'delete_error', -- error in deletion
+                                        'retry',        -- need to retry
+                                        'complete'      -- done
+                                     )),
+    edi              TEXT,
+    jedi             TEXT,
+    error            TEXT,
+    purchase_order   INT             REFERENCES acq.purchase_order
+                                     DEFERRABLE INITIALLY DEFERRED,
+    message_type     TEXT            NOT NULL CONSTRAINT valid_message_type
+                                     CHECK ( message_type IN (
+                                        'ORDERS',
+                                        'ORDRSP',
+                                        'INVOIC',
+                                        'OSTENQ',
+                                        'OSTRPT'
+                                     ))
+);
+
+ALTER TABLE actor.org_address ADD COLUMN san TEXT;
+
+ALTER TABLE acq.provider_address
+	ADD COLUMN fax_phone TEXT;
+
+ALTER TABLE acq.provider_contact_address
+	ADD COLUMN fax_phone TEXT;
+
+CREATE TABLE acq.provider_note (
+    id      SERIAL              PRIMARY KEY,
+    provider    INT             NOT NULL REFERENCES acq.provider (id) DEFERRABLE INITIALLY DEFERRED,
+    creator     INT             NOT NULL REFERENCES actor.usr (id) DEFERRABLE INITIALLY DEFERRED,
+    editor      INT             NOT NULL REFERENCES actor.usr (id) DEFERRABLE INITIALLY DEFERRED,
+    create_time TIMESTAMP WITH TIME ZONE    NOT NULL DEFAULT NOW(),
+    edit_time   TIMESTAMP WITH TIME ZONE    NOT NULL DEFAULT NOW(),
+    value       TEXT            NOT NULL
+);
+CREATE INDEX acq_pro_note_pro_idx      ON acq.provider_note ( provider );
+CREATE INDEX acq_pro_note_creator_idx  ON acq.provider_note ( creator );
+CREATE INDEX acq_pro_note_editor_idx   ON acq.provider_note ( editor );
+
+-- For each fund: the total allocation from all sources, in the
+-- currency of the fund (or 0 if there are no allocations)
+
+CREATE VIEW acq.all_fund_allocation_total AS
+SELECT
+    f.id AS fund,
+    COALESCE( SUM( a.amount * acq.exchange_ratio(
+        s.currency_type, f.currency_type))::numeric(100,2), 0 )
+    AS amount
+FROM
+    acq.fund f
+        LEFT JOIN acq.fund_allocation a
+            ON a.fund = f.id
+        LEFT JOIN acq.funding_source s
+            ON a.funding_source = s.id
+GROUP BY
+    f.id;
+
+-- For every fund: the total encumbrances (or 0 if none),
+-- in the currency of the fund.
+
+CREATE VIEW acq.all_fund_encumbrance_total AS
+SELECT
+	f.id AS fund,
+	COALESCE( encumb.amount, 0 ) AS amount
+FROM
+	acq.fund AS f
+		LEFT JOIN (
+			SELECT
+				fund,
+				sum( amount ) AS amount
+			FROM
+				acq.fund_debit
+			WHERE
+				encumbrance
+			GROUP BY fund
+		) AS encumb
+			ON f.id = encumb.fund;
+
+-- For every fund: the total spent (or 0 if none),
+-- in the currency of the fund.
+
+CREATE VIEW acq.all_fund_spent_total AS
+SELECT
+    f.id AS fund,
+    COALESCE( spent.amount, 0 ) AS amount
+FROM
+    acq.fund AS f
+        LEFT JOIN (
+            SELECT
+                fund,
+                sum( amount ) AS amount
+            FROM
+                acq.fund_debit
+            WHERE
+                NOT encumbrance
+            GROUP BY fund
+        ) AS spent
+            ON f.id = spent.fund;
+
+-- For each fund: the amount not yet spent, in the currency
+-- of the fund.  May include encumbrances.
+
+CREATE VIEW acq.all_fund_spent_balance AS
+SELECT
+	c.fund,
+	c.amount - d.amount AS amount
+FROM acq.all_fund_allocation_total c
+    LEFT JOIN acq.all_fund_spent_total d USING (fund);
+
+-- For each fund: the amount neither spent nor encumbered,
+-- in the currency of the fund
+
+CREATE VIEW acq.all_fund_combined_balance AS
+SELECT
+     a.fund,
+     a.amount - COALESCE( c.amount, 0 ) AS amount
+FROM
+     acq.all_fund_allocation_total a
+        LEFT OUTER JOIN (
+            SELECT
+                fund,
+                SUM( amount ) AS amount
+            FROM
+                acq.fund_debit
+            GROUP BY
+                fund
+        ) AS c USING ( fund );
+
+CREATE OR REPLACE FUNCTION actor.usr_merge(
+	src_usr INT,
+	dest_usr INT,
+	del_addrs BOOLEAN,
+	del_cards BOOLEAN,
+	deactivate_cards BOOLEAN
+) RETURNS VOID AS $$
+DECLARE
+	suffix TEXT;
+	bucket_row RECORD;
+	picklist_row RECORD;
+	queue_row RECORD;
+	folder_row RECORD;
+BEGIN
+
+    -- do some initial cleanup 
+    UPDATE actor.usr SET card = NULL WHERE id = src_usr;
+    UPDATE actor.usr SET mailing_address = NULL WHERE id = src_usr;
+    UPDATE actor.usr SET billing_address = NULL WHERE id = src_usr;
+
+    -- actor.*
+    IF del_cards THEN
+        DELETE FROM actor.card where usr = src_usr;
+    ELSE
+        IF deactivate_cards THEN
+            UPDATE actor.card SET active = 'f' WHERE usr = src_usr;
+        END IF;
+        UPDATE actor.card SET usr = dest_usr WHERE usr = src_usr;
+    END IF;
+
+
+    IF del_addrs THEN
+        DELETE FROM actor.usr_address WHERE usr = src_usr;
+    ELSE
+        UPDATE actor.usr_address SET usr = dest_usr WHERE usr = src_usr;
+    END IF;
+
+    UPDATE actor.usr_note SET usr = dest_usr WHERE usr = src_usr;
+    -- dupes are technically OK in actor.usr_standing_penalty, should manually delete them...
+    UPDATE actor.usr_standing_penalty SET usr = dest_usr WHERE usr = src_usr;
+    PERFORM actor.usr_merge_rows('actor.usr_org_unit_opt_in', 'usr', src_usr, dest_usr);
+    PERFORM actor.usr_merge_rows('actor.usr_setting', 'usr', src_usr, dest_usr);
+
+    -- permission.*
+    PERFORM actor.usr_merge_rows('permission.usr_perm_map', 'usr', src_usr, dest_usr);
+    PERFORM actor.usr_merge_rows('permission.usr_object_perm_map', 'usr', src_usr, dest_usr);
+    PERFORM actor.usr_merge_rows('permission.usr_grp_map', 'usr', src_usr, dest_usr);
+    PERFORM actor.usr_merge_rows('permission.usr_work_ou_map', 'usr', src_usr, dest_usr);
+
+
+    -- container.*
+	
+	-- For each *_bucket table: transfer every bucket belonging to src_usr
+	-- into the custody of dest_usr.
+	--
+	-- In order to avoid colliding with an existing bucket owned by
+	-- the destination user, append the source user's id (in parenthesese)
+	-- to the name.  If you still get a collision, add successive
+	-- spaces to the name and keep trying until you succeed.
+	--
+	FOR bucket_row in
+		SELECT id, name
+		FROM   container.biblio_record_entry_bucket
+		WHERE  owner = src_usr
+	LOOP
+		suffix := ' (' || src_usr || ')';
+		LOOP
+			BEGIN
+				UPDATE  container.biblio_record_entry_bucket
+				SET     owner = dest_usr, name = name || suffix
+				WHERE   id = bucket_row.id;
+			EXCEPTION WHEN unique_violation THEN
+				suffix := suffix || ' ';
+				CONTINUE;
+			END;
+			EXIT;
+		END LOOP;
+	END LOOP;
+
+	FOR bucket_row in
+		SELECT id, name
+		FROM   container.call_number_bucket
+		WHERE  owner = src_usr
+	LOOP
+		suffix := ' (' || src_usr || ')';
+		LOOP
+			BEGIN
+				UPDATE  container.call_number_bucket
+				SET     owner = dest_usr, name = name || suffix
+				WHERE   id = bucket_row.id;
+			EXCEPTION WHEN unique_violation THEN
+				suffix := suffix || ' ';
+				CONTINUE;
+			END;
+			EXIT;
+		END LOOP;
+	END LOOP;
+
+	FOR bucket_row in
+		SELECT id, name
+		FROM   container.copy_bucket
+		WHERE  owner = src_usr
+	LOOP
+		suffix := ' (' || src_usr || ')';
+		LOOP
+			BEGIN
+				UPDATE  container.copy_bucket
+				SET     owner = dest_usr, name = name || suffix
+				WHERE   id = bucket_row.id;
+			EXCEPTION WHEN unique_violation THEN
+				suffix := suffix || ' ';
+				CONTINUE;
+			END;
+			EXIT;
+		END LOOP;
+	END LOOP;
+
+	FOR bucket_row in
+		SELECT id, name
+		FROM   container.user_bucket
+		WHERE  owner = src_usr
+	LOOP
+		suffix := ' (' || src_usr || ')';
+		LOOP
+			BEGIN
+				UPDATE  container.user_bucket
+				SET     owner = dest_usr, name = name || suffix
+				WHERE   id = bucket_row.id;
+			EXCEPTION WHEN unique_violation THEN
+				suffix := suffix || ' ';
+				CONTINUE;
+			END;
+			EXIT;
+		END LOOP;
+	END LOOP;
+
+	UPDATE container.user_bucket_item SET target_user = dest_usr WHERE target_user = src_usr;
+
+    -- vandelay.*
+	-- transfer queues the same way we transfer buckets (see above)
+	FOR queue_row in
+		SELECT id, name
+		FROM   vandelay.queue
+		WHERE  owner = src_usr
+	LOOP
+		suffix := ' (' || src_usr || ')';
+		LOOP
+			BEGIN
+				UPDATE  vandelay.queue
+				SET     owner = dest_usr, name = name || suffix
+				WHERE   id = queue_row.id;
+			EXCEPTION WHEN unique_violation THEN
+				suffix := suffix || ' ';
+				CONTINUE;
+			END;
+			EXIT;
+		END LOOP;
+	END LOOP;
+
+    -- money.*
+    PERFORM actor.usr_merge_rows('money.collections_tracker', 'usr', src_usr, dest_usr);
+    PERFORM actor.usr_merge_rows('money.collections_tracker', 'collector', src_usr, dest_usr);
+    UPDATE money.billable_xact SET usr = dest_usr WHERE usr = src_usr;
+    UPDATE money.billing SET voider = dest_usr WHERE voider = src_usr;
+    UPDATE money.bnm_payment SET accepting_usr = dest_usr WHERE accepting_usr = src_usr;
+
+    -- action.*
+    UPDATE action.circulation SET usr = dest_usr WHERE usr = src_usr;
+    UPDATE action.circulation SET circ_staff = dest_usr WHERE circ_staff = src_usr;
+    UPDATE action.circulation SET checkin_staff = dest_usr WHERE checkin_staff = src_usr;
+
+    UPDATE action.hold_request SET usr = dest_usr WHERE usr = src_usr;
+    UPDATE action.hold_request SET fulfillment_staff = dest_usr WHERE fulfillment_staff = src_usr;
+    UPDATE action.hold_request SET requestor = dest_usr WHERE requestor = src_usr;
+    UPDATE action.hold_notification SET notify_staff = dest_usr WHERE notify_staff = src_usr;
+
+    UPDATE action.in_house_use SET staff = dest_usr WHERE staff = src_usr;
+    UPDATE action.non_cataloged_circulation SET staff = dest_usr WHERE staff = src_usr;
+    UPDATE action.non_cataloged_circulation SET patron = dest_usr WHERE patron = src_usr;
+    UPDATE action.non_cat_in_house_use SET staff = dest_usr WHERE staff = src_usr;
+    UPDATE action.survey_response SET usr = dest_usr WHERE usr = src_usr;
+
+    -- acq.*
+    UPDATE acq.fund_allocation SET allocator = dest_usr WHERE allocator = src_usr;
+    UPDATE acq.fund_transfer SET transfer_user = dest_usr WHERE transfer_user = src_usr;
+
+	-- transfer picklists the same way we transfer buckets (see above)
+	FOR picklist_row in
+		SELECT id, name
+		FROM   acq.picklist
+		WHERE  owner = src_usr
+	LOOP
+		suffix := ' (' || src_usr || ')';
+		LOOP
+			BEGIN
+				UPDATE  acq.picklist
+				SET     owner = dest_usr, name = name || suffix
+				WHERE   id = picklist_row.id;
+			EXCEPTION WHEN unique_violation THEN
+				suffix := suffix || ' ';
+				CONTINUE;
+			END;
+			EXIT;
+		END LOOP;
+	END LOOP;
+
+    UPDATE acq.purchase_order SET owner = dest_usr WHERE owner = src_usr;
+    UPDATE acq.po_note SET creator = dest_usr WHERE creator = src_usr;
+    UPDATE acq.po_note SET editor = dest_usr WHERE editor = src_usr;
+	UPDATE acq.provider_note SET creator = dest_usr WHERE creator = src_usr;
+	UPDATE acq.provider_note SET editor = dest_usr WHERE editor = src_usr;
+    UPDATE acq.lineitem_note SET creator = dest_usr WHERE creator = src_usr;
+    UPDATE acq.lineitem_note SET editor = dest_usr WHERE editor = src_usr;
+    UPDATE acq.lineitem_usr_attr_definition SET usr = dest_usr WHERE usr = src_usr;
+
+    -- asset.*
+    UPDATE asset.copy SET creator = dest_usr WHERE creator = src_usr;
+    UPDATE asset.copy SET editor = dest_usr WHERE editor = src_usr;
+    UPDATE asset.copy_note SET creator = dest_usr WHERE creator = src_usr;
+    UPDATE asset.call_number SET creator = dest_usr WHERE creator = src_usr;
+    UPDATE asset.call_number SET editor = dest_usr WHERE editor = src_usr;
+    UPDATE asset.call_number_note SET creator = dest_usr WHERE creator = src_usr;
+
+    -- serial.*
+    UPDATE serial.record_entry SET creator = dest_usr WHERE creator = src_usr;
+    UPDATE serial.record_entry SET editor = dest_usr WHERE editor = src_usr;
+
+    -- reporter.*
+    -- It's not uncommon to define the reporter schema in a replica 
+    -- DB only, so don't assume these tables exist in the write DB.
+    BEGIN
+    	UPDATE reporter.template SET owner = dest_usr WHERE owner = src_usr;
+    EXCEPTION WHEN undefined_table THEN
+        -- do nothing
+    END;
+    BEGIN
+    	UPDATE reporter.report SET owner = dest_usr WHERE owner = src_usr;
+    EXCEPTION WHEN undefined_table THEN
+        -- do nothing
+    END;
+    BEGIN
+    	UPDATE reporter.schedule SET runner = dest_usr WHERE runner = src_usr;
+    EXCEPTION WHEN undefined_table THEN
+        -- do nothing
+    END;
+    BEGIN
+		-- transfer folders the same way we transfer buckets (see above)
+		FOR folder_row in
+			SELECT id, name
+			FROM   reporter.template_folder
+			WHERE  owner = src_usr
+		LOOP
+			suffix := ' (' || src_usr || ')';
+			LOOP
+				BEGIN
+					UPDATE  reporter.template_folder
+					SET     owner = dest_usr, name = name || suffix
+					WHERE   id = folder_row.id;
+				EXCEPTION WHEN unique_violation THEN
+					suffix := suffix || ' ';
+					CONTINUE;
+				END;
+				EXIT;
+			END LOOP;
+		END LOOP;
+    EXCEPTION WHEN undefined_table THEN
+        -- do nothing
+    END;
+    BEGIN
+		-- transfer folders the same way we transfer buckets (see above)
+		FOR folder_row in
+			SELECT id, name
+			FROM   reporter.report_folder
+			WHERE  owner = src_usr
+		LOOP
+			suffix := ' (' || src_usr || ')';
+			LOOP
+				BEGIN
+					UPDATE  reporter.report_folder
+					SET     owner = dest_usr, name = name || suffix
+					WHERE   id = folder_row.id;
+				EXCEPTION WHEN unique_violation THEN
+					suffix := suffix || ' ';
+					CONTINUE;
+				END;
+				EXIT;
+			END LOOP;
+		END LOOP;
+    EXCEPTION WHEN undefined_table THEN
+        -- do nothing
+    END;
+    BEGIN
+		-- transfer folders the same way we transfer buckets (see above)
+		FOR folder_row in
+			SELECT id, name
+			FROM   reporter.output_folder
+			WHERE  owner = src_usr
+		LOOP
+			suffix := ' (' || src_usr || ')';
+			LOOP
+				BEGIN
+					UPDATE  reporter.output_folder
+					SET     owner = dest_usr, name = name || suffix
+					WHERE   id = folder_row.id;
+				EXCEPTION WHEN unique_violation THEN
+					suffix := suffix || ' ';
+					CONTINUE;
+				END;
+				EXIT;
+			END LOOP;
+		END LOOP;
+    EXCEPTION WHEN undefined_table THEN
+        -- do nothing
+    END;
+
+    -- Finally, delete the source user
+    DELETE FROM actor.usr WHERE id = src_usr;
+
+END;
+$$ LANGUAGE plpgsql;
+
+-- The "add" trigger functions should protect against existing NULLed values, just in case
+CREATE OR REPLACE FUNCTION money.materialized_summary_billing_add () RETURNS TRIGGER AS $$
+BEGIN
+    IF NOT NEW.voided THEN
+        UPDATE  money.materialized_billable_xact_summary
+          SET   total_owed = COALESCE(total_owed, 0.0::numeric) + NEW.amount,
+            last_billing_ts = NEW.billing_ts,
+            last_billing_note = NEW.note,
+            last_billing_type = NEW.billing_type,
+            balance_owed = balance_owed + NEW.amount
+          WHERE id = NEW.xact;
+    END IF;
+
+    RETURN NEW;
+END;
+$$ LANGUAGE PLPGSQL;
+
+CREATE OR REPLACE FUNCTION money.materialized_summary_payment_add () RETURNS TRIGGER AS $$
+BEGIN
+    IF NOT NEW.voided THEN
+        UPDATE  money.materialized_billable_xact_summary
+          SET   total_paid = COALESCE(total_paid, 0.0::numeric) + NEW.amount,
+            last_payment_ts = NEW.payment_ts,
+            last_payment_note = NEW.note,
+            last_payment_type = TG_ARGV[0],
+            balance_owed = balance_owed - NEW.amount
+          WHERE id = NEW.xact;
+    END IF;
+
+    RETURN NEW;
+END;
+$$ LANGUAGE PLPGSQL;
+
+-- Refresh the mat view with the corrected underlying view
+TRUNCATE money.materialized_billable_xact_summary;
+INSERT INTO money.materialized_billable_xact_summary SELECT * FROM money.billable_xact_summary;
+
+CREATE OR REPLACE FUNCTION permission.usr_has_perm_at_nd(
+    user_id    IN INTEGER,
+    perm_code  IN TEXT
+)
+RETURNS SETOF INTEGER AS $$
+--
+-- Return a set of all the org units for which a given user has a given
+-- permission, granted directly (not through inheritance from a parent
+-- org unit).
+--
+-- The permissions apply to a minimum depth of the org unit hierarchy,
+-- for the org unit(s) to which the user is assigned.  (They also apply
+-- to the subordinates of those org units, but we don't report the
+-- subordinates here.)
+--
+-- For purposes of this function, the permission.usr_work_ou_map table
+-- defines which users belong to which org units.  I.e. we ignore the
+-- home_ou column of actor.usr.
+--
+-- The result set may contain duplicates, which should be eliminated
+-- by a DISTINCT clause.
+--
+DECLARE
+    b_super       BOOLEAN;
+    n_perm        INTEGER;
+    n_min_depth   INTEGER;
+    n_work_ou     INTEGER;
+    n_curr_ou     INTEGER;
+    n_depth       INTEGER;
+    n_curr_depth  INTEGER;
+BEGIN
+    --
+    -- Check for superuser
+    --
+    SELECT INTO b_super
+        super_user
+    FROM
+        actor.usr
+    WHERE
+        id = user_id;
+    --
+    IF NOT FOUND THEN
+        return;             -- No user?  No permissions.
+    ELSIF b_super THEN
+        --
+        -- Super user has all permissions everywhere
+        --
+        FOR n_work_ou IN
+            SELECT
+                id
+            FROM
+                actor.org_unit
+            WHERE
+                parent_ou IS NULL
+        LOOP
+            RETURN NEXT n_work_ou;
+        END LOOP;
+        RETURN;
+    END IF;
+    --
+    -- Translate the permission name
+    -- to a numeric permission id
+    --
+    SELECT INTO n_perm
+        id
+    FROM
+        permission.perm_list
+    WHERE
+        code = perm_code;
+    --
+    IF NOT FOUND THEN
+        RETURN;               -- No such permission
+    END IF;
+    --
+    -- Find the highest-level org unit (i.e. the minimum depth)
+    -- to which the permission is applied for this user
+    --
+    -- This query is modified from the one in permission.usr_perms().
+    --
+    SELECT INTO n_min_depth
+        min( depth )
+    FROM    (
+        SELECT depth
+          FROM permission.usr_perm_map upm
+         WHERE upm.usr = user_id
+           AND (upm.perm = n_perm OR upm.perm = -1)
+                    UNION
+        SELECT  gpm.depth
+          FROM  permission.grp_perm_map gpm
+          WHERE (gpm.perm = n_perm OR gpm.perm = -1)
+            AND gpm.grp IN (
+               SELECT   (permission.grp_ancestors(
+                    (SELECT profile FROM actor.usr WHERE id = user_id)
+                )).id
+            )
+                    UNION
+        SELECT  p.depth
+          FROM  permission.grp_perm_map p
+          WHERE (p.perm = n_perm OR p.perm = -1)
+            AND p.grp IN (
+                SELECT (permission.grp_ancestors(m.grp)).id
+                FROM   permission.usr_grp_map m
+                WHERE  m.usr = user_id
+            )
+    ) AS x;
+    --
+    IF NOT FOUND THEN
+        RETURN;                -- No such permission for this user
+    END IF;
+    --
+    -- Identify the org units to which the user is assigned.  Note that
+    -- we pay no attention to the home_ou column in actor.usr.
+    --
+    FOR n_work_ou IN
+        SELECT
+            work_ou
+        FROM
+            permission.usr_work_ou_map
+        WHERE
+            usr = user_id
+    LOOP            -- For each org unit to which the user is assigned
+        --
+        -- Determine the level of the org unit by a lookup in actor.org_unit_type.
+        -- We take it on faith that this depth agrees with the actual hierarchy
+        -- defined in actor.org_unit.
+        --
+        SELECT INTO n_depth
+            type.depth
+        FROM
+            actor.org_unit_type type
+                INNER JOIN actor.org_unit ou
+                    ON ( ou.ou_type = type.id )
+        WHERE
+            ou.id = n_work_ou;
+        --
+        IF NOT FOUND THEN
+            CONTINUE;        -- Maybe raise exception?
+        END IF;
+        --
+        -- Compare the depth of the work org unit to the
+        -- minimum depth, and branch accordingly
+        --
+        IF n_depth = n_min_depth THEN
+            --
+            -- The org unit is at the right depth, so return it.
+            --
+            RETURN NEXT n_work_ou;
+        ELSIF n_depth > n_min_depth THEN
+            --
+            -- Traverse the org unit tree toward the root,
+            -- until you reach the minimum depth determined above
+            --
+            n_curr_depth := n_depth;
+            n_curr_ou := n_work_ou;
+            WHILE n_curr_depth > n_min_depth LOOP
+                SELECT INTO n_curr_ou
+                    parent_ou
+                FROM
+                    actor.org_unit
+                WHERE
+                    id = n_curr_ou;
+                --
+                IF FOUND THEN
+                    n_curr_depth := n_curr_depth - 1;
+                ELSE
+                    --
+                    -- This can happen only if the hierarchy defined in
+                    -- actor.org_unit is corrupted, or out of sync with
+                    -- the depths defined in actor.org_unit_type.
+                    -- Maybe we should raise an exception here, instead
+                    -- of silently ignoring the problem.
+                    --
+                    n_curr_ou = NULL;
+                    EXIT;
+                END IF;
+            END LOOP;
+            --
+            IF n_curr_ou IS NOT NULL THEN
+                RETURN NEXT n_curr_ou;
+            END IF;
+        ELSE
+            --
+            -- The permission applies only at a depth greater than the work org unit.
+            -- Use connectby() to find all dependent org units at the specified depth.
+            --
+            FOR n_curr_ou IN
+                SELECT ou::INTEGER
+                FROM connectby(
+                        'actor.org_unit',         -- table name
+                        'id',                     -- key column
+                        'parent_ou',              -- recursive foreign key
+                        n_work_ou::TEXT,          -- id of starting point
+                        (n_min_depth - n_depth)   -- max depth to search, relative
+                    )                             --   to starting point
+                    AS t(
+                        ou text,            -- dependent org unit
+                        parent_ou text,     -- (ignore)
+                        level int           -- depth relative to starting point
+                    )
+                WHERE
+                    level = n_min_depth - n_depth
+            LOOP
+                RETURN NEXT n_curr_ou;
+            END LOOP;
+        END IF;
+        --
+    END LOOP;
+    --
+    RETURN;
+    --
+END;
+$$ LANGUAGE 'plpgsql';
+
+ALTER TABLE acq.purchase_order
+	ADD COLUMN cancel_reason        INT REFERENCES acq.cancel_reason( id )
+	                                    DEFERRABLE INITIALLY DEFERRED;
+
+ALTER TABLE acq.acq_purchase_order_history
+	ADD COLUMN cancel_reason INTEGER;
+
+ALTER TABLE acq.purchase_order
+	ADD COLUMN prepayment_required BOOLEAN NOT NULL DEFAULT FALSE;
+
+ALTER TABLE acq.acq_purchase_order_history
+	ADD COLUMN prepayment_required BOOLEAN NOT NULL DEFAULT FALSE;
+
+ALTER TABLE acq.lineitem
+	ADD COLUMN cancel_reason        INT REFERENCES acq.cancel_reason( id )
+	                                    DEFERRABLE INITIALLY DEFERRED;
+
+ALTER TABLE acq.acq_lineitem_history
+	ADD COLUMN cancel_reason INTEGER;
+
+ALTER TABLE acq.lineitem
+	ADD COLUMN estimated_unit_price NUMERIC;
+
+ALTER TABLE acq.acq_lineitem_history
+	ADD COLUMN estimated_unit_price NUMERIC;
+
+ALTER TABLE acq.lineitem
+	ADD COLUMN claim_policy INT
+		REFERENCES acq.claim_policy
+		DEFERRABLE INITIALLY DEFERRED;
+
+ALTER TABLE acq.acq_lineitem_history
+	ADD COLUMN claim_policy INT
+		REFERENCES acq.claim_policy
+		DEFERRABLE INITIALLY DEFERRED;
+
+ALTER TABLE acq.lineitem_detail
+	ADD COLUMN cancel_reason        INT REFERENCES acq.cancel_reason( id )
+	                                    DEFERRABLE INITIALLY DEFERRED;
+
+ALTER TABLE acq.lineitem_detail
+	DROP CONSTRAINT lineitem_detail_lineitem_fkey;
+
+ALTER TABLE acq.lineitem_detail
+	ADD FOREIGN KEY (lineitem) REFERENCES acq.lineitem( id )
+		ON DELETE CASCADE
+		DEFERRABLE INITIALLY DEFERRED;
+
+ALTER TABLE acq.lineitem_detail DROP CONSTRAINT lineitem_detail_eg_copy_id_fkey;
+
+INSERT INTO acq.cancel_reason ( id, org_unit, label, description ) VALUES (
+	1, 1, 'invalid_isbn', oils_i18n_gettext( 1, 'ISBN is unrecognizable', 'acqcr', 'label' ));
+
+INSERT INTO acq.cancel_reason ( id, org_unit, label, description ) VALUES (
+	2, 1, 'postpone', oils_i18n_gettext( 2, 'Title has been postponed', 'acqcr', 'label' ));
+
+CREATE OR REPLACE FUNCTION vandelay.add_field ( target_xml TEXT, source_xml TEXT, field TEXT ) RETURNS TEXT AS $_$
+
+    use MARC::Record;
+    use MARC::File::XML (BinaryEncoding => 'UTF-8');
+    use strict;
+
+    my $target_xml = shift;
+    my $source_xml = shift;
+    my $field_spec = shift;
+
+    my $target_r = MARC::Record->new_from_xml( $target_xml );
+    my $source_r = MARC::Record->new_from_xml( $source_xml );
+
+    return $target_xml unless ($target_r && $source_r);
+
+    my @field_list = split(',', $field_spec);
+
+    my %fields;
+    for my $f (@field_list) {
+        $f =~ s/^\s*//; $f =~ s/\s*$//;
+        if ($f =~ /^(.{3})(\w*)(?:\[([^]]*)\])?$/) {
+            my $field = $1;
+            $field =~ s/\s+//;
+            my $sf = $2;
+            $sf =~ s/\s+//;
+            my $match = $3;
+            $match =~ s/^\s*//; $match =~ s/\s*$//;
+            $fields{$field} = { sf => [ split('', $sf) ] };
+            if ($match) {
+                my ($msf,$mre) = split('~', $match);
+                if (length($msf) > 0 and length($mre) > 0) {
+                    $msf =~ s/^\s*//; $msf =~ s/\s*$//;
+                    $mre =~ s/^\s*//; $mre =~ s/\s*$//;
+                    $fields{$field}{match} = { sf => $msf, re => qr/$mre/ };
+                }
+            }
+        }
+    }
+
+    for my $f ( keys %fields) {
+        if ( @{$fields{$f}{sf}} ) {
+            for my $from_field ($source_r->field( $f )) {
+                for my $to_field ($target_r->field( $f )) {
+                    if (exists($fields{$f}{match})) {
+                        next unless (grep { $_ =~ $fields{$f}{match}{re} } $to_field->subfield($fields{$f}{match}{sf}));
+                    }
+                    my @new_sf = map { ($_ => $from_field->subfield($_)) } @{$fields{$f}{sf}};
+                    $to_field->add_subfields( @new_sf );
+                }
+            }
+        } else {
+            my @new_fields = map { $_->clone } $source_r->field( $f );
+            $target_r->insert_fields_ordered( @new_fields );
+        }
+    }
+
+    $target_xml = $target_r->as_xml_record;
+    $target_xml =~ s/^<\?.+?\?>$//mo;
+    $target_xml =~ s/\n//sgo;
+    $target_xml =~ s/>\s+</></sgo;
+
+    return $target_xml;
+
+$_$ LANGUAGE PLPERLU;
+
+CREATE OR REPLACE FUNCTION vandelay.strip_field ( xml TEXT, field TEXT ) RETURNS TEXT AS $_$
+
+    use MARC::Record;
+    use MARC::File::XML (BinaryEncoding => 'UTF-8');
+    use strict;
+
+    my $xml = shift;
+    my $r = MARC::Record->new_from_xml( $xml );
+
+    return $xml unless ($r);
+
+    my $field_spec = shift;
+    my @field_list = split(',', $field_spec);
+
+    my %fields;
+    for my $f (@field_list) {
+        $f =~ s/^\s*//; $f =~ s/\s*$//;
+        if ($f =~ /^(.{3})(\w*)(?:\[([^]]*)\])?$/) {
+            my $field = $1;
+            $field =~ s/\s+//;
+            my $sf = $2;
+            $sf =~ s/\s+//;
+            my $match = $3;
+            $match =~ s/^\s*//; $match =~ s/\s*$//;
+            $fields{$field} = { sf => [ split('', $sf) ] };
+            if ($match) {
+                my ($msf,$mre) = split('~', $match);
+                if (length($msf) > 0 and length($mre) > 0) {
+                    $msf =~ s/^\s*//; $msf =~ s/\s*$//;
+                    $mre =~ s/^\s*//; $mre =~ s/\s*$//;
+                    $fields{$field}{match} = { sf => $msf, re => qr/$mre/ };
+                }
+            }
+        }
+    }
+
+    for my $f ( keys %fields) {
+        for my $to_field ($r->field( $f )) {
+            if (exists($fields{$f}{match})) {
+                next unless (grep { $_ =~ $fields{$f}{match}{re} } $to_field->subfield($fields{$f}{match}{sf}));
+            }
+
+            if ( @{$fields{$f}{sf}} ) {
+                $to_field->delete_subfield(code => $fields{$f}{sf});
+            } else {
+                $r->delete_field( $to_field );
+            }
+        }
+    }
+
+    $xml = $r->as_xml_record;
+    $xml =~ s/^<\?.+?\?>$//mo;
+    $xml =~ s/\n//sgo;
+    $xml =~ s/>\s+</></sgo;
+
+    return $xml;
+
+$_$ LANGUAGE PLPERLU;
+
+CREATE OR REPLACE FUNCTION vandelay.replace_field ( target_xml TEXT, source_xml TEXT, field TEXT ) RETURNS TEXT AS $_$
+    SELECT vandelay.add_field( vandelay.strip_field( $1, $3), $2, $3 );
+$_$ LANGUAGE SQL;
+
+CREATE OR REPLACE FUNCTION vandelay.preserve_field ( incumbent_xml TEXT, incoming_xml TEXT, field TEXT ) RETURNS TEXT AS $_$
+    SELECT vandelay.add_field( vandelay.strip_field( $2, $3), $1, $3 );
+$_$ LANGUAGE SQL;
+
+CREATE VIEW action.unfulfilled_hold_max_loop AS
+	SELECT  hold,
+	        max(count) AS max
+	FROM    action.unfulfilled_hold_loops
+	GROUP BY 1;
+
+ALTER TABLE acq.lineitem_attr
+	DROP CONSTRAINT lineitem_attr_lineitem_fkey;
+
+ALTER TABLE acq.lineitem_attr
+	ADD FOREIGN KEY (lineitem) REFERENCES acq.lineitem( id )
+		ON DELETE CASCADE
+		DEFERRABLE INITIALLY DEFERRED;
+
+ALTER TABLE acq.po_note
+	ADD COLUMN vendor_public BOOLEAN NOT NULL DEFAULT FALSE;
+
+CREATE TABLE vandelay.merge_profile (
+    id              BIGSERIAL   PRIMARY KEY,
+    owner           INT         NOT NULL REFERENCES actor.org_unit (id) ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED,
+    name            TEXT        NOT NULL,
+    add_spec        TEXT,
+    replace_spec    TEXT,
+    strip_spec      TEXT,
+    preserve_spec   TEXT,
+    CONSTRAINT vand_merge_prof_owner_name_idx UNIQUE (owner,name),
+    CONSTRAINT add_replace_strip_or_preserve CHECK ((preserve_spec IS NOT NULL OR replace_spec IS NOT NULL) OR (preserve_spec IS NULL AND replace_spec IS NULL))
+);
+
+CREATE OR REPLACE FUNCTION vandelay.match_bib_record ( ) RETURNS TRIGGER AS $func$
+DECLARE
+    attr        RECORD;
+    attr_def    RECORD;
+    eg_rec      RECORD;
+    id_value    TEXT;
+    exact_id    BIGINT;
+BEGIN
+
+    DELETE FROM vandelay.bib_match WHERE queued_record = NEW.id;
+
+    SELECT * INTO attr_def FROM vandelay.bib_attr_definition WHERE xpath = '//*[@tag="901"]/*[@code="c"]' ORDER BY id LIMIT 1;
+
+    IF attr_def IS NOT NULL AND attr_def.id IS NOT NULL THEN
+        id_value := extract_marc_field('vandelay.queued_bib_record', NEW.id, attr_def.xpath, attr_def.remove);
+
+        IF id_value IS NOT NULL AND id_value <> '' AND id_value ~ $r$^\d+$$r$ THEN
+            SELECT id INTO exact_id FROM biblio.record_entry WHERE id = id_value::BIGINT AND NOT deleted;
+            SELECT * INTO attr FROM vandelay.queued_bib_record_attr WHERE record = NEW.id and field = attr_def.id LIMIT 1;
+            IF exact_id IS NOT NULL THEN
+                INSERT INTO vandelay.bib_match (field_type, matched_attr, queued_record, eg_record) VALUES ('id', attr.id, NEW.id, exact_id);
+            END IF;
+        END IF;
+    END IF;
+
+    IF exact_id IS NULL THEN
+        FOR attr IN SELECT a.* FROM vandelay.queued_bib_record_attr a JOIN vandelay.bib_attr_definition d ON (d.id = a.field) WHERE record = NEW.id AND d.ident IS TRUE LOOP
+
+            -- All numbers? check for an id match
+            IF (attr.attr_value ~ $r$^\d+$$r$) THEN
+                FOR eg_rec IN SELECT * FROM biblio.record_entry WHERE id = attr.attr_value::BIGINT AND deleted IS FALSE LOOP
+                    INSERT INTO vandelay.bib_match (field_type, matched_attr, queued_record, eg_record) VALUES ('id', attr.id, NEW.id, eg_rec.id);
+                END LOOP;
+            END IF;
+
+            -- Looks like an ISBN? check for an isbn match
+            IF (attr.attr_value ~* $r$^[0-9x]+$$r$ AND character_length(attr.attr_value) IN (10,13)) THEN
+                FOR eg_rec IN EXECUTE $$SELECT * FROM metabib.full_rec fr WHERE fr.value LIKE LOWER('$$ || attr.attr_value || $$%') AND fr.tag = '020' AND fr.subfield = 'a'$$ LOOP
+                    PERFORM id FROM biblio.record_entry WHERE id = eg_rec.record AND deleted IS FALSE;
+                    IF FOUND THEN
+                        INSERT INTO vandelay.bib_match (field_type, matched_attr, queued_record, eg_record) VALUES ('isbn', attr.id, NEW.id, eg_rec.record);
+                    END IF;
+                END LOOP;
+
+                -- subcheck for isbn-as-tcn
+                FOR eg_rec IN SELECT * FROM biblio.record_entry WHERE tcn_value = 'i' || attr.attr_value AND deleted IS FALSE LOOP
+                    INSERT INTO vandelay.bib_match (field_type, matched_attr, queued_record, eg_record) VALUES ('tcn_value', attr.id, NEW.id, eg_rec.id);
+                END LOOP;
+            END IF;
+
+            -- check for an OCLC tcn_value match
+            IF (attr.attr_value ~ $r$^o\d+$$r$) THEN
+                FOR eg_rec IN SELECT * FROM biblio.record_entry WHERE tcn_value = regexp_replace(attr.attr_value,'^o','ocm') AND deleted IS FALSE LOOP
+                    INSERT INTO vandelay.bib_match (field_type, matched_attr, queued_record, eg_record) VALUES ('tcn_value', attr.id, NEW.id, eg_rec.id);
+                END LOOP;
+            END IF;
+
+            -- check for a direct tcn_value match
+            FOR eg_rec IN SELECT * FROM biblio.record_entry WHERE tcn_value = attr.attr_value AND deleted IS FALSE LOOP
+                INSERT INTO vandelay.bib_match (field_type, matched_attr, queued_record, eg_record) VALUES ('tcn_value', attr.id, NEW.id, eg_rec.id);
+            END LOOP;
+
+            -- check for a direct item barcode match
+            FOR eg_rec IN
+                    SELECT  DISTINCT b.*
+                      FROM  biblio.record_entry b
+                            JOIN asset.call_number cn ON (cn.record = b.id)
+                            JOIN asset.copy cp ON (cp.call_number = cn.id)
+                      WHERE cp.barcode = attr.attr_value AND cp.deleted IS FALSE
+            LOOP
+                INSERT INTO vandelay.bib_match (field_type, matched_attr, queued_record, eg_record) VALUES ('id', attr.id, NEW.id, eg_rec.id);
+            END LOOP;
+
+        END LOOP;
+    END IF;
+
+    RETURN NULL;
+END;
+$func$ LANGUAGE PLPGSQL;
+
+CREATE OR REPLACE FUNCTION vandelay.merge_record_xml ( target_xml TEXT, source_xml TEXT, add_rule TEXT, replace_preserve_rule TEXT, strip_rule TEXT ) RETURNS TEXT AS $_$
+    SELECT vandelay.replace_field( vandelay.add_field( vandelay.strip_field( $1, $5) , $2, $3 ), $2, $4);
+$_$ LANGUAGE SQL;
+
+CREATE TYPE vandelay.compile_profile AS (add_rule TEXT, replace_rule TEXT, preserve_rule TEXT, strip_rule TEXT);
+CREATE OR REPLACE FUNCTION vandelay.compile_profile ( incoming_xml TEXT ) RETURNS vandelay.compile_profile AS $_$
+DECLARE
+    output              vandelay.compile_profile%ROWTYPE;
+    profile             vandelay.merge_profile%ROWTYPE;
+    profile_tmpl        TEXT;
+    profile_tmpl_owner  TEXT;
+    add_rule            TEXT := '';
+    strip_rule          TEXT := '';
+    replace_rule        TEXT := '';
+    preserve_rule       TEXT := '';
+
+BEGIN
+
+    profile_tmpl := (oils_xpath('//*[@tag="905"]/*[@code="t"]/text()',incoming_xml))[1];
+    profile_tmpl_owner := (oils_xpath('//*[@tag="905"]/*[@code="o"]/text()',incoming_xml))[1];
+
+    IF profile_tmpl IS NOT NULL AND profile_tmpl <> '' AND profile_tmpl_owner IS NOT NULL AND profile_tmpl_owner <> '' THEN
+        SELECT  p.* INTO profile
+          FROM  vandelay.merge_profile p
+                JOIN actor.org_unit u ON (u.id = p.owner)
+          WHERE p.name = profile_tmpl
+                AND u.shortname = profile_tmpl_owner;
+
+        IF profile.id IS NOT NULL THEN
+            add_rule := COALESCE(profile.add_spec,'');
+            strip_rule := COALESCE(profile.strip_spec,'');
+            replace_rule := COALESCE(profile.replace_spec,'');
+            preserve_rule := COALESCE(profile.preserve_spec,'');
+        END IF;
+    END IF;
+
+    add_rule := add_rule || ',' || COALESCE(ARRAY_TO_STRING(oils_xpath('//*[@tag="905"]/*[@code="a"]/text()',incoming_xml),''),'');
+    strip_rule := strip_rule || ',' || COALESCE(ARRAY_TO_STRING(oils_xpath('//*[@tag="905"]/*[@code="d"]/text()',incoming_xml),''),'');
+    replace_rule := replace_rule || ',' || COALESCE(ARRAY_TO_STRING(oils_xpath('//*[@tag="905"]/*[@code="r"]/text()',incoming_xml),''),'');
+    preserve_rule := preserve_rule || ',' || COALESCE(ARRAY_TO_STRING(oils_xpath('//*[@tag="905"]/*[@code="p"]/text()',incoming_xml),''),'');
+
+    output.add_rule := BTRIM(add_rule,',');
+    output.replace_rule := BTRIM(replace_rule,',');
+    output.strip_rule := BTRIM(strip_rule,',');
+    output.preserve_rule := BTRIM(preserve_rule,',');
+
+    RETURN output;
+END;
+$_$ LANGUAGE PLPGSQL;
+
+-- Template-based marc munging functions
+CREATE OR REPLACE FUNCTION vandelay.template_overlay_bib_record ( v_marc TEXT, eg_id BIGINT, merge_profile_id INT ) RETURNS BOOL AS $$
+DECLARE
+    merge_profile   vandelay.merge_profile%ROWTYPE;
+    dyn_profile     vandelay.compile_profile%ROWTYPE;
+    editor_string   TEXT;
+    editor_id       INT;
+    source_marc     TEXT;
+    target_marc     TEXT;
+    eg_marc         TEXT;
+    replace_rule    TEXT;
+    match_count     INT;
+BEGIN
+
+    SELECT  b.marc INTO eg_marc
+      FROM  biblio.record_entry b
+      WHERE b.id = eg_id
+      LIMIT 1;
+
+    IF eg_marc IS NULL OR v_marc IS NULL THEN
+        -- RAISE NOTICE 'no marc for template or bib record';
+        RETURN FALSE;
+    END IF;
+
+    dyn_profile := vandelay.compile_profile( v_marc );
+
+    IF merge_profile_id IS NOT NULL THEN
+        SELECT * INTO merge_profile FROM vandelay.merge_profile WHERE id = merge_profile_id;
+        IF FOUND THEN
+            dyn_profile.add_rule := BTRIM( dyn_profile.add_rule || ',' || COALESCE(merge_profile.add_spec,''), ',');
+            dyn_profile.strip_rule := BTRIM( dyn_profile.strip_rule || ',' || COALESCE(merge_profile.strip_spec,''), ',');
+            dyn_profile.replace_rule := BTRIM( dyn_profile.replace_rule || ',' || COALESCE(merge_profile.replace_spec,''), ',');
+            dyn_profile.preserve_rule := BTRIM( dyn_profile.preserve_rule || ',' || COALESCE(merge_profile.preserve_spec,''), ',');
+        END IF;
+    END IF;
+
+    IF dyn_profile.replace_rule <> '' AND dyn_profile.preserve_rule <> '' THEN
+        -- RAISE NOTICE 'both replace [%] and preserve [%] specified', dyn_profile.replace_rule, dyn_profile.preserve_rule;
+        RETURN FALSE;
+    END IF;
+
+    IF dyn_profile.replace_rule <> '' THEN
+        source_marc = v_marc;
+        target_marc = eg_marc;
+        replace_rule = dyn_profile.replace_rule;
+    ELSE
+        source_marc = eg_marc;
+        target_marc = v_marc;
+        replace_rule = dyn_profile.preserve_rule;
+    END IF;
+
+    UPDATE  biblio.record_entry
+      SET   marc = vandelay.merge_record_xml( target_marc, source_marc, dyn_profile.add_rule, replace_rule, dyn_profile.strip_rule )
+      WHERE id = eg_id;
+
+    IF NOT FOUND THEN
+        -- RAISE NOTICE 'update of biblio.record_entry failed';
+        RETURN FALSE;
+    END IF;
+
+    RETURN TRUE;
+
+END;
+$$ LANGUAGE PLPGSQL;
+
+CREATE OR REPLACE FUNCTION vandelay.template_overlay_bib_record ( v_marc TEXT, eg_id BIGINT) RETURNS BOOL AS $$
+    SELECT vandelay.template_overlay_bib_record( $1, $2, NULL);
+$$ LANGUAGE SQL;
+
+CREATE OR REPLACE FUNCTION vandelay.overlay_bib_record ( import_id BIGINT, eg_id BIGINT, merge_profile_id INT ) RETURNS BOOL AS $$
+DECLARE
+    merge_profile   vandelay.merge_profile%ROWTYPE;
+    dyn_profile     vandelay.compile_profile%ROWTYPE;
+    editor_string   TEXT;
+    editor_id       INT;
+    source_marc     TEXT;
+    target_marc     TEXT;
+    eg_marc         TEXT;
+    v_marc          TEXT;
+    replace_rule    TEXT;
+    match_count     INT;
+BEGIN
+
+    SELECT  q.marc INTO v_marc
+      FROM  vandelay.queued_record q
+            JOIN vandelay.bib_match m ON (m.queued_record = q.id AND q.id = import_id)
+      LIMIT 1;
+
+    IF v_marc IS NULL THEN
+        -- RAISE NOTICE 'no marc for vandelay or bib record';
+        RETURN FALSE;
+    END IF;
+
+    IF vandelay.template_overlay_bib_record( v_marc, eg_id, merge_profile_id) THEN
+        UPDATE  vandelay.queued_bib_record
+          SET   imported_as = eg_id,
+                import_time = NOW()
+          WHERE id = import_id;
+
+        editor_string := (oils_xpath('//*[@tag="905"]/*[@code="u"]/text()',v_marc))[1];
+
+        IF editor_string IS NOT NULL AND editor_string <> '' THEN
+            SELECT usr INTO editor_id FROM actor.card WHERE barcode = editor_string;
+
+            IF editor_id IS NULL THEN
+                SELECT id INTO editor_id FROM actor.usr WHERE usrname = editor_string;
+            END IF;
+
+            IF editor_id IS NOT NULL THEN
+                UPDATE biblio.record_entry SET editor = editor_id WHERE id = eg_id;
+            END IF;
+        END IF;
+
+        RETURN TRUE;
+    END IF;
+
+    -- RAISE NOTICE 'update of biblio.record_entry failed';
+
+    RETURN FALSE;
+
+END;
+$$ LANGUAGE PLPGSQL;
+
+CREATE OR REPLACE FUNCTION vandelay.auto_overlay_bib_record ( import_id BIGINT, merge_profile_id INT ) RETURNS BOOL AS $$
+DECLARE
+    eg_id           BIGINT;
+    match_count     INT;
+    match_attr      vandelay.bib_attr_definition%ROWTYPE;
+BEGIN
+
+    PERFORM * FROM vandelay.queued_bib_record WHERE import_time IS NOT NULL AND id = import_id;
+
+    IF FOUND THEN
+        -- RAISE NOTICE 'already imported, cannot auto-overlay'
+        RETURN FALSE;
+    END IF;
+
+    SELECT COUNT(*) INTO match_count FROM vandelay.bib_match WHERE queued_record = import_id;
+
+    IF match_count <> 1 THEN
+        -- RAISE NOTICE 'not an exact match';
+        RETURN FALSE;
+    END IF;
+
+    SELECT  d.* INTO match_attr
+      FROM  vandelay.bib_attr_definition d
+            JOIN vandelay.queued_bib_record_attr a ON (a.field = d.id)
+            JOIN vandelay.bib_match m ON (m.matched_attr = a.id)
+      WHERE m.queued_record = import_id;
+
+    IF NOT (match_attr.xpath ~ '@tag="901"' AND match_attr.xpath ~ '@code="c"') THEN
+        -- RAISE NOTICE 'not a 901c match: %', match_attr.xpath;
+        RETURN FALSE;
+    END IF;
+
+    SELECT  m.eg_record INTO eg_id
+      FROM  vandelay.bib_match m
+      WHERE m.queued_record = import_id
+      LIMIT 1;
+
+    IF eg_id IS NULL THEN
+        RETURN FALSE;
+    END IF;
+
+    RETURN vandelay.overlay_bib_record( import_id, eg_id, merge_profile_id );
+END;
+$$ LANGUAGE PLPGSQL;
+
+CREATE OR REPLACE FUNCTION vandelay.auto_overlay_bib_queue ( queue_id BIGINT, merge_profile_id INT ) RETURNS SETOF BIGINT AS $$
+DECLARE
+    queued_record   vandelay.queued_bib_record%ROWTYPE;
+BEGIN
+
+    FOR queued_record IN SELECT * FROM vandelay.queued_bib_record WHERE queue = queue_id AND import_time IS NULL LOOP
+
+        IF vandelay.auto_overlay_bib_record( queued_record.id, merge_profile_id ) THEN
+            RETURN NEXT queued_record.id;
+        END IF;
+
+    END LOOP;
+
+    RETURN;
+
+END;
+$$ LANGUAGE PLPGSQL;
+
+CREATE OR REPLACE FUNCTION vandelay.auto_overlay_bib_queue ( queue_id BIGINT ) RETURNS SETOF BIGINT AS $$
+    SELECT * FROM vandelay.auto_overlay_bib_queue( $1, NULL );
+$$ LANGUAGE SQL;
+
+CREATE OR REPLACE FUNCTION vandelay.overlay_authority_record ( import_id BIGINT, eg_id BIGINT, merge_profile_id INT ) RETURNS BOOL AS $$
+DECLARE
+    merge_profile   vandelay.merge_profile%ROWTYPE;
+    dyn_profile     vandelay.compile_profile%ROWTYPE;
+    source_marc     TEXT;
+    target_marc     TEXT;
+    eg_marc         TEXT;
+    v_marc          TEXT;
+    replace_rule    TEXT;
+    match_count     INT;
+BEGIN
+
+    SELECT  b.marc INTO eg_marc
+      FROM  authority.record_entry b
+            JOIN vandelay.authority_match m ON (m.eg_record = b.id AND m.queued_record = import_id)
+      LIMIT 1;
+
+    SELECT  q.marc INTO v_marc
+      FROM  vandelay.queued_record q
+            JOIN vandelay.authority_match m ON (m.queued_record = q.id AND q.id = import_id)
+      LIMIT 1;
+
+    IF eg_marc IS NULL OR v_marc IS NULL THEN
+        -- RAISE NOTICE 'no marc for vandelay or authority record';
+        RETURN FALSE;
+    END IF;
+
+    dyn_profile := vandelay.compile_profile( v_marc );
+
+    IF merge_profile_id IS NOT NULL THEN
+        SELECT * INTO merge_profile FROM vandelay.merge_profile WHERE id = merge_profile_id;
+        IF FOUND THEN
+            dyn_profile.add_rule := BTRIM( dyn_profile.add_rule || ',' || COALESCE(merge_profile.add_spec,''), ',');
+            dyn_profile.strip_rule := BTRIM( dyn_profile.strip_rule || ',' || COALESCE(merge_profile.strip_spec,''), ',');
+            dyn_profile.replace_rule := BTRIM( dyn_profile.replace_rule || ',' || COALESCE(merge_profile.replace_spec,''), ',');
+            dyn_profile.preserve_rule := BTRIM( dyn_profile.preserve_rule || ',' || COALESCE(merge_profile.preserve_spec,''), ',');
+        END IF;
+    END IF;
+
+    IF dyn_profile.replace_rule <> '' AND dyn_profile.preserve_rule <> '' THEN
+        -- RAISE NOTICE 'both replace [%] and preserve [%] specified', dyn_profile.replace_rule, dyn_profile.preserve_rule;
+        RETURN FALSE;
+    END IF;
+
+    IF dyn_profile.replace_rule <> '' THEN
+        source_marc = v_marc;
+        target_marc = eg_marc;
+        replace_rule = dyn_profile.replace_rule;
+    ELSE
+        source_marc = eg_marc;
+        target_marc = v_marc;
+        replace_rule = dyn_profile.preserve_rule;
+    END IF;
+
+    UPDATE  authority.record_entry
+      SET   marc = vandelay.merge_record_xml( target_marc, source_marc, dyn_profile.add_rule, replace_rule, dyn_profile.strip_rule )
+      WHERE id = eg_id;
+
+    IF FOUND THEN
+        UPDATE  vandelay.queued_authority_record
+          SET   imported_as = eg_id,
+                import_time = NOW()
+          WHERE id = import_id;
+        RETURN TRUE;
+    END IF;
+
+    -- RAISE NOTICE 'update of authority.record_entry failed';
+
+    RETURN FALSE;
+
+END;
+$$ LANGUAGE PLPGSQL;
+
+CREATE OR REPLACE FUNCTION vandelay.auto_overlay_authority_record ( import_id BIGINT, merge_profile_id INT ) RETURNS BOOL AS $$
+DECLARE
+    eg_id           BIGINT;
+    match_count     INT;
+BEGIN
+    SELECT COUNT(*) INTO match_count FROM vandelay.authority_match WHERE queued_record = import_id;
+
+    IF match_count <> 1 THEN
+        -- RAISE NOTICE 'not an exact match';
+        RETURN FALSE;
+    END IF;
+
+    SELECT  m.eg_record INTO eg_id
+      FROM  vandelay.authority_match m
+      WHERE m.queued_record = import_id
+      LIMIT 1;
+
+    IF eg_id IS NULL THEN
+        RETURN FALSE;
+    END IF;
+
+    RETURN vandelay.overlay_authority_record( import_id, eg_id, merge_profile_id );
+END;
+$$ LANGUAGE PLPGSQL;
+
+CREATE OR REPLACE FUNCTION vandelay.auto_overlay_authority_queue ( queue_id BIGINT, merge_profile_id INT ) RETURNS SETOF BIGINT AS $$
+DECLARE
+    queued_record   vandelay.queued_authority_record%ROWTYPE;
+BEGIN
+
+    FOR queued_record IN SELECT * FROM vandelay.queued_authority_record WHERE queue = queue_id AND import_time IS NULL LOOP
+
+        IF vandelay.auto_overlay_authority_record( queued_record.id, merge_profile_id ) THEN
+            RETURN NEXT queued_record.id;
+        END IF;
+
+    END LOOP;
+
+    RETURN;
+
+END;
+$$ LANGUAGE PLPGSQL;
+
+CREATE OR REPLACE FUNCTION vandelay.auto_overlay_authority_queue ( queue_id BIGINT ) RETURNS SETOF BIGINT AS $$
+    SELECT * FROM vandelay.auto_overlay_authority_queue( $1, NULL );
+$$ LANGUAGE SQL;
+
+CREATE TYPE vandelay.tcn_data AS (tcn TEXT, tcn_source TEXT, used BOOL);
+CREATE OR REPLACE FUNCTION vandelay.find_bib_tcn_data ( xml TEXT ) RETURNS SETOF vandelay.tcn_data AS $_$
+DECLARE
+    eg_tcn          TEXT;
+    eg_tcn_source   TEXT;
+    output          vandelay.tcn_data%ROWTYPE;
+BEGIN
+
+    -- 001/003
+    eg_tcn := BTRIM((oils_xpath('//*[@tag="001"]/text()',xml))[1]);
+    IF eg_tcn IS NOT NULL AND eg_tcn <> '' THEN
+
+        eg_tcn_source := BTRIM((oils_xpath('//*[@tag="003"]/text()',xml))[1]);
+        IF eg_tcn_source IS NULL OR eg_tcn_source = '' THEN
+            eg_tcn_source := 'System Local';
+        END IF;
+
+        PERFORM id FROM biblio.record_entry WHERE tcn_value = eg_tcn  AND NOT deleted;
+
+        IF NOT FOUND THEN
+            output.used := FALSE;
+        ELSE
+            output.used := TRUE;
+        END IF;
+
+        output.tcn := eg_tcn;
+        output.tcn_source := eg_tcn_source;
+        RETURN NEXT output;
+
+    END IF;
+
+    -- 901 ab
+    eg_tcn := BTRIM((oils_xpath('//*[@tag="901"]/*[@code="a"]/text()',xml))[1]);
+    IF eg_tcn IS NOT NULL AND eg_tcn <> '' THEN
+
+        eg_tcn_source := BTRIM((oils_xpath('//*[@tag="901"]/*[@code="b"]/text()',xml))[1]);
+        IF eg_tcn_source IS NULL OR eg_tcn_source = '' THEN
+            eg_tcn_source := 'System Local';
+        END IF;
+
+        PERFORM id FROM biblio.record_entry WHERE tcn_value = eg_tcn  AND NOT deleted;
+
+        IF NOT FOUND THEN
+            output.used := FALSE;
+        ELSE
+            output.used := TRUE;
+        END IF;
+
+        output.tcn := eg_tcn;
+        output.tcn_source := eg_tcn_source;
+        RETURN NEXT output;
+
+    END IF;
+
+    -- 039 ab
+    eg_tcn := BTRIM((oils_xpath('//*[@tag="039"]/*[@code="a"]/text()',xml))[1]);
+    IF eg_tcn IS NOT NULL AND eg_tcn <> '' THEN
+
+        eg_tcn_source := BTRIM((oils_xpath('//*[@tag="039"]/*[@code="b"]/text()',xml))[1]);
+        IF eg_tcn_source IS NULL OR eg_tcn_source = '' THEN
+            eg_tcn_source := 'System Local';
+        END IF;
+
+        PERFORM id FROM biblio.record_entry WHERE tcn_value = eg_tcn  AND NOT deleted;
+
+        IF NOT FOUND THEN
+            output.used := FALSE;
+        ELSE
+            output.used := TRUE;
+        END IF;
+
+        output.tcn := eg_tcn;
+        output.tcn_source := eg_tcn_source;
+        RETURN NEXT output;
+
+    END IF;
+
+    -- 020 a
+    eg_tcn := REGEXP_REPLACE((oils_xpath('//*[@tag="020"]/*[@code="a"]/text()',xml))[1], $re$^(\w+).*?$$re$, $re$\1$re$);
+    IF eg_tcn IS NOT NULL AND eg_tcn <> '' THEN
+
+        eg_tcn_source := 'ISBN';
+
+        PERFORM id FROM biblio.record_entry WHERE tcn_value = eg_tcn  AND NOT deleted;
+
+        IF NOT FOUND THEN
+            output.used := FALSE;
+        ELSE
+            output.used := TRUE;
+        END IF;
+
+        output.tcn := eg_tcn;
+        output.tcn_source := eg_tcn_source;
+        RETURN NEXT output;
+
+    END IF;
+
+    -- 022 a
+    eg_tcn := REGEXP_REPLACE((oils_xpath('//*[@tag="022"]/*[@code="a"]/text()',xml))[1], $re$^(\w+).*?$$re$, $re$\1$re$);
+    IF eg_tcn IS NOT NULL AND eg_tcn <> '' THEN
+
+        eg_tcn_source := 'ISSN';
+
+        PERFORM id FROM biblio.record_entry WHERE tcn_value = eg_tcn  AND NOT deleted;
+
+        IF NOT FOUND THEN
+            output.used := FALSE;
+        ELSE
+            output.used := TRUE;
+        END IF;
+
+        output.tcn := eg_tcn;
+        output.tcn_source := eg_tcn_source;
+        RETURN NEXT output;
+
+    END IF;
+
+    -- 010 a
+    eg_tcn := REGEXP_REPLACE((oils_xpath('//*[@tag="010"]/*[@code="a"]/text()',xml))[1], $re$^(\w+).*?$$re$, $re$\1$re$);
+    IF eg_tcn IS NOT NULL AND eg_tcn <> '' THEN
+
+        eg_tcn_source := 'LCCN';
+
+        PERFORM id FROM biblio.record_entry WHERE tcn_value = eg_tcn  AND NOT deleted;
+
+        IF NOT FOUND THEN
+            output.used := FALSE;
+        ELSE
+            output.used := TRUE;
+        END IF;
+
+        output.tcn := eg_tcn;
+        output.tcn_source := eg_tcn_source;
+        RETURN NEXT output;
+
+    END IF;
+
+    -- 035 a
+    eg_tcn := REGEXP_REPLACE((oils_xpath('//*[@tag="035"]/*[@code="a"]/text()',xml))[1], $re$^.*?(\w+)$$re$, $re$\1$re$);
+    IF eg_tcn IS NOT NULL AND eg_tcn <> '' THEN
+
+        eg_tcn_source := 'System Legacy';
+
+        PERFORM id FROM biblio.record_entry WHERE tcn_value = eg_tcn  AND NOT deleted;
+
+        IF NOT FOUND THEN
+            output.used := FALSE;
+        ELSE
+            output.used := TRUE;
+        END IF;
+
+        output.tcn := eg_tcn;
+        output.tcn_source := eg_tcn_source;
+        RETURN NEXT output;
+
+    END IF;
+
+    RETURN;
+END;
+$_$ LANGUAGE PLPGSQL;
+
+CREATE INDEX claim_lid_idx ON acq.claim( lineitem_detail );
+
+CREATE OR REPLACE RULE protect_bib_rec_delete AS ON DELETE TO biblio.record_entry DO INSTEAD (UPDATE biblio.record_entry SET deleted = TRUE WHERE OLD.id = biblio.record_entry.id; DELETE FROM metabib.metarecord_source_map WHERE source = OLD.id);
+
+UPDATE biblio.record_entry SET marc = '<record xmlns="http://www.loc.gov/MARC21/slim"/>' WHERE id = -1;
+
+CREATE INDEX metabib_title_field_entry_value_idx ON metabib.title_field_entry (SUBSTRING(value,1,1024)) WHERE index_vector = ''::TSVECTOR;
+CREATE INDEX metabib_author_field_entry_value_idx ON metabib.author_field_entry (SUBSTRING(value,1,1024)) WHERE index_vector = ''::TSVECTOR;
+CREATE INDEX metabib_subject_field_entry_value_idx ON metabib.subject_field_entry (SUBSTRING(value,1,1024)) WHERE index_vector = ''::TSVECTOR;
+CREATE INDEX metabib_keyword_field_entry_value_idx ON metabib.keyword_field_entry (SUBSTRING(value,1,1024)) WHERE index_vector = ''::TSVECTOR;
+CREATE INDEX metabib_series_field_entry_value_idx ON metabib.series_field_entry (SUBSTRING(value,1,1024)) WHERE index_vector = ''::TSVECTOR;
+
+CREATE INDEX metabib_author_field_entry_source_idx ON metabib.author_field_entry (source);
+CREATE INDEX metabib_keyword_field_entry_source_idx ON metabib.keyword_field_entry (source);
+CREATE INDEX metabib_title_field_entry_source_idx ON metabib.title_field_entry (source);
+CREATE INDEX metabib_series_field_entry_source_idx ON metabib.series_field_entry (source);
+
+ALTER TABLE metabib.series_field_entry
+	ADD CONSTRAINT metabib_series_field_entry_source_pkey FOREIGN KEY (source)
+		REFERENCES biblio.record_entry (id)
+		ON DELETE CASCADE
+		DEFERRABLE INITIALLY DEFERRED;
+
+ALTER TABLE metabib.series_field_entry
+	ADD CONSTRAINT metabib_series_field_entry_field_pkey FOREIGN KEY (field)
+		REFERENCES config.metabib_field (id)
+		ON DELETE CASCADE
+		DEFERRABLE INITIALLY DEFERRED;
+
+CREATE TABLE acq.claim_policy_action (
+	id              SERIAL       PRIMARY KEY,
+	claim_policy    INT          NOT NULL REFERENCES acq.claim_policy
+                                 ON DELETE CASCADE
+	                             DEFERRABLE INITIALLY DEFERRED,
+	action_interval INTERVAL     NOT NULL,
+	action          INT          NOT NULL REFERENCES acq.claim_event_type
+	                             DEFERRABLE INITIALLY DEFERRED,
+	CONSTRAINT action_sequence UNIQUE (claim_policy, action_interval)
+);
+
+CREATE OR REPLACE FUNCTION public.ingest_acq_marc ( ) RETURNS TRIGGER AS $function$
+DECLARE
+    value       TEXT;
+    atype       TEXT;
+    prov        INT;
+    pos         INT;
+    adef        RECORD;
+    xpath_string    TEXT;
+BEGIN
+    FOR adef IN SELECT *,tableoid FROM acq.lineitem_attr_definition LOOP
+ 
+        SELECT relname::TEXT INTO atype FROM pg_class WHERE oid = adef.tableoid;
+ 
+        IF (atype NOT IN ('lineitem_usr_attr_definition','lineitem_local_attr_definition')) THEN
+            IF (atype = 'lineitem_provider_attr_definition') THEN
+                SELECT provider INTO prov FROM acq.lineitem_provider_attr_definition WHERE id = adef.id;
+                CONTINUE WHEN NEW.provider IS NULL OR prov <> NEW.provider;
+            END IF;
+ 
+            IF (atype = 'lineitem_provider_attr_definition') THEN
+                SELECT xpath INTO xpath_string FROM acq.lineitem_provider_attr_definition WHERE id = adef.id;
+            ELSIF (atype = 'lineitem_marc_attr_definition') THEN
+                SELECT xpath INTO xpath_string FROM acq.lineitem_marc_attr_definition WHERE id = adef.id;
+            ELSIF (atype = 'lineitem_generated_attr_definition') THEN
+                SELECT xpath INTO xpath_string FROM acq.lineitem_generated_attr_definition WHERE id = adef.id;
+            END IF;
+ 
+            xpath_string := REGEXP_REPLACE(xpath_string,$re$//?text\(\)$$re$,'');
+ 
+            pos := 1;
+ 
+            LOOP
+                SELECT extract_acq_marc_field(id, xpath_string || '[' || pos || ']', adef.remove) INTO value FROM acq.lineitem WHERE id = NEW.id;
+ 
+                IF (value IS NOT NULL AND value <> '') THEN
+                    INSERT INTO acq.lineitem_attr (lineitem, definition, attr_type, attr_name, attr_value)
+                        VALUES (NEW.id, adef.id, atype, adef.code, value);
+                ELSE
+                    EXIT;
+                END IF;
+ 
+                pos := pos + 1;
+            END LOOP;
+ 
+        END IF;
+ 
+    END LOOP;
+ 
+    RETURN NULL;
+END;
+$function$ LANGUAGE PLPGSQL;
+
+UPDATE config.metabib_field SET label = name;
+ALTER TABLE config.metabib_field ALTER COLUMN label SET NOT NULL;
+
+ALTER TABLE config.metabib_field ADD CONSTRAINT field_class_fkey FOREIGN KEY (field_class) REFERENCES config.metabib_class (name);
+
+ALTER TABLE config.metabib_field DROP CONSTRAINT metabib_field_field_class_check;
+
+ALTER TABLE config.metabib_field ADD CONSTRAINT metabib_field_format_fkey FOREIGN KEY (format) REFERENCES config.xml_transform (name);
+
+CREATE TABLE config.metabib_search_alias (
+    alias       TEXT    PRIMARY KEY,
+    field_class TEXT    NOT NULL REFERENCES config.metabib_class (name),
+    field       INT     REFERENCES config.metabib_field (id)
+);
+
+INSERT INTO config.metabib_search_alias (alias,field_class) VALUES ('kw','keyword');
+INSERT INTO config.metabib_search_alias (alias,field_class) VALUES ('eg.keyword','keyword');
+INSERT INTO config.metabib_search_alias (alias,field_class) VALUES ('dc.publisher','keyword');
+INSERT INTO config.metabib_search_alias (alias,field_class) VALUES ('dc.identifier','keyword');
+INSERT INTO config.metabib_search_alias (alias,field_class) VALUES ('bib.subjecttitle','keyword');
+INSERT INTO config.metabib_search_alias (alias,field_class) VALUES ('bib.genre','keyword');
+INSERT INTO config.metabib_search_alias (alias,field_class) VALUES ('bib.edition','keyword');
+INSERT INTO config.metabib_search_alias (alias,field_class) VALUES ('srw.serverchoice','keyword');
+
+INSERT INTO config.metabib_search_alias (alias,field_class) VALUES ('au','author');
+INSERT INTO config.metabib_search_alias (alias,field_class) VALUES ('name','author');
+INSERT INTO config.metabib_search_alias (alias,field_class) VALUES ('creator','author');
+INSERT INTO config.metabib_search_alias (alias,field_class) VALUES ('eg.author','author');
+INSERT INTO config.metabib_search_alias (alias,field_class) VALUES ('eg.name','author');
+INSERT INTO config.metabib_search_alias (alias,field_class) VALUES ('dc.creator','author');
+INSERT INTO config.metabib_search_alias (alias,field_class) VALUES ('dc.contributor','author');
+INSERT INTO config.metabib_search_alias (alias,field_class) VALUES ('bib.name','author');
+INSERT INTO config.metabib_search_alias (alias,field_class,field) VALUES ('bib.namepersonal','author',8);
+INSERT INTO config.metabib_search_alias (alias,field_class,field) VALUES ('bib.namepersonalfamily','author',8);
+INSERT INTO config.metabib_search_alias (alias,field_class,field) VALUES ('bib.namepersonalgiven','author',8);
+INSERT INTO config.metabib_search_alias (alias,field_class,field) VALUES ('bib.namecorporate','author',7);
+INSERT INTO config.metabib_search_alias (alias,field_class,field) VALUES ('bib.nameconference','author',9);
+
+INSERT INTO config.metabib_search_alias (alias,field_class) VALUES ('ti','title');
+INSERT INTO config.metabib_search_alias (alias,field_class) VALUES ('eg.title','title');
+INSERT INTO config.metabib_search_alias (alias,field_class) VALUES ('dc.title','title');
+INSERT INTO config.metabib_search_alias (alias,field_class,field) VALUES ('bib.titleabbreviated','title',2);
+INSERT INTO config.metabib_search_alias (alias,field_class,field) VALUES ('bib.titleuniform','title',5);
+INSERT INTO config.metabib_search_alias (alias,field_class,field) VALUES ('bib.titletranslated','title',3);
+INSERT INTO config.metabib_search_alias (alias,field_class,field) VALUES ('bib.titlealternative','title',4);
+INSERT INTO config.metabib_search_alias (alias,field_class,field) VALUES ('bib.title','title',2);
+
+INSERT INTO config.metabib_search_alias (alias,field_class) VALUES ('su','subject');
+INSERT INTO config.metabib_search_alias (alias,field_class) VALUES ('eg.subject','subject');
+INSERT INTO config.metabib_search_alias (alias,field_class) VALUES ('dc.subject','subject');
+INSERT INTO config.metabib_search_alias (alias,field_class,field) VALUES ('bib.subjectplace','subject',11);
+INSERT INTO config.metabib_search_alias (alias,field_class,field) VALUES ('bib.subjectname','subject',12);
+INSERT INTO config.metabib_search_alias (alias,field_class,field) VALUES ('bib.subjectoccupation','subject',16);
+
+INSERT INTO config.metabib_search_alias (alias,field_class) VALUES ('se','series');
+INSERT INTO config.metabib_search_alias (alias,field_class) VALUES ('eg.series','series');
+INSERT INTO config.metabib_search_alias (alias,field_class,field) VALUES ('bib.titleseries','series',1);
+
+UPDATE config.metabib_field SET facet_field=TRUE WHERE id = 1;
+UPDATE config.metabib_field SET xpath=$$//mods32:mods/mods32:name[@type='corporate' and mods32:role/mods32:roleTerm[text()='creator']]$$, facet_field=TRUE, facet_xpath=$$*[local-name()='namePart']$$ WHERE id = 7;
+UPDATE config.metabib_field SET xpath=$$//mods32:mods/mods32:name[@type='personal' and mods32:role/mods32:roleTerm[text()='creator']]$$, facet_field=TRUE, facet_xpath=$$*[local-name()='namePart']$$ WHERE id = 8;
+UPDATE config.metabib_field SET xpath=$$//mods32:mods/mods32:name[@type='conference' and mods32:role/mods32:roleTerm[text()='creator']]$$, facet_field=TRUE, facet_xpath=$$*[local-name()='namePart']$$ WHERE id = 9;
+UPDATE config.metabib_field SET xpath=$$//mods32:mods/mods32:name[@type='personal' and not(mods32:role)]$$, facet_field=TRUE, facet_xpath=$$*[local-name()='namePart']$$ WHERE id = 10;
+
+UPDATE config.metabib_field SET facet_field=TRUE WHERE id = 11;
+UPDATE config.metabib_field SET facet_field=TRUE , facet_xpath=$$*[local-name()='namePart']$$ WHERE id = 12;
+UPDATE config.metabib_field SET facet_field=TRUE WHERE id = 13;
+UPDATE config.metabib_field SET facet_field=TRUE WHERE id = 14;
+
+CREATE INDEX metabib_rec_descriptor_item_type_idx ON metabib.rec_descriptor (item_type);
+CREATE INDEX metabib_rec_descriptor_item_form_idx ON metabib.rec_descriptor (item_form);
+CREATE INDEX metabib_rec_descriptor_bib_level_idx ON metabib.rec_descriptor (bib_level);
+CREATE INDEX metabib_rec_descriptor_control_type_idx ON metabib.rec_descriptor (control_type);
+CREATE INDEX metabib_rec_descriptor_char_encoding_idx ON metabib.rec_descriptor (char_encoding);
+CREATE INDEX metabib_rec_descriptor_enc_level_idx ON metabib.rec_descriptor (enc_level);
+CREATE INDEX metabib_rec_descriptor_audience_idx ON metabib.rec_descriptor (audience);
+CREATE INDEX metabib_rec_descriptor_lit_form_idx ON metabib.rec_descriptor (lit_form);
+CREATE INDEX metabib_rec_descriptor_cat_form_idx ON metabib.rec_descriptor (cat_form);
+CREATE INDEX metabib_rec_descriptor_pub_status_idx ON metabib.rec_descriptor (pub_status);
+CREATE INDEX metabib_rec_descriptor_item_lang_idx ON metabib.rec_descriptor (item_lang);
+CREATE INDEX metabib_rec_descriptor_vr_format_idx ON metabib.rec_descriptor (vr_format);
+CREATE INDEX metabib_rec_descriptor_date1_idx ON metabib.rec_descriptor (date1);
+CREATE INDEX metabib_rec_descriptor_dates_idx ON metabib.rec_descriptor (date1,date2);
+
+CREATE TABLE asset.opac_visible_copies (
+  id        BIGINT primary key, -- copy id
+  record    BIGINT,
+  circ_lib  INTEGER
+);
+COMMENT ON TABLE asset.opac_visible_copies IS $$
+Materialized view of copies that are visible in the OPAC, used by
+search.query_parser_fts() to speed up OPAC visibility checks on large
+databases.  Contents are maintained by a set of triggers.
+$$;
+CREATE INDEX opac_visible_copies_idx1 on asset.opac_visible_copies (record, circ_lib);
+
+CREATE OR REPLACE FUNCTION search.query_parser_fts (
+
+    param_search_ou INT,
+    param_depth     INT,
+    param_query     TEXT,
+    param_statuses  INT[],
+    param_locations INT[],
+    param_offset    INT,
+    param_check     INT,
+    param_limit     INT,
+    metarecord      BOOL,
+    staff           BOOL
+ 
+) RETURNS SETOF search.search_result AS $func$
+DECLARE
+
+    current_res         search.search_result%ROWTYPE;
+    search_org_list     INT[];
+
+    check_limit         INT;
+    core_limit          INT;
+    core_offset         INT;
+    tmp_int             INT;
+
+    core_result         RECORD;
+    core_cursor         REFCURSOR;
+    core_rel_query      TEXT;
+
+    total_count         INT := 0;
+    check_count         INT := 0;
+    deleted_count       INT := 0;
+    visible_count       INT := 0;
+    excluded_count      INT := 0;
+
+BEGIN
+
+    check_limit := COALESCE( param_check, 1000 );
+    core_limit  := COALESCE( param_limit, 25000 );
+    core_offset := COALESCE( param_offset, 0 );
+
+    -- core_skip_chk := COALESCE( param_skip_chk, 1 );
+
+    IF param_search_ou > 0 THEN
+        IF param_depth IS NOT NULL THEN
+            SELECT array_accum(distinct id) INTO search_org_list FROM actor.org_unit_descendants( param_search_ou, param_depth );
+        ELSE
+            SELECT array_accum(distinct id) INTO search_org_list FROM actor.org_unit_descendants( param_search_ou );
+        END IF;
+    ELSIF param_search_ou < 0 THEN
+        SELECT array_accum(distinct org_unit) INTO search_org_list FROM actor.org_lasso_map WHERE lasso = -param_search_ou;
+    ELSIF param_search_ou = 0 THEN
+        -- reserved for user lassos (ou_buckets/type='lasso') with ID passed in depth ... hack? sure.
+    END IF;
+
+    OPEN core_cursor FOR EXECUTE param_query;
+
+    LOOP
+
+        FETCH core_cursor INTO core_result;
+        EXIT WHEN NOT FOUND;
+        EXIT WHEN total_count >= core_limit;
+
+        total_count := total_count + 1;
+
+        CONTINUE WHEN total_count NOT BETWEEN  core_offset + 1 AND check_limit + core_offset;
+
+        check_count := check_count + 1;
+
+        PERFORM 1 FROM biblio.record_entry b WHERE NOT b.deleted AND b.id IN ( SELECT * FROM search.explode_array( core_result.records ) );
+        IF NOT FOUND THEN
+            -- RAISE NOTICE ' % were all deleted ... ', core_result.records;
+            deleted_count := deleted_count + 1;
+            CONTINUE;
+        END IF;
+
+        PERFORM 1
+          FROM  biblio.record_entry b
+                JOIN config.bib_source s ON (b.source = s.id)
+          WHERE s.transcendant
+                AND b.id IN ( SELECT * FROM search.explode_array( core_result.records ) );
+
+        IF FOUND THEN
+            -- RAISE NOTICE ' % were all transcendant ... ', core_result.records;
+            visible_count := visible_count + 1;
+
+            current_res.id = core_result.id;
+            current_res.rel = core_result.rel;
+
+            tmp_int := 1;
+            IF metarecord THEN
+                SELECT COUNT(DISTINCT s.source) INTO tmp_int FROM metabib.metarecord_source_map s WHERE s.metarecord = core_result.id;
+            END IF;
+
+            IF tmp_int = 1 THEN
+                current_res.record = core_result.records[1];
+            ELSE
+                current_res.record = NULL;
+            END IF;
+
+            RETURN NEXT current_res;
+
+            CONTINUE;
+        END IF;
+
+        PERFORM 1
+          FROM  asset.call_number cn
+                JOIN asset.uri_call_number_map map ON (map.call_number = cn.id)
+                JOIN asset.uri uri ON (map.uri = uri.id)
+          WHERE NOT cn.deleted
+                AND cn.label = '##URI##'
+                AND uri.active
+                AND ( param_locations IS NULL OR array_upper(param_locations, 1) IS NULL )
+                AND cn.record IN ( SELECT * FROM search.explode_array( core_result.records ) )
+                AND cn.owning_lib IN ( SELECT * FROM search.explode_array( search_org_list ) )
+          LIMIT 1;
+
+        IF FOUND THEN
+            -- RAISE NOTICE ' % have at least one URI ... ', core_result.records;
+            visible_count := visible_count + 1;
+
+            current_res.id = core_result.id;
+            current_res.rel = core_result.rel;
+
+            tmp_int := 1;
+            IF metarecord THEN
+                SELECT COUNT(DISTINCT s.source) INTO tmp_int FROM metabib.metarecord_source_map s WHERE s.metarecord = core_result.id;
+            END IF;
+
+            IF tmp_int = 1 THEN
+                current_res.record = core_result.records[1];
+            ELSE
+                current_res.record = NULL;
+            END IF;
+
+            RETURN NEXT current_res;
+
+            CONTINUE;
+        END IF;
+
+        IF param_statuses IS NOT NULL AND array_upper(param_statuses, 1) > 0 THEN
+
+            PERFORM 1
+              FROM  asset.call_number cn
+                    JOIN asset.copy cp ON (cp.call_number = cn.id)
+              WHERE NOT cn.deleted
+                    AND NOT cp.deleted
+                    AND cp.status IN ( SELECT * FROM search.explode_array( param_statuses ) )
+                    AND cn.record IN ( SELECT * FROM search.explode_array( core_result.records ) )
+                    AND cp.circ_lib IN ( SELECT * FROM search.explode_array( search_org_list ) )
+              LIMIT 1;
+
+            IF NOT FOUND THEN
+                -- RAISE NOTICE ' % were all status-excluded ... ', core_result.records;
+                excluded_count := excluded_count + 1;
+                CONTINUE;
+            END IF;
+
+        END IF;
+
+        IF param_locations IS NOT NULL AND array_upper(param_locations, 1) > 0 THEN
+
+            PERFORM 1
+              FROM  asset.call_number cn
+                    JOIN asset.copy cp ON (cp.call_number = cn.id)
+              WHERE NOT cn.deleted
+                    AND NOT cp.deleted
+                    AND cp.location IN ( SELECT * FROM search.explode_array( param_locations ) )
+                    AND cn.record IN ( SELECT * FROM search.explode_array( core_result.records ) )
+                    AND cp.circ_lib IN ( SELECT * FROM search.explode_array( search_org_list ) )
+              LIMIT 1;
+
+            IF NOT FOUND THEN
+                -- RAISE NOTICE ' % were all copy_location-excluded ... ', core_result.records;
+                excluded_count := excluded_count + 1;
+                CONTINUE;
+            END IF;
+
+        END IF;
+
+        IF staff IS NULL OR NOT staff THEN
+
+            PERFORM 1
+              FROM  asset.opac_visible_copies
+              WHERE circ_lib IN ( SELECT * FROM search.explode_array( search_org_list ) )
+                    AND record IN ( SELECT * FROM search.explode_array( core_result.records ) )
+              LIMIT 1;
+
+            IF NOT FOUND THEN
+                -- RAISE NOTICE ' % were all visibility-excluded ... ', core_result.records;
+                excluded_count := excluded_count + 1;
+                CONTINUE;
+            END IF;
+
+        ELSE
+
+            PERFORM 1
+              FROM  asset.call_number cn
+                    JOIN asset.copy cp ON (cp.call_number = cn.id)
+                    JOIN actor.org_unit a ON (cp.circ_lib = a.id)
+              WHERE NOT cn.deleted
+                    AND NOT cp.deleted
+                    AND cp.circ_lib IN ( SELECT * FROM search.explode_array( search_org_list ) )
+                    AND cn.record IN ( SELECT * FROM search.explode_array( core_result.records ) )
+              LIMIT 1;
+
+            IF NOT FOUND THEN
+
+                PERFORM 1
+                  FROM  asset.call_number cn
+                  WHERE cn.record IN ( SELECT * FROM search.explode_array( core_result.records ) )
+                  LIMIT 1;
+
+                IF FOUND THEN
+                    -- RAISE NOTICE ' % were all visibility-excluded ... ', core_result.records;
+                    excluded_count := excluded_count + 1;
+                    CONTINUE;
+                END IF;
+
+            END IF;
+
+        END IF;
+
+        visible_count := visible_count + 1;
+
+        current_res.id = core_result.id;
+        current_res.rel = core_result.rel;
+
+        tmp_int := 1;
+        IF metarecord THEN
+            SELECT COUNT(DISTINCT s.source) INTO tmp_int FROM metabib.metarecord_source_map s WHERE s.metarecord = core_result.id;
+        END IF;
+
+        IF tmp_int = 1 THEN
+            current_res.record = core_result.records[1];
+        ELSE
+            current_res.record = NULL;
+        END IF;
+
+        RETURN NEXT current_res;
+
+        IF visible_count % 1000 = 0 THEN
+            -- RAISE NOTICE ' % visible so far ... ', visible_count;
+        END IF;
+
+    END LOOP;
+
+    current_res.id = NULL;
+    current_res.rel = NULL;
+    current_res.record = NULL;
+    current_res.total = total_count;
+    current_res.checked = check_count;
+    current_res.deleted = deleted_count;
+    current_res.visible = visible_count;
+    current_res.excluded = excluded_count;
+
+    CLOSE core_cursor;
+
+    RETURN NEXT current_res;
+
+END;
+$func$ LANGUAGE PLPGSQL;
+
+ALTER TABLE biblio.record_entry ADD COLUMN owner INT REFERENCES actor.org_unit (id);
+ALTER TABLE biblio.record_entry ADD COLUMN share_depth INT;
+
+ALTER TABLE auditor.biblio_record_entry_history ADD COLUMN owner INT;
+ALTER TABLE auditor.biblio_record_entry_history ADD COLUMN share_depth INT;
+
+DROP VIEW auditor.biblio_record_entry_lifecycle;
+
+SELECT auditor.create_auditor_lifecycle( 'biblio', 'record_entry' );
+
+CREATE OR REPLACE FUNCTION public.first_word ( TEXT ) RETURNS TEXT AS $$
+        SELECT COALESCE(SUBSTRING( $1 FROM $_$^\S+$_$), '');
+$$ LANGUAGE SQL STRICT IMMUTABLE;
+
+CREATE OR REPLACE FUNCTION public.normalize_space( TEXT ) RETURNS TEXT AS $$
+    SELECT regexp_replace(regexp_replace(regexp_replace($1, E'\\n', ' ', 'g'), E'(?:^\\s+)|(\\s+$)', '', 'g'), E'\\s+', ' ', 'g');
+$$ LANGUAGE SQL STRICT IMMUTABLE;
+
+CREATE OR REPLACE FUNCTION public.lowercase( TEXT ) RETURNS TEXT AS $$
+    return lc(shift);
+$$ LANGUAGE PLPERLU STRICT IMMUTABLE;
+
+CREATE OR REPLACE FUNCTION public.uppercase( TEXT ) RETURNS TEXT AS $$
+    return uc(shift);
+$$ LANGUAGE PLPERLU STRICT IMMUTABLE;
+
+CREATE OR REPLACE FUNCTION public.remove_diacritics( TEXT ) RETURNS TEXT AS $$
+    use Unicode::Normalize;
+
+    my $x = NFD(shift);
+    $x =~ s/\pM+//go;
+    return $x;
+
+$$ LANGUAGE PLPERLU STRICT IMMUTABLE;
+
+CREATE OR REPLACE FUNCTION public.entityize( TEXT ) RETURNS TEXT AS $$
+    use Unicode::Normalize;
+
+    my $x = NFC(shift);
+    $x =~ s/([\x{0080}-\x{fffd}])/sprintf('&#x%X;',ord($1))/sgoe;
+    return $x;
+
+$$ LANGUAGE PLPERLU STRICT IMMUTABLE;
+
+CREATE OR REPLACE FUNCTION actor.org_unit_ancestor_setting( setting_name TEXT, org_id INT ) RETURNS SETOF actor.org_unit_setting AS $$
+DECLARE
+    setting RECORD;
+    cur_org INT;
+BEGIN
+    cur_org := org_id;
+    LOOP
+        SELECT INTO setting * FROM actor.org_unit_setting WHERE org_unit = cur_org AND name = setting_name;
+        IF FOUND THEN
+            RETURN NEXT setting;
+        END IF;
+        SELECT INTO cur_org parent_ou FROM actor.org_unit WHERE id = cur_org;
+        EXIT WHEN cur_org IS NULL;
+    END LOOP;
+    RETURN;
+END;
+$$ LANGUAGE plpgsql STABLE;
+
+CREATE OR REPLACE FUNCTION acq.extract_holding_attr_table (lineitem int, tag text) RETURNS SETOF acq.flat_lineitem_holding_subfield AS $$
+DECLARE
+    counter INT;
+    lida    acq.flat_lineitem_holding_subfield%ROWTYPE;
+BEGIN
+
+    SELECT  COUNT(*) INTO counter
+      FROM  oils_xpath_table(
+                'id',
+                'marc',
+                'acq.lineitem',
+                '//*[@tag="' || tag || '"]',
+                'id=' || lineitem
+            ) as t(i int,c text);
+
+    FOR i IN 1 .. counter LOOP
+        FOR lida IN
+            SELECT  *
+              FROM  (   SELECT  id,i,t,v
+                          FROM  oils_xpath_table(
+                                    'id',
+                                    'marc',
+                                    'acq.lineitem',
+                                    '//*[@tag="' || tag || '"][position()=' || i || ']/*/@code|' ||
+                                        '//*[@tag="' || tag || '"][position()=' || i || ']/*[@code]',
+                                    'id=' || lineitem
+                                ) as t(id int,t text,v text)
+                    )x
+        LOOP
+            RETURN NEXT lida;
+        END LOOP;
+    END LOOP;
+
+    RETURN;
+END;
+$$ LANGUAGE PLPGSQL;
+
+CREATE OR REPLACE FUNCTION oils_i18n_xlate ( keytable TEXT, keyclass TEXT, keycol TEXT, identcol TEXT, keyvalue TEXT, raw_locale TEXT ) RETURNS TEXT AS $func$
+DECLARE
+    locale      TEXT := REGEXP_REPLACE( REGEXP_REPLACE( raw_locale, E'[;, ].+$', '' ), E'_', '-', 'g' );
+    language    TEXT := REGEXP_REPLACE( locale, E'-.+$', '' );
+    result      config.i18n_core%ROWTYPE;
+    fallback    TEXT;
+    keyfield    TEXT := keyclass || '.' || keycol;
+BEGIN
+
+    -- Try the full locale
+    SELECT  * INTO result
+      FROM  config.i18n_core
+      WHERE fq_field = keyfield
+            AND identity_value = keyvalue
+            AND translation = locale;
+
+    -- Try just the language
+    IF NOT FOUND THEN
+        SELECT  * INTO result
+          FROM  config.i18n_core
+          WHERE fq_field = keyfield
+                AND identity_value = keyvalue
+                AND translation = language;
+    END IF;
+
+    -- Fall back to the string we passed in in the first place
+    IF NOT FOUND THEN
+    EXECUTE
+            'SELECT ' ||
+                keycol ||
+            ' FROM ' || keytable ||
+            ' WHERE ' || identcol || ' = ' || quote_literal(keyvalue)
+                INTO fallback;
+        RETURN fallback;
+    END IF;
+
+    RETURN result.string;
+END;
+$func$ LANGUAGE PLPGSQL STABLE;
+
+SELECT auditor.create_auditor ( 'acq', 'invoice' );
+
+SELECT auditor.create_auditor ( 'acq', 'invoice_item' );
+
+SELECT auditor.create_auditor ( 'acq', 'invoice_entry' );
+
+INSERT INTO acq.cancel_reason ( id, org_unit, label, description, keep_debits ) VALUES (
+    3, 1, 'delivered_but_lost',
+    oils_i18n_gettext( 2, 'Delivered but not received; presumed lost', 'acqcr', 'label' ), TRUE );
+
+CREATE TABLE config.global_flag (
+    label   TEXT    NOT NULL
+) INHERITS (config.internal_flag);
+ALTER TABLE config.global_flag ADD PRIMARY KEY (name);
+
+INSERT INTO config.global_flag (name, label) -- defaults to enabled=FALSE
+    VALUES (
+        'cat.bib.use_id_for_tcn',
+        oils_i18n_gettext(
+            'cat.bib.use_id_for_tcn',
+            'Cat: Use Internal ID for TCN Value',
+            'cgf', 
+            'label'
+        )
+    );
+
+-- resolves performance issue noted by EG Indiana
+
+CREATE INDEX scecm_owning_copy_idx ON asset.stat_cat_entry_copy_map(owning_copy);
+
+INSERT INTO config.metabib_class ( name, label ) VALUES ( 'identifier', oils_i18n_gettext('identifier', 'Identifier', 'cmc', 'name') );
+
+INSERT INTO config.metabib_field ( id, field_class, name, label, format, xpath, facet_field ) VALUES
+    (17, 'identifier', 'accession', oils_i18n_gettext(17, 'Accession Number', 'cmf', 'label'), 'marcxml', $$//marcxml:datafield[tag="001"]/text()$$, TRUE );
+INSERT INTO config.metabib_field ( id, field_class, name, label, format, xpath, facet_field ) VALUES
+    (18, 'identifier', 'isbn', oils_i18n_gettext(18, 'ISBN', 'cmf', 'label'), 'marcxml', $$//marcxml:datafield[tag="020"]/marcxml:subfield[code="a" or code="z"]/text()$$, TRUE );
+INSERT INTO config.metabib_field ( id, field_class, name, label, format, xpath, facet_field ) VALUES
+    (19, 'identifier', 'issn', oils_i18n_gettext(19, 'ISSN', 'cmf', 'label'), 'marcxml', $$//marcxml:datafield[tag="022"]/marcxml:subfield[code="a" or code="z"]/text()$$, TRUE );
+INSERT INTO config.metabib_field ( id, field_class, name, label, format, xpath, facet_field ) VALUES
+    (20, 'identifier', 'upc', oils_i18n_gettext(20, 'UPC', 'cmf', 'label'), 'marcxml', $$//marcxml:datafield[tag="024" and ind1="1"]/marcxml:subfield[code="a" or code="z"]/text()$$, TRUE );
+INSERT INTO config.metabib_field ( id, field_class, name, label, format, xpath, facet_field ) VALUES
+    (21, 'identifier', 'ismn', oils_i18n_gettext(21, 'ISMN', 'cmf', 'label'), 'marcxml', $$//marcxml:datafield[tag="024" and ind1="2"]/marcxml:subfield[code="a" or code="z"]/text()$$, TRUE );
+INSERT INTO config.metabib_field ( id, field_class, name, label, format, xpath, facet_field ) VALUES
+    (22, 'identifier', 'ean', oils_i18n_gettext(22, 'EAN', 'cmf', 'label'), 'marcxml', $$//marcxml:datafield[tag="024" and ind1="3"]/marcxml:subfield[code="a" or code="z"]/text()$$, TRUE );
+INSERT INTO config.metabib_field ( id, field_class, name, label, format, xpath, facet_field ) VALUES
+    (23, 'identifier', 'isrc', oils_i18n_gettext(23, 'ISRC', 'cmf', 'label'), 'marcxml', $$//marcxml:datafield[tag="024" and ind1="0"]/marcxml:subfield[code="a" or code="z"]/text()$$, TRUE );
+INSERT INTO config.metabib_field ( id, field_class, name, label, format, xpath, facet_field ) VALUES
+    (24, 'identifier', 'sici', oils_i18n_gettext(24, 'SICI', 'cmf', 'label'), 'marcxml', $$//marcxml:datafield[tag="024" and ind1="4"]/marcxml:subfield[code="a" or code="z"]/text()$$, TRUE );
+INSERT INTO config.metabib_field ( id, field_class, name, label, format, xpath, facet_field ) VALUES
+    (25, 'identifier', 'bibcn', oils_i18n_gettext(25, 'Local Free-Text Call Number', 'cmf', 'label'), 'marcxml', $$//marcxml:datafield[tag="099"]//text()$$, TRUE );
+
+SELECT SETVAL('config.metabib_field_id_seq'::TEXT, (SELECT MAX(id) FROM config.metabib_field), TRUE);
+ 
+
+DELETE FROM config.metabib_search_alias WHERE alias = 'dc.identifier';
+
+INSERT INTO config.metabib_search_alias (alias,field_class) VALUES ('id','identifier');
+INSERT INTO config.metabib_search_alias (alias,field_class) VALUES ('dc.identifier','identifier');
+INSERT INTO config.metabib_search_alias (alias,field_class,field) VALUES ('eg.isbn','identifier', 18);
+INSERT INTO config.metabib_search_alias (alias,field_class,field) VALUES ('eg.issn','identifier', 19);
+INSERT INTO config.metabib_search_alias (alias,field_class,field) VALUES ('eg.upc','identifier', 20);
+INSERT INTO config.metabib_search_alias (alias,field_class,field) VALUES ('eg.callnumber','identifier', 25);
+
+CREATE TABLE metabib.identifier_field_entry (
+	id		BIGSERIAL	PRIMARY KEY,
+	source		BIGINT		NOT NULL,
+	field		INT		NOT NULL,
+	value		TEXT		NOT NULL,
+	index_vector	tsvector	NOT NULL
+);
+CREATE TRIGGER metabib_identifier_field_entry_fti_trigger
+	BEFORE UPDATE OR INSERT ON metabib.identifier_field_entry
+	FOR EACH ROW EXECUTE PROCEDURE oils_tsearch2('keyword');
+
+CREATE INDEX metabib_identifier_field_entry_index_vector_idx ON metabib.identifier_field_entry USING GIST (index_vector);
+CREATE INDEX metabib_identifier_field_entry_value_idx ON metabib.identifier_field_entry
+    (SUBSTRING(value,1,1024)) WHERE index_vector = ''::TSVECTOR;
+CREATE INDEX metabib_identifier_field_entry_source_idx ON metabib.identifier_field_entry (source);
+
+ALTER TABLE metabib.identifier_field_entry ADD CONSTRAINT metabib_identifier_field_entry_source_pkey
+    FOREIGN KEY (source) REFERENCES biblio.record_entry (id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
+ALTER TABLE metabib.identifier_field_entry ADD CONSTRAINT metabib_identifier_field_entry_field_pkey
+    FOREIGN KEY (field) REFERENCES config.metabib_field (id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
+
+CREATE OR REPLACE FUNCTION public.translate_isbn1013( TEXT ) RETURNS TEXT AS $func$
+    use Business::ISBN;
+    use strict;
+    use warnings;
+
+    # For each ISBN found in a single string containing a set of ISBNs:
+    #   * Normalize an incoming ISBN to have the correct checksum and no hyphens
+    #   * Convert an incoming ISBN10 or ISBN13 to its counterpart and return
+
+    my $input = shift;
+    my $output = '';
+
+    foreach my $word (split(/\s/, $input)) {
+        my $isbn = Business::ISBN->new($word);
+
+        # First check the checksum; if it is not valid, fix it and add the original
+        # bad-checksum ISBN to the output
+        if ($isbn && $isbn->is_valid_checksum() == Business::ISBN::BAD_CHECKSUM) {
+            $output .= $isbn->isbn() . " ";
+            $isbn->fix_checksum();
+        }
+
+        # If we now have a valid ISBN, convert it to its counterpart ISBN10/ISBN13
+        # and add the normalized original ISBN to the output
+        if ($isbn && $isbn->is_valid()) {
+            my $isbn_xlated = ($isbn->type eq "ISBN13") ? $isbn->as_isbn10 : $isbn->as_isbn13;
+            $output .= $isbn->isbn . " ";
+
+            # If we successfully converted the ISBN to its counterpart, add the
+            # converted ISBN to the output as well
+            $output .= ($isbn_xlated->isbn . " ") if ($isbn_xlated);
+        }
+    }
+    return $output if $output;
+
+    # If there were no valid ISBNs, just return the raw input
+    return $input;
+$func$ LANGUAGE PLPERLU;
+
+COMMENT ON FUNCTION public.translate_isbn1013(TEXT) IS $$
+/*
+ * Copyright (C) 2010 Merrimack Valley Library Consortium
+ * Jason Stephenson <jstephenson at mvlc.org>
+ * Copyright (C) 2010 Laurentian University
+ * Dan Scott <dscott at laurentian.ca>
+ *
+ * The translate_isbn1013 function takes an input ISBN and returns the
+ * following in a single space-delimited string if the input ISBN is valid:
+ *   - The normalized input ISBN (hyphens stripped)
+ *   - The normalized input ISBN with a fixed checksum if the checksum was bad
+ *   - The ISBN converted to its ISBN10 or ISBN13 counterpart, if possible
+ */
+$$;
+
+UPDATE config.metabib_field SET facet_field = FALSE WHERE id BETWEEN 17 AND 25;
+UPDATE config.metabib_field SET xpath = REPLACE(xpath,'marcxml','marc') WHERE id BETWEEN 17 AND 25;
+UPDATE config.metabib_field SET xpath = REPLACE(xpath,'tag','@tag') WHERE id BETWEEN 17 AND 25;
+UPDATE config.metabib_field SET xpath = REPLACE(xpath,'code','@code') WHERE id BETWEEN 17 AND 25;
+UPDATE config.metabib_field SET xpath = REPLACE(xpath,'"',E'\'') WHERE id BETWEEN 17 AND 25;
+UPDATE config.metabib_field SET xpath = REPLACE(xpath,'/text()','') WHERE id BETWEEN 17 AND 24;
+
+INSERT INTO config.index_normalizer (name, description, func, param_count) VALUES (
+	'ISBN 10/13 conversion',
+	'Translate ISBN10 to ISBN13, and vice versa, for indexing purposes.',
+	'translate_isbn1013',
+	0
+);
+
+INSERT INTO config.index_normalizer (name, description, func, param_count) VALUES (
+	'Replace',
+	'Replace all occurences of first parameter in the string with the second parameter.',
+	'replace',
+	2
+);
+
+INSERT INTO config.metabib_field_index_norm_map (field,norm,pos)
+    SELECT  m.id, i.id, 1
+      FROM  config.metabib_field m,
+            config.index_normalizer i
+      WHERE i.func IN ('first_word')
+            AND m.id IN (18);
+
+INSERT INTO config.metabib_field_index_norm_map (field,norm,pos)
+    SELECT  m.id, i.id, 2
+      FROM  config.metabib_field m,
+            config.index_normalizer i
+      WHERE i.func IN ('translate_isbn1013')
+            AND m.id IN (18);
+
+INSERT INTO config.metabib_field_index_norm_map (field,norm,params)
+    SELECT  m.id, i.id, $$['-','']$$
+      FROM  config.metabib_field m,
+            config.index_normalizer i
+      WHERE i.func IN ('replace')
+            AND m.id IN (19);
+
+INSERT INTO config.metabib_field_index_norm_map (field,norm,params)
+    SELECT  m.id, i.id, $$[' ','']$$
+      FROM  config.metabib_field m,
+            config.index_normalizer i
+      WHERE i.func IN ('replace')
+            AND m.id IN (19);
+
+DELETE FROM config.metabib_field_index_norm_map WHERE norm IN (1,2) and field > 16;
+
+UPDATE  config.metabib_field_index_norm_map
+  SET   params = REPLACE(params,E'\'','"')
+  WHERE params IS NOT NULL AND params <> '';
+
+DROP TRIGGER IF EXISTS metabib_identifier_field_entry_fti_trigger ON metabib.identifier_field_entry;
+
+CREATE TEXT SEARCH CONFIGURATION identifier ( COPY = title );
+
+ALTER TABLE config.circ_modifier
+	ADD COLUMN avg_wait_time INTERVAL;
+
+--CREATE TABLE actor.usr_password_reset (
+--  id SERIAL PRIMARY KEY,
+--  uuid TEXT NOT NULL, 
+--  usr BIGINT NOT NULL REFERENCES actor.usr(id) DEFERRABLE INITIALLY DEFERRED, 
+--  request_time TIMESTAMP NOT NULL DEFAULT NOW(), 
+--  has_been_reset BOOL NOT NULL DEFAULT false
+--);
+--COMMENT ON TABLE actor.usr_password_reset IS $$
+--/*
+-- * Copyright (C) 2010 Laurentian University
+-- * Dan Scott <dscott at laurentian.ca>
+-- *
+-- * Self-serve password reset requests
+-- *
+-- * ****
+-- *
+-- * This program is free software; you can redistribute it and/or
+-- * modify it under the terms of the GNU General Public License
+-- * as published by the Free Software Foundation; either version 2
+-- * of the License, or (at your option) any later version.
+-- *
+-- * This program is distributed in the hope that it will be useful,
+-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+-- * GNU General Public License for more details.
+-- */
+--$$;
+--CREATE UNIQUE INDEX actor_usr_password_reset_uuid_idx ON actor.usr_password_reset (uuid);
+--CREATE INDEX actor_usr_password_reset_usr_idx ON actor.usr_password_reset (usr);
+--CREATE INDEX actor_usr_password_reset_request_time_idx ON actor.usr_password_reset (request_time);
+--CREATE INDEX actor_usr_password_reset_has_been_reset_idx ON actor.usr_password_reset (has_been_reset);
+
+-- Use the identifier search class tsconfig
+DROP TRIGGER IF EXISTS metabib_identifier_field_entry_fti_trigger ON metabib.identifier_field_entry;
+CREATE TRIGGER metabib_identifier_field_entry_fti_trigger
+    BEFORE INSERT OR UPDATE ON metabib.identifier_field_entry
+    FOR EACH ROW
+    EXECUTE PROCEDURE public.oils_tsearch2('identifier');
+
+INSERT INTO config.global_flag (name,label,enabled)
+    VALUES ('history.circ.retention_age',oils_i18n_gettext('history.circ.retention_age', 'Historical Circulation Retention Age', 'cgf', 'label'), TRUE);
+INSERT INTO config.global_flag (name,label,enabled)
+    VALUES ('history.circ.retention_count',oils_i18n_gettext('history.circ.retention_count', 'Historical Circulations per Copy', 'cgf', 'label'), TRUE);
+
+-- turn a JSON scalar into an SQL TEXT value
+CREATE OR REPLACE FUNCTION oils_json_to_text( TEXT ) RETURNS TEXT AS $f$
+    use JSON::XS;                    
+    my $json = shift();
+    my $txt;
+    eval { $txt = JSON::XS->new->allow_nonref->decode( $json ) };   
+    return undef if ($@);
+    return $txt
+$f$ LANGUAGE PLPERLU;
+
+-- Return the list of circ chain heads in xact_start order that the user has chosen to "retain"
+CREATE OR REPLACE FUNCTION action.usr_visible_circs (usr_id INT) RETURNS SETOF action.circulation AS $func$
+DECLARE
+    c               action.circulation%ROWTYPE;
+    view_age        INTERVAL;
+    usr_view_age    actor.usr_setting%ROWTYPE;
+    usr_view_start  actor.usr_setting%ROWTYPE;
+BEGIN
+    SELECT * INTO usr_view_age FROM actor.usr_setting WHERE usr = usr_id AND name = 'history.circ.retention_age';
+    SELECT * INTO usr_view_start FROM actor.usr_setting WHERE usr = usr_id AND name = 'history.circ.retention_start';
+
+    IF usr_view_age.value IS NOT NULL AND usr_view_start.value IS NOT NULL THEN
+        -- User opted in and supplied a retention age
+        IF oils_json_to_text(usr_view_age.value)::INTERVAL > AGE(NOW(), oils_json_to_text(usr_view_start.value)::TIMESTAMPTZ) THEN
+            view_age := AGE(NOW(), oils_json_to_text(usr_view_start.value)::TIMESTAMPTZ);
+        ELSE
+            view_age := oils_json_to_text(usr_view_age.value)::INTERVAL;
+        END IF;
+    ELSIF usr_view_start.value IS NOT NULL THEN
+        -- User opted in
+        view_age := AGE(NOW(), oils_json_to_text(usr_view_start.value)::TIMESTAMPTZ);
+    ELSE
+        -- User did not opt in
+        RETURN;
+    END IF;
+
+    FOR c IN
+        SELECT  *
+          FROM  action.circulation
+          WHERE usr = usr_id
+                AND parent_circ IS NULL
+                AND xact_start > NOW() - view_age
+          ORDER BY xact_start
+    LOOP
+        RETURN NEXT c;
+    END LOOP;
+
+    RETURN;
+END;
+$func$ LANGUAGE PLPGSQL;
+
+CREATE OR REPLACE FUNCTION action.purge_circulations () RETURNS INT AS $func$
+DECLARE
+    usr_keep_age    actor.usr_setting%ROWTYPE;
+    usr_keep_start  actor.usr_setting%ROWTYPE;
+    org_keep_age    INTERVAL;
+    org_keep_count  INT;
+
+    keep_age        INTERVAL;
+
+    target_acp      RECORD;
+    circ_chain_head action.circulation%ROWTYPE;
+    circ_chain_tail action.circulation%ROWTYPE;
+
+    purge_position  INT;
+    count_purged    INT;
+BEGIN
+
+    count_purged := 0;
+
+    SELECT value::INTERVAL INTO org_keep_age FROM config.global_flag WHERE name = 'history.circ.retention_age' AND enabled;
+
+    SELECT value::INT INTO org_keep_count FROM config.global_flag WHERE name = 'history.circ.retention_count' AND enabled;
+    IF org_keep_count IS NULL THEN
+        RETURN count_purged; -- Gimme a count to keep, or I keep them all, forever
+    END IF;
+
+    -- First, find copies with more than keep_count non-renewal circs
+    FOR target_acp IN
+        SELECT  target_copy,
+                COUNT(*) AS total_real_circs
+          FROM  action.circulation
+          WHERE parent_circ IS NULL
+                AND xact_finish IS NOT NULL
+          GROUP BY target_copy
+          HAVING COUNT(*) > org_keep_count
+    LOOP
+        purge_position := 0;
+        -- And, for those, select circs that are finished and older than keep_age
+        FOR circ_chain_head IN
+            SELECT  *
+              FROM  action.circulation
+              WHERE target_copy = target_acp.target_copy
+                    AND parent_circ IS NULL
+              ORDER BY xact_start
+        LOOP
+
+            -- Stop once we've purged enough circs to hit org_keep_count
+            EXIT WHEN target_acp.total_real_circs - purge_position <= org_keep_count;
+
+            SELECT * INTO circ_chain_tail FROM action.circ_chain(circ_chain_head.id) ORDER BY xact_start DESC LIMIT 1;
+            EXIT WHEN circ_chain_tail.xact_finish IS NULL;
+
+            -- Now get the user setings, if any, to block purging if the user wants to keep more circs
+            usr_keep_age.value := NULL;
+            SELECT * INTO usr_keep_age FROM actor.usr_setting WHERE usr = circ_chain_head.usr AND name = 'history.circ.retention_age';
+
+            usr_keep_start.value := NULL;
+            SELECT * INTO usr_keep_start FROM actor.usr_setting WHERE usr = circ_chain_head.usr AND name = 'history.circ.retention_start_date';
+
+            IF usr_keep_age.value IS NOT NULL AND usr_keep_start.value IS NOT NULL THEN
+                IF oils_json_to_string(usr_keep_age.value)::INTERVAL > AGE(NOW(), oils_json_to_string(usr_keep_start.value)::TIMESTAMPTZ) THEN
+                    keep_age := AGE(NOW(), oils_json_to_string(usr_keep_start.value)::TIMESTAMPTZ);
+                ELSE
+                    keep_age := oils_json_to_string(usr_keep_age.value)::INTERVAL;
+                END IF;
+            ELSIF usr_keep_start.value IS NOT NULL THEN
+                keep_age := AGE(NOW(), oils_json_to_string(usr_keep_start.value)::TIMESTAMPTZ);
+            ELSE
+                keep_age := COALESCE( org_keep_age::INTERVAL, '2000 years'::INTEVAL );
+            END IF;
+
+            EXIT WHEN AGE(NOW(), circ_chain_tail.xact_finish) < keep_age;
+
+            -- We've passed the purging tests, purge the circ chain starting at the end
+            DELETE FROM action.circulation WHERE id = circ_chain_tail.id;
+            WHILE circ_chain_tail.parent_circ IS NOT NULL LOOP
+                SELECT * INTO circ_chain_tail FROM action.circulation WHERE id = circ_chain_tail.parent_circ;
+                DELETE FROM action.circulation WHERE id = circ_chain_tail.id;
+            END LOOP;
+
+            count_purged := count_purged + 1;
+            purge_position := purge_position + 1;
+
+        END LOOP;
+    END LOOP;
+END;
+$func$ LANGUAGE PLPGSQL;
+
+CREATE OR REPLACE FUNCTION action.usr_visible_holds (usr_id INT) RETURNS SETOF action.hold_request AS $func$
+DECLARE
+    h               action.hold_request%ROWTYPE;
+    view_age        INTERVAL;
+    view_count      INT;
+    usr_view_count  actor.usr_setting%ROWTYPE;
+    usr_view_age    actor.usr_setting%ROWTYPE;
+    usr_view_start  actor.usr_setting%ROWTYPE;
+BEGIN
+    SELECT * INTO usr_view_count FROM actor.usr_setting WHERE usr = usr_id AND name = 'history.hold.retention_count';
+    SELECT * INTO usr_view_age FROM actor.usr_setting WHERE usr = usr_id AND name = 'history.hold.retention_age';
+    SELECT * INTO usr_view_start FROM actor.usr_setting WHERE usr = usr_id AND name = 'history.hold.retention_start';
+
+    FOR h IN
+        SELECT  *
+          FROM  action.hold_request
+          WHERE usr = usr_id
+                AND fulfillment_time IS NULL
+                AND cancel_time IS NULL
+          ORDER BY request_time DESC
+    LOOP
+        RETURN NEXT h;
+    END LOOP;
+
+    IF usr_view_start.value IS NULL THEN
+        RETURN;
+    END IF;
+
+    IF usr_view_age.value IS NOT NULL THEN
+        -- User opted in and supplied a retention age
+        IF oils_json_to_string(usr_view_age.value)::INTERVAL > AGE(NOW(), oils_json_to_string(usr_view_start.value)::TIMESTAMPTZ) THEN
+            view_age := AGE(NOW(), oils_json_to_string(usr_view_start.value)::TIMESTAMPTZ);
+        ELSE
+            view_age := oils_json_to_string(usr_view_age.value)::INTERVAL;
+        END IF;
+    ELSE
+        -- User opted in
+        view_age := AGE(NOW(), oils_json_to_string(usr_view_start.value)::TIMESTAMPTZ);
+    END IF;
+
+    IF usr_view_count.value IS NOT NULL THEN
+        view_count := oils_json_to_text(usr_view_count.value)::INT;
+    ELSE
+        view_count := 1000;
+    END IF;
+
+    -- show some fulfilled/canceled holds
+    FOR h IN
+        SELECT  *
+          FROM  action.hold_request
+          WHERE usr = usr_id
+                AND ( fulfillment_time IS NOT NULL OR cancel_time IS NOT NULL )
+                AND request_time > NOW() - view_age
+          ORDER BY request_time DESC
+          LIMIT view_count
+    LOOP
+        RETURN NEXT h;
+    END LOOP;
+
+    RETURN;
+END;
+$func$ LANGUAGE PLPGSQL;
+
+DROP TABLE IF EXISTS serial.bib_summary CASCADE;
+
+DROP TABLE IF EXISTS serial.index_summary CASCADE;
+
+DROP TABLE IF EXISTS serial.sup_summary CASCADE;
+
+DROP TABLE IF EXISTS serial.issuance CASCADE;
+
+DROP TABLE IF EXISTS serial.binding_unit CASCADE;
+
+DROP TABLE IF EXISTS serial.subscription CASCADE;
+
+CREATE TABLE asset.copy_template (
+	id             SERIAL   PRIMARY KEY,
+	owning_lib     INT      NOT NULL
+	                        REFERENCES actor.org_unit (id)
+	                        DEFERRABLE INITIALLY DEFERRED,
+	creator        BIGINT   NOT NULL
+	                        REFERENCES actor.usr (id)
+	                        DEFERRABLE INITIALLY DEFERRED,
+	editor         BIGINT   NOT NULL
+	                        REFERENCES actor.usr (id)
+	                        DEFERRABLE INITIALLY DEFERRED,
+	create_date    TIMESTAMP WITH TIME ZONE    DEFAULT NOW(),
+	edit_date      TIMESTAMP WITH TIME ZONE    DEFAULT NOW(),
+	name           TEXT     NOT NULL,
+	-- columns above this point are attributes of the template itself
+	-- columns after this point are attributes of the copy this template modifies/creates
+	circ_lib       INT      REFERENCES actor.org_unit (id)
+	                        DEFERRABLE INITIALLY DEFERRED,
+	status         INT      REFERENCES config.copy_status (id)
+	                        DEFERRABLE INITIALLY DEFERRED,
+	location       INT      REFERENCES asset.copy_location (id)
+	                        DEFERRABLE INITIALLY DEFERRED,
+	loan_duration  INT      CONSTRAINT valid_loan_duration CHECK (
+	                            loan_duration IS NULL OR loan_duration IN (1,2,3)),
+	fine_level     INT      CONSTRAINT valid_fine_level CHECK (
+	                            fine_level IS NULL OR loan_duration IN (1,2,3)),
+	age_protect    INT,
+	circulate      BOOL,
+	deposit        BOOL,
+	ref            BOOL,
+	holdable       BOOL,
+	deposit_amount NUMERIC(6,2),
+	price          NUMERIC(8,2),
+	circ_modifier  TEXT,
+	circ_as_type   TEXT,
+	alert_message  TEXT,
+	opac_visible   BOOL,
+	floating       BOOL,
+	mint_condition BOOL
+);
+
+CREATE TABLE serial.subscription (
+	id                     SERIAL       PRIMARY KEY,
+	owning_lib             INT          NOT NULL DEFAULT 1
+	                                    REFERENCES actor.org_unit (id)
+	                                    ON DELETE SET NULL
+	                                    DEFERRABLE INITIALLY DEFERRED,
+	start_date             TIMESTAMP WITH TIME ZONE     NOT NULL,
+	end_date               TIMESTAMP WITH TIME ZONE,    -- interpret NULL as current subscription
+	record_entry           BIGINT       REFERENCES biblio.record_entry (id)
+	                                    ON DELETE SET NULL
+	                                    DEFERRABLE INITIALLY DEFERRED,
+	expected_date_offset   INTERVAL
+	-- acquisitions/business-side tables link to here
+);
+
+--at least one distribution per org_unit holding issues
+CREATE TABLE serial.distribution (
+	id                    SERIAL  PRIMARY KEY,
+	record_entry          BIGINT  REFERENCES serial.record_entry (id)
+	                              ON DELETE SET NULL
+	                              DEFERRABLE INITIALLY DEFERRED,
+	summary_method        TEXT    CONSTRAINT sdist_summary_method_check CHECK (
+	                                  summary_method IS NULL
+	                                  OR summary_method IN ( 'add_to_sre',
+	                                  'merge_with_sre', 'use_sre_only',
+	                                  'use_sdist_only')),
+	subscription          INT     NOT NULL
+	                              REFERENCES serial.subscription (id)
+								  ON DELETE CASCADE
+								  DEFERRABLE INITIALLY DEFERRED,
+	holding_lib           INT     NOT NULL
+	                              REFERENCES actor.org_unit (id)
+								  DEFERRABLE INITIALLY DEFERRED,
+	label                 TEXT    NOT NULL,
+	receive_call_number   BIGINT  REFERENCES asset.call_number (id)
+	                              DEFERRABLE INITIALLY DEFERRED,
+	receive_unit_template INT     REFERENCES asset.copy_template (id)
+	                              DEFERRABLE INITIALLY DEFERRED,
+	bind_call_number      BIGINT  REFERENCES asset.call_number (id)
+	                              DEFERRABLE INITIALLY DEFERRED,
+	bind_unit_template    INT     REFERENCES asset.copy_template (id)
+	                              DEFERRABLE INITIALLY DEFERRED,
+	unit_label_prefix     TEXT,
+	unit_label_suffix     TEXT
+);
+
+CREATE UNIQUE INDEX one_dist_per_sre_idx ON serial.distribution (record_entry);
+
+CREATE TABLE serial.stream (
+	id              SERIAL  PRIMARY KEY,
+	distribution    INT     NOT NULL
+	                        REFERENCES serial.distribution (id)
+	                        ON DELETE CASCADE
+	                        DEFERRABLE INITIALLY DEFERRED,
+	routing_label   TEXT
+);
+
+CREATE UNIQUE INDEX label_once_per_dist
+	ON serial.stream (distribution, routing_label)
+	WHERE routing_label IS NOT NULL;
+
+CREATE TABLE serial.routing_list_user (
+	id             SERIAL       PRIMARY KEY,
+	stream         INT          NOT NULL
+	                            REFERENCES serial.stream
+	                            ON DELETE CASCADE
+	                            DEFERRABLE INITIALLY DEFERRED,
+	pos            INT          NOT NULL DEFAULT 1,
+	reader         INT          REFERENCES actor.usr
+	                            ON DELETE CASCADE
+	                            DEFERRABLE INITIALLY DEFERRED,
+	department     TEXT,
+	note           TEXT,
+	CONSTRAINT one_pos_per_routing_list UNIQUE ( stream, pos ),
+	CONSTRAINT reader_or_dept CHECK
+	(
+	    -- Recipient is a person or a department, but not both
+		(reader IS NOT NULL AND department IS NULL) OR
+		(reader IS NULL AND department IS NOT NULL)
+	)
+);
+
+CREATE TABLE serial.caption_and_pattern (
+	id           SERIAL       PRIMARY KEY,
+	subscription INT          NOT NULL REFERENCES serial.subscription (id)
+	                          ON DELETE CASCADE
+	                          DEFERRABLE INITIALLY DEFERRED,
+	type         TEXT         NOT NULL
+	                          CONSTRAINT cap_type CHECK ( type in
+	                          ( 'basic', 'supplement', 'index' )),
+	create_date  TIMESTAMPTZ  NOT NULL DEFAULT now(),
+	start_date   TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
+	end_date     TIMESTAMP WITH TIME ZONE,
+	active       BOOL         NOT NULL DEFAULT FALSE,
+	pattern_code TEXT         NOT NULL,       -- must contain JSON
+	enum_1       TEXT,
+	enum_2       TEXT,
+	enum_3       TEXT,
+	enum_4       TEXT,
+	enum_5       TEXT,
+	enum_6       TEXT,
+	chron_1      TEXT,
+	chron_2      TEXT,
+	chron_3      TEXT,
+	chron_4      TEXT,
+	chron_5      TEXT
+);
+
+CREATE TABLE serial.issuance (
+	id              SERIAL    PRIMARY KEY,
+	creator         INT       NOT NULL
+	                          REFERENCES actor.usr (id)
+							  DEFERRABLE INITIALLY DEFERRED,
+	editor          INT       NOT NULL
+	                          REFERENCES actor.usr (id)
+	                          DEFERRABLE INITIALLY DEFERRED,
+	create_date     TIMESTAMP WITH TIME ZONE        NOT NULL DEFAULT now(),
+	edit_date       TIMESTAMP WITH TIME ZONE        NOT NULL DEFAULT now(),
+	subscription    INT       NOT NULL
+	                          REFERENCES serial.subscription (id)
+	                          ON DELETE CASCADE
+	                          DEFERRABLE INITIALLY DEFERRED,
+	label           TEXT,
+	date_published  TIMESTAMP WITH TIME ZONE,
+	caption_and_pattern  INT  REFERENCES serial.caption_and_pattern (id)
+                              DEFERRABLE INITIALLY DEFERRED,
+	holding_code    TEXT,
+	holding_type    TEXT      CONSTRAINT valid_holding_type CHECK
+	                          (
+	                              holding_type IS NULL
+	                              OR holding_type IN ('basic','supplement','index')
+	                          ),
+	holding_link_id INT
+	-- TODO: add columns for separate enumeration/chronology values
+);
+
+CREATE TABLE serial.unit (
+	label           TEXT,
+	label_sort_key  TEXT,
+	contents        TEXT    NOT NULL
+) INHERITS (asset.copy);
+
+ALTER TABLE serial.unit ADD PRIMARY KEY (id);
+
+ALTER TABLE serial.unit ADD CONSTRAINT serial_unit_call_number_fkey FOREIGN KEY (call_number) REFERENCES asset.call_number (id) DEFERRABLE INITIALLY DEFERRED;
+
+ALTER TABLE serial.unit ADD CONSTRAINT serial_unit_creator_fkey FOREIGN KEY (creator) REFERENCES actor.usr (id) ON DELETE SET NULL DEFERRABLE INITIALLY DEFERRED;
+
+ALTER TABLE serial.unit ADD CONSTRAINT serial_unit_editor_fkey FOREIGN KEY (editor) REFERENCES actor.usr (id) ON DELETE SET NULL DEFERRABLE INITIALLY DEFERRED;
+
+CREATE TABLE serial.item (
+	id              SERIAL  PRIMARY KEY,
+	creator         INT     NOT NULL
+	                        REFERENCES actor.usr (id)
+	                        DEFERRABLE INITIALLY DEFERRED,
+	editor          INT     NOT NULL
+	                        REFERENCES actor.usr (id)
+	                        DEFERRABLE INITIALLY DEFERRED,
+	create_date     TIMESTAMP WITH TIME ZONE        NOT NULL DEFAULT now(),
+	edit_date       TIMESTAMP WITH TIME ZONE        NOT NULL DEFAULT now(),
+	issuance        INT     NOT NULL
+	                        REFERENCES serial.issuance (id)
+	                        ON DELETE CASCADE
+	                        DEFERRABLE INITIALLY DEFERRED,
+	stream          INT     NOT NULL
+	                        REFERENCES serial.stream (id)
+	                        ON DELETE CASCADE
+	                        DEFERRABLE INITIALLY DEFERRED,
+	unit            INT     REFERENCES serial.unit (id)
+	                        ON DELETE SET NULL
+	                        DEFERRABLE INITIALLY DEFERRED,
+	uri             INT     REFERENCES asset.uri (id)
+	                        ON DELETE SET NULL
+	                        DEFERRABLE INITIALLY DEFERRED,
+	date_expected   TIMESTAMP WITH TIME ZONE,
+	date_received   TIMESTAMP WITH TIME ZONE,
+	status          TEXT    CONSTRAINT valid_status CHECK (
+                               status IN ( 'Bindery', 'Bound', 'Claimed', 'Discarded',
+                               'Expected', 'Not Held', 'Not Published', 'Received'))
+                            DEFAULT 'Expected',
+	shadowed        BOOL    NOT NULL DEFAULT FALSE
+);
+
+CREATE TABLE serial.item_note (
+	id          SERIAL  PRIMARY KEY,
+	item        INT     NOT NULL
+	                    REFERENCES serial.item (id)
+	                    ON DELETE CASCADE
+	                    DEFERRABLE INITIALLY DEFERRED,
+	creator     INT     NOT NULL
+	                    REFERENCES actor.usr (id)
+	                    DEFERRABLE INITIALLY DEFERRED,
+	create_date TIMESTAMP WITH TIME ZONE    DEFAULT NOW(),
+	pub         BOOL    NOT NULL    DEFAULT FALSE,
+	title       TEXT    NOT NULL,
+	value       TEXT    NOT NULL
+);
+
+CREATE TABLE serial.basic_summary (
+	id                  SERIAL  PRIMARY KEY,
+	distribution        INT     NOT NULL
+	                            REFERENCES serial.distribution (id)
+	                            ON DELETE CASCADE
+	                            DEFERRABLE INITIALLY DEFERRED,
+	generated_coverage  TEXT    NOT NULL,
+	textual_holdings    TEXT,
+	show_generated      BOOL    NOT NULL DEFAULT TRUE
+);
+
+CREATE TABLE serial.supplement_summary (
+	id                  SERIAL  PRIMARY KEY,
+	distribution        INT     NOT NULL
+	                            REFERENCES serial.distribution (id)
+	                            ON DELETE CASCADE
+	                            DEFERRABLE INITIALLY DEFERRED,
+	generated_coverage  TEXT    NOT NULL,
+	textual_holdings    TEXT,
+	show_generated      BOOL    NOT NULL DEFAULT TRUE
+);
+
+CREATE TABLE serial.index_summary (
+	id                  SERIAL  PRIMARY KEY,
+	distribution        INT     NOT NULL
+	                            REFERENCES serial.distribution (id)
+	                            ON DELETE CASCADE
+	                            DEFERRABLE INITIALLY DEFERRED,
+	generated_coverage  TEXT    NOT NULL,
+	textual_holdings    TEXT,
+	show_generated      BOOL    NOT NULL DEFAULT TRUE
+);
+
+-- DELETE FROM action_trigger.environment WHERE event_def IN (29,30); DELETE FROM action_trigger.event where event_def IN (29,30); DELETE FROM action_trigger.event_definition WHERE id IN (29,30); DELETE FROM action_trigger.hook WHERE key IN ('money.format.payment_receipt.email','money.format.payment_receipt.print'); DELETE FROM config.upgrade_log WHERE version = '0289'; -- from testing, this sql will remove these events, etc.
+
+DROP INDEX IF EXISTS authority.authority_record_unique_tcn;
+CREATE UNIQUE INDEX authority_record_unique_tcn ON authority.record_entry (arn_source,arn_value) WHERE deleted = FALSE OR deleted IS FALSE;
+
+DROP INDEX IF EXISTS asset.asset_call_number_label_once_per_lib;
+CREATE UNIQUE INDEX asset_call_number_label_once_per_lib ON asset.call_number (record, owning_lib, label) WHERE deleted = FALSE OR deleted IS FALSE;
+
+DROP INDEX IF EXISTS biblio.biblio_record_unique_tcn;
+CREATE UNIQUE INDEX biblio_record_unique_tcn ON biblio.record_entry (tcn_value) WHERE deleted = FALSE OR deleted IS FALSE;
+
+CREATE OR REPLACE FUNCTION config.interval_to_seconds( interval_val INTERVAL )
+RETURNS INTEGER AS $$
+BEGIN
+	RETURN EXTRACT( EPOCH FROM interval_val );
+END;
+$$ LANGUAGE plpgsql;
+
+CREATE OR REPLACE FUNCTION config.interval_to_seconds( interval_string TEXT )
+RETURNS INTEGER AS $$
+BEGIN
+	RETURN config.interval_to_seconds( interval_string::INTERVAL );
+END;
+$$ LANGUAGE plpgsql;
+
+INSERT INTO container.biblio_record_entry_bucket_type( code, label ) VALUES (
+    'temp',
+    oils_i18n_gettext(
+        'temp',
+        'Temporary bucket which gets deleted after use.',
+        'cbrebt',
+        'label'
+    )
+);
+
+-- DELETE FROM action_trigger.environment WHERE event_def IN (31,32); DELETE FROM action_trigger.event where event_def IN (31,32); DELETE FROM action_trigger.event_definition WHERE id IN (31,32); DELETE FROM action_trigger.hook WHERE key IN ('biblio.format.record_entry.email','biblio.format.record_entry.print'); DELETE FROM action_trigger.cleanup WHERE module = 'DeleteTempBiblioBucket'; DELETE FROM container.biblio_record_entry_bucket_item WHERE bucket IN (SELECT id FROM container.biblio_record_entry_bucket WHERE btype = 'temp'); DELETE FROM container.biblio_record_entry_bucket WHERE btype = 'temp'; DELETE FROM container.biblio_record_entry_bucket_type WHERE code = 'temp'; DELETE FROM config.upgrade_log WHERE version = '0294'; -- from testing, this sql will remove these events, etc.
+
+CREATE OR REPLACE FUNCTION biblio.check_marcxml_well_formed () RETURNS TRIGGER AS $func$
+BEGIN
+
+    IF xml_is_well_formed(NEW.marc) THEN
+        RETURN NEW;
+    ELSE
+        RAISE EXCEPTION 'Attempted to % MARCXML that is not well formed', TG_OP;
+    END IF;
+    
+END;
+$func$ LANGUAGE PLPGSQL;
+
+CREATE TRIGGER a_marcxml_is_well_formed BEFORE INSERT OR UPDATE ON biblio.record_entry FOR EACH ROW EXECUTE PROCEDURE biblio.check_marcxml_well_formed();
+
+CREATE TRIGGER a_marcxml_is_well_formed BEFORE INSERT OR UPDATE ON authority.record_entry FOR EACH ROW EXECUTE PROCEDURE biblio.check_marcxml_well_formed();
+
+ALTER TABLE serial.record_entry
+	ALTER COLUMN marc DROP NOT NULL;
+
+insert INTO CONFIG.xml_transform(name, namespace_uri, prefix, xslt)
+VALUES ('marc21expand880', 'http://www.loc.gov/MARC21/slim', 'marc', $$<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet
+    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
+    xmlns:marc="http://www.loc.gov/MARC21/slim"
+    version="1.0">
+<!--
+Copyright (C) 2010  Equinox Software, Inc.
+Galen Charlton <gmc at esilibrary.cOM.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+marc21_expand_880.xsl - stylesheet used during indexing to
+                        map alternative graphical representations
+                        of MARC fields stored in 880 fields
+                        to the corresponding tag name and value.
+
+For example, if a MARC record for a Chinese book has
+
+245.00 $6 880-01 $a Ba shi san nian duan pian xiao shuo xuan
+880.00 $6 245-01/$1 $a八十三年短篇小說選
+
+this stylesheet will transform it to the equivalent of
+
+245.00 $6 880-01 $a Ba shi san nian duan pian xiao shuo xuan
+245.00 $6 245-01/$1 $a八十三年短篇小說選
+
+-->
+    <xsl:output encoding="UTF-8" indent="yes" method="xml"/>
+
+    <xsl:template match="@*|node()">
+        <xsl:copy>
+            <xsl:apply-templates select="@*|node()"/>
+        </xsl:copy>
+    </xsl:template>
+
+    <xsl:template match="//marc:datafield[@tag='880']">
+        <xsl:if test="./marc:subfield[@code='6'] and string-length(./marc:subfield[@code='6']) &gt;= 6">
+            <marc:datafield>
+                <xsl:attribute name="tag">
+                    <xsl:value-of select="substring(./marc:subfield[@code='6'], 1, 3)" />
+                </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:apply-templates />
+            </marc:datafield>
+        </xsl:if>
+    </xsl:template>
+    
+</xsl:stylesheet>$$);
+
+-- Splitting the ingest trigger up into little bits
+
+CREATE TEMPORARY TABLE eg_0301_check_if_has_contents (
+    flag INTEGER PRIMARY KEY
+) ON COMMIT DROP;
+INSERT INTO eg_0301_check_if_has_contents VALUES (1);
+
+-- cause failure if either of the tables we want to drop have rows
+INSERT INTO eg_0301_check_if_has_contents SELECT 1 FROM asset.copy_transparency LIMIT 1;
+INSERT INTO eg_0301_check_if_has_contents SELECT 1 FROM asset.copy_transparency_map LIMIT 1;
+
+DROP TABLE IF EXISTS asset.copy_transparency_map;
+DROP TABLE IF EXISTS asset.copy_transparency;
+
+UPDATE config.metabib_field SET facet_xpath = '//' || facet_xpath WHERE facet_xpath IS NOT NULL;
+
+-- We won't necessarily use all of these, but they are here for completeness.
+-- Source is the EDI spec 1229 codelist, eg: http://www.stylusstudio.com/edifact/D04B/1229.htm
+-- Values are the EDI code value + 1000
+
+INSERT INTO acq.cancel_reason (keep_debits, id, org_unit, label, description) VALUES 
+('t',(  1+1000), 1, 'Added',     'The information is to be or has been added.'),
+('f',(  2+1000), 1, 'Deleted',   'The information is to be or has been deleted.'),
+('t',(  3+1000), 1, 'Changed',   'The information is to be or has been changed.'),
+('t',(  4+1000), 1, 'No action',                  'This line item is not affected by the actual message.'),
+('t',(  5+1000), 1, 'Accepted without amendment', 'This line item is entirely accepted by the seller.'),
+('t',(  6+1000), 1, 'Accepted with amendment',    'This line item is accepted but amended by the seller.'),
+('f',(  7+1000), 1, 'Not accepted',               'This line item is not accepted by the seller.'),
+('t',(  8+1000), 1, 'Schedule only', 'Code specifying that the message is a schedule only.'),
+('t',(  9+1000), 1, 'Amendments',    'Code specifying that amendments are requested/notified.'),
+('f',( 10+1000), 1, 'Not found',   'This line item is not found in the referenced message.'),
+('t',( 11+1000), 1, 'Not amended', 'This line is not amended by the buyer.'),
+('t',( 12+1000), 1, 'Line item numbers changed', 'Code specifying that the line item numbers have changed.'),
+('t',( 13+1000), 1, 'Buyer has deducted amount', 'Buyer has deducted amount from payment.'),
+('t',( 14+1000), 1, 'Buyer claims against invoice', 'Buyer has a claim against an outstanding invoice.'),
+('t',( 15+1000), 1, 'Charge back by seller', 'Factor has been requested to charge back the outstanding item.'),
+('t',( 16+1000), 1, 'Seller will issue credit note', 'Seller agrees to issue a credit note.'),
+('t',( 17+1000), 1, 'Terms changed for new terms', 'New settlement terms have been agreed.'),
+('t',( 18+1000), 1, 'Abide outcome of negotiations', 'Factor agrees to abide by the outcome of negotiations between seller and buyer.'),
+('t',( 19+1000), 1, 'Seller rejects dispute', 'Seller does not accept validity of dispute.'),
+('t',( 20+1000), 1, 'Settlement', 'The reported situation is settled.'),
+('t',( 21+1000), 1, 'No delivery', 'Code indicating that no delivery will be required.'),
+('t',( 22+1000), 1, 'Call-off delivery', 'A request for delivery of a particular quantity of goods to be delivered on a particular date (or within a particular period).'),
+('t',( 23+1000), 1, 'Proposed amendment', 'A code used to indicate an amendment suggested by the sender.'),
+('t',( 24+1000), 1, 'Accepted with amendment, no confirmation required', 'Accepted with changes which require no confirmation.'),
+('t',( 25+1000), 1, 'Equipment provisionally repaired', 'The equipment or component has been provisionally repaired.'),
+('t',( 26+1000), 1, 'Included', 'Code indicating that the entity is included.'),
+('t',( 27+1000), 1, 'Verified documents for coverage', 'Upon receipt and verification of documents we shall cover you when due as per your instructions.'),
+('t',( 28+1000), 1, 'Verified documents for debit',    'Upon receipt and verification of documents we shall authorize you to debit our account with you when due.'),
+('t',( 29+1000), 1, 'Authenticated advice for coverage',      'On receipt of your authenticated advice we shall cover you when due as per your instructions.'),
+('t',( 30+1000), 1, 'Authenticated advice for authorization', 'On receipt of your authenticated advice we shall authorize you to debit our account with you when due.'),
+('t',( 31+1000), 1, 'Authenticated advice for credit',        'On receipt of your authenticated advice we shall credit your account with us when due.'),
+('t',( 32+1000), 1, 'Credit advice requested for direct debit',           'A credit advice is requested for the direct debit.'),
+('t',( 33+1000), 1, 'Credit advice and acknowledgement for direct debit', 'A credit advice and acknowledgement are requested for the direct debit.'),
+('t',( 34+1000), 1, 'Inquiry',     'Request for information.'),
+('t',( 35+1000), 1, 'Checked',     'Checked.'),
+('t',( 36+1000), 1, 'Not checked', 'Not checked.'),
+('f',( 37+1000), 1, 'Cancelled',   'Discontinued.'),
+('t',( 38+1000), 1, 'Replaced',    'Provide a replacement.'),
+('t',( 39+1000), 1, 'New',         'Not existing before.'),
+('t',( 40+1000), 1, 'Agreed',      'Consent.'),
+('t',( 41+1000), 1, 'Proposed',    'Put forward for consideration.'),
+('t',( 42+1000), 1, 'Already delivered', 'Delivery has taken place.'),
+('t',( 43+1000), 1, 'Additional subordinate structures will follow', 'Additional subordinate structures will follow the current hierarchy level.'),
+('t',( 44+1000), 1, 'Additional subordinate structures will not follow', 'No additional subordinate structures will follow the current hierarchy level.'),
+('t',( 45+1000), 1, 'Result opposed',         'A notification that the result is opposed.'),
+('t',( 46+1000), 1, 'Auction held',           'A notification that an auction was held.'),
+('t',( 47+1000), 1, 'Legal action pursued',   'A notification that legal action has been pursued.'),
+('t',( 48+1000), 1, 'Meeting held',           'A notification that a meeting was held.'),
+('t',( 49+1000), 1, 'Result set aside',       'A notification that the result has been set aside.'),
+('t',( 50+1000), 1, 'Result disputed',        'A notification that the result has been disputed.'),
+('t',( 51+1000), 1, 'Countersued',            'A notification that a countersuit has been filed.'),
+('t',( 52+1000), 1, 'Pending',                'A notification that an action is awaiting settlement.'),
+('f',( 53+1000), 1, 'Court action dismissed', 'A notification that a court action will no longer be heard.'),
+('t',( 54+1000), 1, 'Referred item, accepted', 'The item being referred to has been accepted.'),
+('f',( 55+1000), 1, 'Referred item, rejected', 'The item being referred to has been rejected.'),
+('t',( 56+1000), 1, 'Debit advice statement line',  'Notification that the statement line is a debit advice.'),
+('t',( 57+1000), 1, 'Credit advice statement line', 'Notification that the statement line is a credit advice.'),
+('t',( 58+1000), 1, 'Grouped credit advices',       'Notification that the credit advices are grouped.'),
+('t',( 59+1000), 1, 'Grouped debit advices',        'Notification that the debit advices are grouped.'),
+('t',( 60+1000), 1, 'Registered', 'The name is registered.'),
+('f',( 61+1000), 1, 'Payment denied', 'The payment has been denied.'),
+('t',( 62+1000), 1, 'Approved as amended', 'Approved with modifications.'),
+('t',( 63+1000), 1, 'Approved as submitted', 'The request has been approved as submitted.'),
+('f',( 64+1000), 1, 'Cancelled, no activity', 'Cancelled due to the lack of activity.'),
+('t',( 65+1000), 1, 'Under investigation', 'Investigation is being done.'),
+('t',( 66+1000), 1, 'Initial claim received', 'Notification that the initial claim was received.'),
+('f',( 67+1000), 1, 'Not in process', 'Not in process.'),
+('f',( 68+1000), 1, 'Rejected, duplicate', 'Rejected because it is a duplicate.'),
+('f',( 69+1000), 1, 'Rejected, resubmit with corrections', 'Rejected but may be resubmitted when corrected.'),
+('t',( 70+1000), 1, 'Pending, incomplete', 'Pending because of incomplete information.'),
+('t',( 71+1000), 1, 'Under field office investigation', 'Investigation by the field is being done.'),
+('t',( 72+1000), 1, 'Pending, awaiting additional material', 'Pending awaiting receipt of additional material.'),
+('t',( 73+1000), 1, 'Pending, awaiting review', 'Pending while awaiting review.'),
+('t',( 74+1000), 1, 'Reopened', 'Opened again.'),
+('t',( 75+1000), 1, 'Processed by primary, forwarded to additional payer(s)',   'This request has been processed by the primary payer and sent to additional payer(s).'),
+('t',( 76+1000), 1, 'Processed by secondary, forwarded to additional payer(s)', 'This request has been processed by the secondary payer and sent to additional payer(s).'),
+('t',( 77+1000), 1, 'Processed by tertiary, forwarded to additional payer(s)',  'This request has been processed by the tertiary payer and sent to additional payer(s).'),
+('t',( 78+1000), 1, 'Previous payment decision reversed', 'A previous payment decision has been reversed.'),
+('t',( 79+1000), 1, 'Not our claim, forwarded to another payer(s)', 'A request does not belong to this payer but has been forwarded to another payer(s).'),
+('t',( 80+1000), 1, 'Transferred to correct insurance carrier', 'The request has been transferred to the correct insurance carrier for processing.'),
+('t',( 81+1000), 1, 'Not paid, predetermination pricing only', 'Payment has not been made and the enclosed response is predetermination pricing only.'),
+('t',( 82+1000), 1, 'Documentation claim', 'The claim is for documentation purposes only, no payment required.'),
+('t',( 83+1000), 1, 'Reviewed', 'Assessed.'),
+('f',( 84+1000), 1, 'Repriced', 'This price was changed.'),
+('t',( 85+1000), 1, 'Audited', 'An official examination has occurred.'),
+('t',( 86+1000), 1, 'Conditionally paid', 'Payment has been conditionally made.'),
+('t',( 87+1000), 1, 'On appeal', 'Reconsideration of the decision has been applied for.'),
+('t',( 88+1000), 1, 'Closed', 'Shut.'),
+('t',( 89+1000), 1, 'Reaudited', 'A subsequent official examination has occurred.'),
+('t',( 90+1000), 1, 'Reissued', 'Issued again.'),
+('t',( 91+1000), 1, 'Closed after reopening', 'Reopened and then closed.'),
+('t',( 92+1000), 1, 'Redetermined', 'Determined again or differently.'),
+('t',( 93+1000), 1, 'Processed as primary',   'Processed as the first.'),
+('t',( 94+1000), 1, 'Processed as secondary', 'Processed as the second.'),
+('t',( 95+1000), 1, 'Processed as tertiary',  'Processed as the third.'),
+('t',( 96+1000), 1, 'Correction of error', 'A correction to information previously communicated which contained an error.'),
+('t',( 97+1000), 1, 'Single credit item of a group', 'Notification that the credit item is a single credit item of a group of credit items.'),
+('t',( 98+1000), 1, 'Single debit item of a group',  'Notification that the debit item is a single debit item of a group of debit items.'),
+('t',( 99+1000), 1, 'Interim response', 'The response is an interim one.'),
+('t',(100+1000), 1, 'Final response',   'The response is an final one.'),
+('t',(101+1000), 1, 'Debit advice requested', 'A debit advice is requested for the transaction.'),
+('t',(102+1000), 1, 'Transaction not impacted', 'Advice that the transaction is not impacted.'),
+('t',(103+1000), 1, 'Patient to be notified',                    'The action to take is to notify the patient.'),
+('t',(104+1000), 1, 'Healthcare provider to be notified',        'The action to take is to notify the healthcare provider.'),
+('t',(105+1000), 1, 'Usual general practitioner to be notified', 'The action to take is to notify the usual general practitioner.'),
+('t',(106+1000), 1, 'Advice without details', 'An advice without details is requested or notified.'),
+('t',(107+1000), 1, 'Advice with details', 'An advice with details is requested or notified.'),
+('t',(108+1000), 1, 'Amendment requested', 'An amendment is requested.'),
+('t',(109+1000), 1, 'For information', 'Included for information only.'),
+('f',(110+1000), 1, 'Withdraw', 'A code indicating discontinuance or retraction.'),
+('t',(111+1000), 1, 'Delivery date change', 'The action / notiification is a change of the delivery date.'),
+('f',(112+1000), 1, 'Quantity change',      'The action / notification is a change of quantity.'),
+('t',(113+1000), 1, 'Resale and claim', 'The identified items have been sold by the distributor to the end customer, and compensation for the loss of inventory value is claimed.'),
+('t',(114+1000), 1, 'Resale',           'The identified items have been sold by the distributor to the end customer.'),
+('t',(115+1000), 1, 'Prior addition', 'This existing line item becomes available at an earlier date.');
+
+INSERT INTO config.metabib_field ( id, field_class, name, label, format, xpath, facet_field, search_field ) VALUES
+    (26, 'identifier', 'arcn', oils_i18n_gettext(26, 'Authority record control number', 'cmf', 'label'), 'marcxml', $$//marc:subfield[@code='0']$$, TRUE, FALSE );
+ 
+SELECT SETVAL('config.metabib_field_id_seq'::TEXT, (SELECT MAX(id) FROM config.metabib_field), TRUE);
+ 
+INSERT INTO config.index_normalizer (name, description, func, param_count) VALUES (
+	'Remove Parenthesized Substring',
+	'Remove any parenthesized substrings from the extracted text, such as the agency code preceding authority record control numbers in subfield 0.',
+	'remove_paren_substring',
+	0
+);
+
+INSERT INTO config.index_normalizer (name, description, func, param_count) VALUES (
+	'Trim Surrounding Space',
+	'Trim leading and trailing spaces from extracted text.',
+	'btrim',
+	0
+);
+
+INSERT INTO config.metabib_field_index_norm_map (field,norm,pos)
+    SELECT  m.id,
+            i.id,
+            -2
+      FROM  config.metabib_field m,
+            config.index_normalizer i
+      WHERE i.func IN ('remove_paren_substring')
+            AND m.id IN (26);
+
+INSERT INTO config.metabib_field_index_norm_map (field,norm,pos)
+    SELECT  m.id,
+            i.id,
+            -1
+      FROM  config.metabib_field m,
+            config.index_normalizer i
+      WHERE i.func IN ('btrim')
+            AND m.id IN (26);
+
+-- Function that takes, and returns, marcxml and compiles an embedded ruleset for you, and they applys it
+CREATE OR REPLACE FUNCTION vandelay.merge_record_xml ( target_marc TEXT, template_marc TEXT ) RETURNS TEXT AS $$
+DECLARE
+    dyn_profile     vandelay.compile_profile%ROWTYPE;
+    replace_rule    TEXT;
+    tmp_marc        TEXT;
+    trgt_marc        TEXT;
+    tmpl_marc        TEXT;
+    match_count     INT;
+BEGIN
+
+    IF target_marc IS NULL OR template_marc IS NULL THEN
+        -- RAISE NOTICE 'no marc for target or template record';
+        RETURN NULL;
+    END IF;
+
+    dyn_profile := vandelay.compile_profile( template_marc );
+
+    IF dyn_profile.replace_rule <> '' AND dyn_profile.preserve_rule <> '' THEN
+        -- RAISE NOTICE 'both replace [%] and preserve [%] specified', dyn_profile.replace_rule, dyn_profile.preserve_rule;
+        RETURN NULL;
+    END IF;
+
+    IF dyn_profile.replace_rule <> '' THEN
+        trgt_marc = target_marc;
+        tmpl_marc = template_marc;
+        replace_rule = dyn_profile.replace_rule;
+    ELSE
+        tmp_marc = target_marc;
+        trgt_marc = template_marc;
+        tmpl_marc = tmp_marc;
+        replace_rule = dyn_profile.preserve_rule;
+    END IF;
+
+    RETURN vandelay.merge_record_xml( trgt_marc, tmpl_marc, dyn_profile.add_rule, replace_rule, dyn_profile.strip_rule );
+
+END;
+$$ LANGUAGE PLPGSQL;
+
+-- Function to generate an ephemeral overlay template from an authority record
+CREATE OR REPLACE FUNCTION authority.generate_overlay_template ( TEXT, BIGINT ) RETURNS TEXT AS $func$
+
+    use MARC::Record;
+    use MARC::File::XML (BinaryEncoding => 'UTF-8');
+
+    my $xml = shift;
+    my $r = MARC::Record->new_from_xml( $xml );
+
+    return undef unless ($r);
+
+    my $id = shift() || $r->subfield( '901' => 'c' );
+    $id =~ s/^\s*(?:\([^)]+\))?\s*(.+)\s*?$/$1/;
+    return undef unless ($id); # We need an ID!
+
+    my $tmpl = MARC::Record->new();
+
+    my @rule_fields;
+    for my $field ( $r->field( '1..' ) ) { # Get main entry fields from the authority record
+
+        my $tag = $field->tag;
+        my $i1 = $field->indicator(1);
+        my $i2 = $field->indicator(2);
+        my $sf = join '', map { $_->[0] } $field->subfields;
+        my @data = map { @$_ } $field->subfields;
+
+        my @replace_them;
+
+        # Map the authority field to bib fields it can control.
+        if ($tag >= 100 and $tag <= 111) {       # names
+            @replace_them = map { $tag + $_ } (0, 300, 500, 600, 700);
+        } elsif ($tag eq '130') {                # uniform title
+            @replace_them = qw/130 240 440 730 830/;
+        } elsif ($tag >= 150 and $tag <= 155) {  # subjects
+            @replace_them = ($tag + 500);
+        } elsif ($tag >= 180 and $tag <= 185) {  # floating subdivisions
+            @replace_them = qw/100 400 600 700 800 110 410 610 710 810 111 411 611 711 811 130 240 440 730 830 650 651 655/;
+        } else {
+            next;
+        }
+
+        # Dummy up the bib-side data
+        $tmpl->append_fields(
+            map {
+                MARC::Field->new( $_, $i1, $i2, @data )
+            } @replace_them
+        );
+
+        # Construct some 'replace' rules
+        push @rule_fields, map { $_ . $sf . '[0~\)' .$id . '$]' } @replace_them;
+    }
+
+    # Insert the replace rules into the template
+    $tmpl->append_fields(
+        MARC::Field->new( '905' => ' ' => ' ' => 'r' => join(',', @rule_fields ) )
+    );
+
+    $xml = $tmpl->as_xml_record;
+    $xml =~ s/^<\?.+?\?>$//mo;
+    $xml =~ s/\n//sgo;
+    $xml =~ s/>\s+</></sgo;
+
+    return $xml;
+
+$func$ LANGUAGE PLPERLU;
+
+CREATE OR REPLACE FUNCTION authority.generate_overlay_template ( BIGINT ) RETURNS TEXT AS $func$
+    SELECT authority.generate_overlay_template( marc, id ) FROM authority.record_entry WHERE id = $1;
+$func$ LANGUAGE SQL;
+
+CREATE OR REPLACE FUNCTION authority.generate_overlay_template ( TEXT ) RETURNS TEXT AS $func$
+    SELECT authority.generate_overlay_template( $1, NULL );
+$func$ LANGUAGE SQL;
+
+DELETE FROM config.metabib_field_index_norm_map WHERE field = 26;
+DELETE FROM config.metabib_field WHERE id = 26;
+
+-- Making this a global_flag (UI accessible) instead of an internal_flag
+INSERT INTO config.global_flag (name, label) -- defaults to enabled=FALSE
+    VALUES (
+        'ingest.disable_authority_linking',
+        oils_i18n_gettext(
+            'ingest.disable_authority_linking',
+            'Authority Automation: Disable bib-authority link tracking',
+            'cgf', 
+            'label'
+        )
+    );
+UPDATE config.global_flag SET enabled = (SELECT enabled FROM ONLY config.internal_flag WHERE name = 'ingest.disable_authority_linking');
+DELETE FROM config.internal_flag WHERE name = 'ingest.disable_authority_linking';
+
+INSERT INTO config.global_flag (name, label) -- defaults to enabled=FALSE
+    VALUES (
+        'ingest.disable_authority_auto_update',
+        oils_i18n_gettext(
+            'ingest.disable_authority_auto_update',
+            'Authority Automation: Disable automatic authority updating (requires link tracking)',
+            'cgf', 
+            'label'
+        )
+    );
+
+-- Enable automated ingest of authority records; just insert the row into
+-- authority.record_entry and authority.full_rec will automatically be populated
+
+CREATE OR REPLACE FUNCTION authority.propagate_changes (aid BIGINT, bid BIGINT) RETURNS BIGINT AS $func$
+    UPDATE  biblio.record_entry
+      SET   marc = vandelay.merge_record_xml( marc, authority.generate_overlay_template( $1 ) )
+      WHERE id = $2;
+    SELECT $1;
+$func$ LANGUAGE SQL;
+
+CREATE OR REPLACE FUNCTION authority.propagate_changes (aid BIGINT) RETURNS SETOF BIGINT AS $func$
+    SELECT authority.propagate_changes( authority, bib ) FROM authority.bib_linking WHERE authority = $1;
+$func$ LANGUAGE SQL;
+
+-- authority.rec_descriptor appears to be unused currently
+CREATE OR REPLACE FUNCTION authority.reingest_authority_rec_descriptor( auth_id BIGINT ) RETURNS VOID AS $func$
+BEGIN
+    DELETE FROM authority.rec_descriptor WHERE record = auth_id;
+--    INSERT INTO authority.rec_descriptor (record, record_status, char_encoding)
+--        SELECT  auth_id, ;
+
+    RETURN;
+END;
+$func$ LANGUAGE PLPGSQL;
+
+CREATE OR REPLACE FUNCTION authority.reingest_authority_full_rec( auth_id BIGINT ) RETURNS VOID AS $func$
+BEGIN
+    DELETE FROM authority.full_rec WHERE record = auth_id;
+    INSERT INTO authority.full_rec (record, tag, ind1, ind2, subfield, value)
+        SELECT record, tag, ind1, ind2, subfield, value FROM authority.flatten_marc( auth_id );
+
+    RETURN;
+END;
+$func$ LANGUAGE PLPGSQL;
+
+-- AFTER UPDATE OR INSERT trigger for authority.record_entry
+CREATE OR REPLACE FUNCTION authority.indexing_ingest_or_delete () RETURNS TRIGGER AS $func$
+BEGIN
+
+    IF NEW.deleted IS TRUE THEN -- If this authority is deleted
+        DELETE FROM authority.bib_linking WHERE authority = NEW.id; -- Avoid updating fields in bibs that are no longer visible
+          -- Should remove matching $0 from controlled fields at the same time?
+        RETURN NEW; -- and we're done
+    END IF;
+
+    IF TG_OP = 'UPDATE' THEN -- re-ingest?
+        PERFORM * FROM config.internal_flag WHERE name = 'ingest.reingest.force_on_same_marc' AND enabled;
+
+        IF NOT FOUND AND OLD.marc = NEW.marc THEN -- don't do anything if the MARC didn't change
+            RETURN NEW;
+        END IF;
+    END IF;
+
+    -- Flatten and insert the afr data
+    PERFORM * FROM config.internal_flag WHERE name = 'ingest.disable_authority_full_rec' AND enabled;
+    IF NOT FOUND THEN
+        PERFORM authority.reingest_authority_full_rec(NEW.id);
+-- authority.rec_descriptor is not currently used
+--        PERFORM * FROM config.internal_flag WHERE name = 'ingest.disable_authority_rec_descriptor' AND enabled;
+--        IF NOT FOUND THEN
+--            PERFORM authority.reingest_authority_rec_descriptor(NEW.id);
+--        END IF;
+    END IF;
+
+    RETURN NEW;
+END;
+$func$ LANGUAGE PLPGSQL;
+
+CREATE TRIGGER aaa_auth_ingest_or_delete AFTER INSERT OR UPDATE ON authority.record_entry FOR EACH ROW EXECUTE PROCEDURE authority.indexing_ingest_or_delete ();
+
+-- Some records manage to get XML namespace declarations into each element,
+-- like <datafield xmlns:marc="http://www.loc.gov/MARC21/slim"
+-- This broke the old maintain_901(), so we'll make the regex more robust
+
+CREATE OR REPLACE FUNCTION maintain_901 () RETURNS TRIGGER AS $func$
+BEGIN
+    -- Remove any existing 901 fields before we insert the authoritative one
+    NEW.marc := REGEXP_REPLACE(NEW.marc, E'<datafield\s*[^<>]*?\s*tag="901".+?</datafield>', '', 'g');
+    IF TG_TABLE_SCHEMA = 'biblio' THEN
+        NEW.marc := REGEXP_REPLACE(
+            NEW.marc,
+            E'(</(?:[^:]*?:)?record>)',
+            E'<datafield tag="901" ind1=" " ind2=" ">' ||
+                '<subfield code="a">' || NEW.tcn_value || E'</subfield>' ||
+                '<subfield code="b">' || NEW.tcn_source || E'</subfield>' ||
+                '<subfield code="c">' || NEW.id || E'</subfield>' ||
+                '<subfield code="t">' || TG_TABLE_SCHEMA || E'</subfield>' ||
+                CASE WHEN NEW.owner IS NOT NULL THEN '<subfield code="o">' || NEW.owner || E'</subfield>' ELSE '' END ||
+                CASE WHEN NEW.share_depth IS NOT NULL THEN '<subfield code="d">' || NEW.share_depth || E'</subfield>' ELSE '' END ||
+             E'</datafield>\\1'
+        );
+    ELSIF TG_TABLE_SCHEMA = 'authority' THEN
+        NEW.marc := REGEXP_REPLACE(
+            NEW.marc,
+            E'(</(?:[^:]*?:)?record>)',
+            E'<datafield tag="901" ind1=" " ind2=" ">' ||
+                '<subfield code="a">' || NEW.arn_value || E'</subfield>' ||
+                '<subfield code="b">' || NEW.arn_source || E'</subfield>' ||
+                '<subfield code="c">' || NEW.id || E'</subfield>' ||
+                '<subfield code="t">' || TG_TABLE_SCHEMA || E'</subfield>' ||
+             E'</datafield>\\1'
+        );
+    ELSIF TG_TABLE_SCHEMA = 'serial' THEN
+        NEW.marc := REGEXP_REPLACE(
+            NEW.marc,
+            E'(</(?:[^:]*?:)?record>)',
+            E'<datafield tag="901" ind1=" " ind2=" ">' ||
+                '<subfield code="c">' || NEW.id || E'</subfield>' ||
+                '<subfield code="t">' || TG_TABLE_SCHEMA || E'</subfield>' ||
+                '<subfield code="o">' || NEW.owning_lib || E'</subfield>' ||
+                CASE WHEN NEW.record IS NOT NULL THEN '<subfield code="r">' || NEW.record || E'</subfield>' ELSE '' END ||
+             E'</datafield>\\1'
+        );
+    ELSE
+        NEW.marc := REGEXP_REPLACE(
+            NEW.marc,
+            E'(</(?:[^:]*?:)?record>)',
+            E'<datafield tag="901" ind1=" " ind2=" ">' ||
+                '<subfield code="c">' || NEW.id || E'</subfield>' ||
+                '<subfield code="t">' || TG_TABLE_SCHEMA || E'</subfield>' ||
+             E'</datafield>\\1'
+        );
+    END IF;
+
+    RETURN NEW;
+END;
+$func$ LANGUAGE PLPGSQL;
+
+CREATE TRIGGER b_maintain_901 BEFORE INSERT OR UPDATE ON biblio.record_entry FOR EACH ROW EXECUTE PROCEDURE maintain_901();
+CREATE TRIGGER b_maintain_901 BEFORE INSERT OR UPDATE ON authority.record_entry FOR EACH ROW EXECUTE PROCEDURE maintain_901();
+CREATE TRIGGER b_maintain_901 BEFORE INSERT OR UPDATE ON serial.record_entry FOR EACH ROW EXECUTE PROCEDURE maintain_901();
+ 
+-- In booking, elbow room defines:
+--  a) how far in the future you must make a reservation on a given item if
+--      that item will have to transit somewhere to fulfill the reservation.
+--  b) how soon a reservation must be starting for the reserved item to
+--      be op-captured by the checkin interface.
+
+-- We don't want to clobber any default_elbow room at any level:
+
+CREATE OR REPLACE FUNCTION pg_temp.default_elbow() RETURNS INTEGER AS $$
+DECLARE
+    existing    actor.org_unit_setting%ROWTYPE;
+BEGIN
+    SELECT INTO existing id FROM actor.org_unit_setting WHERE name = 'circ.booking_reservation.default_elbow_room';
+    IF NOT FOUND THEN
+        INSERT INTO actor.org_unit_setting (org_unit, name, value) VALUES (
+            (SELECT id FROM actor.org_unit WHERE parent_ou IS NULL),
+            'circ.booking_reservation.default_elbow_room',
+            '"1 day"'
+        );
+        RETURN 1;
+    END IF;
+    RETURN 0;
+END;
+$$ LANGUAGE plpgsql;
+
+SELECT pg_temp.default_elbow();
+
+DROP FUNCTION IF EXISTS action.usr_visible_circ_copies( INTEGER );
+
+-- returns the distinct set of target copy IDs from a user's visible circulation history
+CREATE OR REPLACE FUNCTION action.usr_visible_circ_copies( INTEGER ) RETURNS SETOF BIGINT AS $$
+    SELECT DISTINCT(target_copy) FROM action.usr_visible_circs($1)
+$$ LANGUAGE SQL;
+
+ALTER TABLE action.in_house_use DROP CONSTRAINT in_house_use_item_fkey;
+ALTER TABLE action.transit_copy DROP CONSTRAINT transit_copy_target_copy_fkey;
+ALTER TABLE action.hold_transit_copy DROP CONSTRAINT ahtc_tc_fkey;
+ALTER TABLE action.hold_copy_map DROP CONSTRAINT hold_copy_map_target_copy_fkey;
+
+ALTER TABLE asset.stat_cat_entry_copy_map DROP CONSTRAINT a_sc_oc_fkey;
+
+ALTER TABLE authority.record_entry ADD COLUMN owner INT;
+ALTER TABLE serial.record_entry ADD COLUMN owner INT;
+
+INSERT INTO config.global_flag (name, label) -- defaults to enabled=FALSE
+    VALUES (
+        'cat.maintain_control_numbers',
+        oils_i18n_gettext(
+            'cat.maintain_control_numbers',
+            'Cat: Maintain 001/003/035 according to the MARC21 specification',
+            'cgf', 
+            'label'
+        )
+    );
+
+INSERT INTO config.global_flag (name, label, enabled)
+    VALUES (
+        'circ.holds.empty_issuance_ok',
+        oils_i18n_gettext(
+            'circ.holds.empty_issuance_ok',
+            'Holds: Allow holds on empty issuances',
+            'cgf',
+            'label'
+        ),
+        TRUE
+    );
+
+CREATE OR REPLACE FUNCTION maintain_control_numbers() RETURNS TRIGGER AS $func$
+use strict;
+use MARC::Record;
+use MARC::File::XML (BinaryEncoding => 'UTF-8');
+use Encode;
+use Unicode::Normalize;
+
+my $record = MARC::Record->new_from_xml($_TD->{new}{marc});
+my $schema = $_TD->{table_schema};
+my $rec_id = $_TD->{new}{id};
+
+# Short-circuit if maintaining control numbers per MARC21 spec is not enabled
+my $enable = spi_exec_query("SELECT enabled FROM config.global_flag WHERE name = 'cat.maintain_control_numbers'");
+if (!($enable->{processed}) or $enable->{rows}[0]->{enabled} eq 'f') {
+    return;
+}
+
+# Get the control number identifier from an OU setting based on $_TD->{new}{owner}
+my $ou_cni = 'EVRGRN';
+
+my $owner;
+if ($schema eq 'serial') {
+    $owner = $_TD->{new}{owning_lib};
+} else {
+    # are.owner and bre.owner can be null, so fall back to the consortial setting
+    $owner = $_TD->{new}{owner} || 1;
+}
+
+my $ous_rv = spi_exec_query("SELECT value FROM actor.org_unit_ancestor_setting('cat.marc_control_number_identifier', $owner)");
+if ($ous_rv->{processed}) {
+    $ou_cni = $ous_rv->{rows}[0]->{value};
+    $ou_cni =~ s/"//g; # Stupid VIM syntax highlighting"
+} else {
+    # Fall back to the shortname of the OU if there was no OU setting
+    $ous_rv = spi_exec_query("SELECT shortname FROM actor.org_unit WHERE id = $owner");
+    if ($ous_rv->{processed}) {
+        $ou_cni = $ous_rv->{rows}[0]->{shortname};
+    }
+}
+
+my ($create, $munge) = (0, 0);
+my ($orig_001, $orig_003) = ('', '');
+
+# Incoming MARC records may have multiple 001s or 003s, despite the spec
+my @control_ids = $record->field('003');
+my @scns = $record->field('035');
+
+foreach my $id_field ('001', '003') {
+    my $spec_value;
+    my @controls = $record->field($id_field);
+
+    if ($id_field eq '001') {
+        $spec_value = $rec_id;
+    } else {
+        $spec_value = $ou_cni;
+    }
+
+    # Create the 001/003 if none exist
+    if (scalar(@controls) == 0) {
+        $record->insert_fields_ordered(MARC::Field->new($id_field, $spec_value));
+        $create = 1;
+    } elsif (scalar(@controls) > 1) {
+        # Do we already have the right 001/003 value in the existing set?
+        unless (grep $_->data() eq $spec_value, @controls) {
+            $munge = 1;
+        }
+
+        # Delete the other fields, as with more than 1 001/003 we do not know which 003/001 to match
+        foreach my $control (@controls) {
+            unless ($control->data() eq $spec_value) {
+                $record->delete_field($control);
+            }
+        }
+    } else {
+        # Only one field; check to see if we need to munge it
+        unless (grep $_->data() eq $spec_value, @controls) {
+            $munge = 1;
+        }
+    }
+}
+
+# Now, if we need to munge the 001, we will first push the existing 001/003 into the 035
+if ($munge) {
+    my $scn = "(" . $record->field('003')->data() . ")" . $record->field('001')->data();
+
+    # Do not create duplicate 035 fields
+    unless (grep $_->subfield('a') eq $scn, @scns) {
+        $record->insert_fields_ordered(MARC::Field->new('035', '', '', 'a' => $scn));
+    }
+}
+
+# Set the 001/003 and update the MARC
+if ($create or $munge) {
+    $record->field('001')->data($rec_id);
+    $record->field('003')->data($ou_cni);
+
+    my $xml = $record->as_xml_record();
+    $xml =~ s/\n//sgo;
+    $xml =~ s/^<\?xml.+\?\s*>//go;
+    $xml =~ s/>\s+</></go;
+    $xml =~ s/\p{Cc}//go;
+
+    # Embed a version of OpenILS::Application::AppUtils->entityize()
+    # to avoid having to set PERL5LIB for PostgreSQL as well
+
+    # If we are going to convert non-ASCII characters to XML entities,
+    # we had better be dealing with a UTF8 string to begin with
+    $xml = decode_utf8($xml);
+
+    $xml = NFC($xml);
+
+    # Convert raw ampersands to entities
+    $xml =~ s/&(?!\S+;)/&amp;/gso;
+
+    # Convert Unicode characters to entities
+    $xml =~ s/([\x{0080}-\x{fffd}])/sprintf('&#x%X;',ord($1))/sgoe;
+
+    $xml =~ s/[\x00-\x1f]//go;
+    $_TD->{new}{marc} = $xml;
+
+    return "MODIFY";
+}
+
+return;
+$func$ LANGUAGE PLPERLU;
+
+CREATE TRIGGER c_maintain_control_numbers BEFORE INSERT OR UPDATE ON authority.record_entry FOR EACH ROW EXECUTE PROCEDURE maintain_control_numbers();
+CREATE TRIGGER c_maintain_control_numbers BEFORE INSERT OR UPDATE ON biblio.record_entry FOR EACH ROW EXECUTE PROCEDURE maintain_control_numbers();
+CREATE TRIGGER c_maintain_control_numbers BEFORE INSERT OR UPDATE ON serial.record_entry FOR EACH ROW EXECUTE PROCEDURE maintain_control_numbers();
+
+INSERT INTO metabib.facet_entry (source, field, value)
+    SELECT source, field, value FROM (
+        SELECT * FROM metabib.author_field_entry
+            UNION ALL
+        SELECT * FROM metabib.keyword_field_entry
+            UNION ALL
+        SELECT * FROM metabib.identifier_field_entry
+            UNION ALL
+        SELECT * FROM metabib.title_field_entry
+            UNION ALL
+        SELECT * FROM metabib.subject_field_entry
+            UNION ALL
+        SELECT * FROM metabib.series_field_entry
+        )x
+    WHERE x.index_vector = '';
+        
+DELETE FROM metabib.author_field_entry WHERE index_vector = '';
+DELETE FROM metabib.keyword_field_entry WHERE index_vector = '';
+DELETE FROM metabib.identifier_field_entry WHERE index_vector = '';
+DELETE FROM metabib.title_field_entry WHERE index_vector = '';
+DELETE FROM metabib.subject_field_entry WHERE index_vector = '';
+DELETE FROM metabib.series_field_entry WHERE index_vector = '';
+
+CREATE INDEX metabib_facet_entry_field_idx ON metabib.facet_entry (field);
+CREATE INDEX metabib_facet_entry_value_idx ON metabib.facet_entry (SUBSTRING(value,1,1024));
+CREATE INDEX metabib_facet_entry_source_idx ON metabib.facet_entry (source);
+
+-- copy OPAC visibility materialized view
+CREATE OR REPLACE FUNCTION asset.refresh_opac_visible_copies_mat_view () RETURNS VOID AS $$
+
+    TRUNCATE TABLE asset.opac_visible_copies;
+
+    INSERT INTO asset.opac_visible_copies (id, circ_lib, record)
+    SELECT  cp.id, cp.circ_lib, cn.record
+    FROM  asset.copy cp
+        JOIN asset.call_number cn ON (cn.id = cp.call_number)
+        JOIN actor.org_unit a ON (cp.circ_lib = a.id)
+        JOIN asset.copy_location cl ON (cp.location = cl.id)
+        JOIN config.copy_status cs ON (cp.status = cs.id)
+        JOIN biblio.record_entry b ON (cn.record = b.id)
+    WHERE NOT cp.deleted
+        AND NOT cn.deleted
+        AND NOT b.deleted
+        AND cs.opac_visible
+        AND cl.opac_visible
+        AND cp.opac_visible
+        AND a.opac_visible;
+
+$$ LANGUAGE SQL;
+COMMENT ON FUNCTION asset.refresh_opac_visible_copies_mat_view() IS $$
+Rebuild the copy OPAC visibility cache.  Useful during migrations.
+$$;
+
+-- and actually populate the table
+SELECT asset.refresh_opac_visible_copies_mat_view();
+
+CREATE OR REPLACE FUNCTION asset.cache_copy_visibility () RETURNS TRIGGER as $func$
+DECLARE
+    add_query       TEXT;
+    remove_query    TEXT;
+    do_add          BOOLEAN := false;
+    do_remove       BOOLEAN := false;
+BEGIN
+    add_query := $$
+            INSERT INTO asset.opac_visible_copies (id, circ_lib, record)
+                SELECT  cp.id, cp.circ_lib, cn.record
+                  FROM  asset.copy cp
+                        JOIN asset.call_number cn ON (cn.id = cp.call_number)
+                        JOIN actor.org_unit a ON (cp.circ_lib = a.id)
+                        JOIN asset.copy_location cl ON (cp.location = cl.id)
+                        JOIN config.copy_status cs ON (cp.status = cs.id)
+                        JOIN biblio.record_entry b ON (cn.record = b.id)
+                  WHERE NOT cp.deleted
+                        AND NOT cn.deleted
+                        AND NOT b.deleted
+                        AND cs.opac_visible
+                        AND cl.opac_visible
+                        AND cp.opac_visible
+                        AND a.opac_visible
+    $$;
+ 
+    remove_query := $$ DELETE FROM asset.opac_visible_copies WHERE id IN ( SELECT id FROM asset.copy WHERE $$;
+
+    IF TG_OP = 'INSERT' THEN
+
+        IF TG_TABLE_NAME IN ('copy', 'unit') THEN
+            add_query := add_query || 'AND cp.id = ' || NEW.id || ';';
+            EXECUTE add_query;
+        END IF;
+
+        RETURN NEW;
+
+    END IF;
+
+    -- handle items first, since with circulation activity
+    -- their statuses change frequently
+    IF TG_TABLE_NAME IN ('copy', 'unit') THEN
+
+        IF OLD.location    <> NEW.location OR
+           OLD.call_number <> NEW.call_number OR
+           OLD.status      <> NEW.status OR
+           OLD.circ_lib    <> NEW.circ_lib THEN
+            -- any of these could change visibility, but
+            -- we'll save some queries and not try to calculate
+            -- the change directly
+            do_remove := true;
+            do_add := true;
+        ELSE
+
+            IF OLD.deleted <> NEW.deleted THEN
+                IF NEW.deleted THEN
+                    do_remove := true;
+                ELSE
+                    do_add := true;
+                END IF;
+            END IF;
+
+            IF OLD.opac_visible <> NEW.opac_visible THEN
+                IF OLD.opac_visible THEN
+                    do_remove := true;
+                ELSIF NOT do_remove THEN -- handle edge case where deleted item
+                                        -- is also marked opac_visible
+                    do_add := true;
+                END IF;
+            END IF;
+
+        END IF;
+
+        IF do_remove THEN
+            DELETE FROM asset.opac_visible_copies WHERE id = NEW.id;
+        END IF;
+        IF do_add THEN
+            add_query := add_query || 'AND cp.id = ' || NEW.id || ';';
+            EXECUTE add_query;
+        END IF;
+
+        RETURN NEW;
+
+    END IF;
+
+    IF TG_TABLE_NAME IN ('call_number', 'record_entry') THEN -- these have a 'deleted' column
+ 
+        IF OLD.deleted AND NEW.deleted THEN -- do nothing
+
+            RETURN NEW;
+ 
+        ELSIF NEW.deleted THEN -- remove rows
+ 
+            IF TG_TABLE_NAME = 'call_number' THEN
+                DELETE FROM asset.opac_visible_copies WHERE id IN (SELECT id FROM asset.copy WHERE call_number = NEW.id);
+            ELSIF TG_TABLE_NAME = 'record_entry' THEN
+                DELETE FROM asset.opac_visible_copies WHERE record = NEW.id;
+            END IF;
+ 
+            RETURN NEW;
+ 
+        ELSIF OLD.deleted THEN -- add rows
+ 
+            IF TG_TABLE_NAME IN ('copy','unit') THEN
+                add_query := add_query || 'AND cp.id = ' || NEW.id || ';';
+            ELSIF TG_TABLE_NAME = 'call_number' THEN
+                add_query := add_query || 'AND cp.call_number = ' || NEW.id || ';';
+            ELSIF TG_TABLE_NAME = 'record_entry' THEN
+                add_query := add_query || 'AND cn.record = ' || NEW.id || ';';
+            END IF;
+ 
+            EXECUTE add_query;
+            RETURN NEW;
+ 
+        END IF;
+ 
+    END IF;
+
+    IF TG_TABLE_NAME = 'call_number' THEN
+
+        IF OLD.record <> NEW.record THEN
+            -- call number is linked to different bib
+            remove_query := remove_query || 'call_number = ' || NEW.id || ');';
+            EXECUTE remove_query;
+            add_query := add_query || 'AND cp.call_number = ' || NEW.id || ';';
+            EXECUTE add_query;
+        END IF;
+
+        RETURN NEW;
+
+    END IF;
+
+    IF TG_TABLE_NAME IN ('record_entry') THEN
+        RETURN NEW; -- don't have 'opac_visible'
+    END IF;
+
+    -- actor.org_unit, asset.copy_location, asset.copy_status
+    IF NEW.opac_visible = OLD.opac_visible THEN -- do nothing
+
+        RETURN NEW;
+
+    ELSIF NEW.opac_visible THEN -- add rows
+
+        IF TG_TABLE_NAME = 'org_unit' THEN
+            add_query := add_query || 'AND cp.circ_lib = ' || NEW.id || ';';
+        ELSIF TG_TABLE_NAME = 'copy_location' THEN
+            add_query := add_query || 'AND cp.location = ' || NEW.id || ';';
+        ELSIF TG_TABLE_NAME = 'copy_status' THEN
+            add_query := add_query || 'AND cp.status = ' || NEW.id || ';';
+        END IF;
+ 
+        EXECUTE add_query;
+ 
+    ELSE -- delete rows
+
+        IF TG_TABLE_NAME = 'org_unit' THEN
+            remove_query := 'DELETE FROM asset.opac_visible_copies WHERE circ_lib = ' || NEW.id || ';';
+        ELSIF TG_TABLE_NAME = 'copy_location' THEN
+            remove_query := remove_query || 'location = ' || NEW.id || ');';
+        ELSIF TG_TABLE_NAME = 'copy_status' THEN
+            remove_query := remove_query || 'status = ' || NEW.id || ');';
+        END IF;
+ 
+        EXECUTE remove_query;
+ 
+    END IF;
+ 
+    RETURN NEW;
+END;
+$func$ LANGUAGE PLPGSQL;
+COMMENT ON FUNCTION asset.cache_copy_visibility() IS $$
+Trigger function to update the copy OPAC visiblity cache.
+$$;
+CREATE TRIGGER a_opac_vis_mat_view_tgr AFTER INSERT OR UPDATE ON biblio.record_entry FOR EACH ROW EXECUTE PROCEDURE asset.cache_copy_visibility();
+CREATE TRIGGER a_opac_vis_mat_view_tgr AFTER INSERT OR UPDATE ON asset.copy FOR EACH ROW EXECUTE PROCEDURE asset.cache_copy_visibility();
+CREATE TRIGGER a_opac_vis_mat_view_tgr AFTER INSERT OR UPDATE ON asset.call_number FOR EACH ROW EXECUTE PROCEDURE asset.cache_copy_visibility();
+CREATE TRIGGER a_opac_vis_mat_view_tgr AFTER INSERT OR UPDATE ON asset.copy_location FOR EACH ROW EXECUTE PROCEDURE asset.cache_copy_visibility();
+CREATE TRIGGER a_opac_vis_mat_view_tgr AFTER INSERT OR UPDATE ON serial.unit FOR EACH ROW EXECUTE PROCEDURE asset.cache_copy_visibility();
+CREATE TRIGGER a_opac_vis_mat_view_tgr AFTER INSERT OR UPDATE ON config.copy_status FOR EACH ROW EXECUTE PROCEDURE asset.cache_copy_visibility();
+CREATE TRIGGER a_opac_vis_mat_view_tgr AFTER INSERT OR UPDATE ON actor.org_unit FOR EACH ROW EXECUTE PROCEDURE asset.cache_copy_visibility();
+
+-- must create this rule explicitly; it is not inherited from asset.copy
+CREATE RULE protect_serial_unit_delete AS ON DELETE TO serial.unit DO INSTEAD UPDATE serial.unit SET deleted = TRUE WHERE OLD.id = serial.unit.id;
+
+CREATE RULE protect_authority_rec_delete AS ON DELETE TO authority.record_entry DO INSTEAD (UPDATE authority.record_entry SET deleted = TRUE WHERE OLD.id = authority.record_entry.id);
+
+CREATE OR REPLACE FUNCTION authority.merge_records ( target_record BIGINT, source_record BIGINT ) RETURNS INT AS $func$
+DECLARE
+    moved_objects INT := 0;
+    bib_id        INT := 0;
+    bib_rec       biblio.record_entry%ROWTYPE;
+    auth_link     authority.bib_linking%ROWTYPE;
+BEGIN
+
+    -- 1. Make source_record MARC a copy of the target_record to get auto-sync in linked bib records
+    UPDATE authority.record_entry
+      SET marc = (
+        SELECT marc
+          FROM authority.record_entry
+          WHERE id = target_record
+      )
+      WHERE id = source_record;
+
+    -- 2. Update all bib records with the ID from target_record in their $0
+    FOR bib_rec IN SELECT bre.* FROM biblio.record_entry bre 
+      INNER JOIN authority.bib_linking abl ON abl.bib = bre.id
+      WHERE abl.authority = target_record LOOP
+
+        UPDATE biblio.record_entry
+          SET marc = REGEXP_REPLACE(marc, 
+            E'(<subfield\\s+code="0"\\s*>[^<]*?\\))' || source_record || '<',
+            E'\\1' || target_record || '<', 'g')
+          WHERE id = bib_rec.id;
+
+          moved_objects := moved_objects + 1;
+    END LOOP;
+
+    -- 3. "Delete" source_record
+    DELETE FROM authority.record_entry
+      WHERE id = source_record;
+
+    RETURN moved_objects;
+END;
+$func$ LANGUAGE plpgsql;
+
+-- serial.record_entry already had an owner column spelled "owning_lib"
+-- Adjust the table and affected functions accordingly
+
+ALTER TABLE serial.record_entry DROP COLUMN owner;
+
+CREATE TABLE actor.usr_saved_search (
+    id              SERIAL          PRIMARY KEY,
+	owner           INT             NOT NULL REFERENCES actor.usr (id)
+	                                ON DELETE CASCADE
+	                                DEFERRABLE INITIALLY DEFERRED,
+	name            TEXT            NOT NULL,
+	create_date     TIMESTAMPTZ     NOT NULL DEFAULT now(),
+	query_text      TEXT            NOT NULL,
+	query_type      TEXT            NOT NULL
+	                                CONSTRAINT valid_query_text CHECK (
+	                                query_type IN ( 'URL' )) DEFAULT 'URL',
+	                                -- we may add other types someday
+	target          TEXT            NOT NULL
+	                                CONSTRAINT valid_target CHECK (
+	                                target IN ( 'record', 'metarecord', 'callnumber' )),
+	CONSTRAINT name_once_per_user UNIQUE (owner, name)
+);
+
+-- Apply Dan Wells' changes to the serial schema, from the
+-- seials-integration branch
+
+CREATE TABLE serial.subscription_note (
+	id           SERIAL PRIMARY KEY,
+	subscription INT    NOT NULL
+	                    REFERENCES serial.subscription (id)
+	                    ON DELETE CASCADE
+	                    DEFERRABLE INITIALLY DEFERRED,
+	creator      INT    NOT NULL
+	                    REFERENCES actor.usr (id)
+	                    DEFERRABLE INITIALLY DEFERRED,
+	create_date  TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
+	pub          BOOL   NOT NULL DEFAULT FALSE,
+	title        TEXT   NOT NULL,
+	value        TEXT   NOT NULL
+);
+CREATE INDEX serial_subscription_note_sub_idx ON serial.subscription_note (subscription);
+
+CREATE TABLE serial.distribution_note (
+	id           SERIAL PRIMARY KEY,
+	distribution INT    NOT NULL
+	                    REFERENCES serial.distribution (id)
+	                    ON DELETE CASCADE
+	                    DEFERRABLE INITIALLY DEFERRED,
+	creator      INT    NOT NULL
+	                    REFERENCES actor.usr (id)
+	                    DEFERRABLE INITIALLY DEFERRED,
+	create_date  TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
+	pub          BOOL   NOT NULL DEFAULT FALSE,
+	title        TEXT   NOT NULL,
+	value        TEXT   NOT NULL
+);
+
+------- Begin surgery on serial.unit
+
+ALTER TABLE serial.unit
+	DROP COLUMN label;
+
+ALTER TABLE serial.unit
+	RENAME COLUMN label_sort_key TO sort_key;
+
+ALTER TABLE serial.unit
+	RENAME COLUMN contents TO detailed_contents;
+
+ALTER TABLE serial.unit
+	ADD COLUMN summary_contents TEXT;
+
+UPDATE serial.unit
+SET summary_contents = detailed_contents;
+
+ALTER TABLE serial.unit
+	ALTER column summary_contents SET NOT NULL;
+
+------- End surgery on serial.unit
+
+-- DELETE FROM config.upgrade_log WHERE version = 'temp'; DELETE FROM action_trigger.event WHERE event_def IN (33,34); DELETE FROM action_trigger.environment WHERE event_def IN (33,34); DELETE FROM action_trigger.event_definition WHERE id IN (33,34); DELETE FROM action_trigger.hook WHERE key IN ( 'circ.format.missing_pieces.slip.print', 'circ.format.missing_pieces.letter.print' );
+
+-- Now rebuild the constraints dropped via cascade.
+-- ALTER TABLE acq.provider    ADD CONSTRAINT provider_edi_default_fkey FOREIGN KEY (edi_default) REFERENCES acq.edi_account (id) DEFERRABLE INITIALLY DEFERRED;
+DROP INDEX IF EXISTS money.money_mat_summary_id_idx;
+ALTER TABLE money.materialized_billable_xact_summary ADD PRIMARY KEY (id);
+
+-- ALTER TABLE staging.billing_address_stage ADD PRIMARY KEY (row_id);
+
+DELETE FROM config.metabib_field_index_norm_map
+    WHERE norm IN (
+        SELECT id 
+            FROM config.index_normalizer
+            WHERE func IN ('first_word', 'naco_normalize', 'split_date_range')
+    )
+    AND field = 18
+;
+
+-- We won't necessarily use all of these, but they are here for completeness.
+-- Source is the EDI spec 6063 codelist, eg: http://www.stylusstudio.com/edifact/D04B/6063.htm
+-- Values are the EDI code value + 1200
+
+INSERT INTO acq.cancel_reason (org_unit, keep_debits, id, label, description) VALUES 
+(1, 't', 1201, 'Discrete quantity', 'Individually separated and distinct quantity.'),
+(1, 't', 1202, 'Charge', 'Quantity relevant for charge.'),
+(1, 't', 1203, 'Cumulative quantity', 'Quantity accumulated.'),
+(1, 't', 1204, 'Interest for overdrawn account', 'Interest for overdrawing the account.'),
+(1, 't', 1205, 'Active ingredient dose per unit', 'The dosage of active ingredient per unit.'),
+(1, 't', 1206, 'Auditor', 'The number of entities that audit accounts.'),
+(1, 't', 1207, 'Branch locations, leased', 'The number of branch locations being leased by an entity.'),
+(1, 't', 1208, 'Inventory quantity at supplier''s subject to inspection by', 'customer Quantity of goods which the customer requires the supplier to have in inventory and which may be inspected by the customer if desired.'),
+(1, 't', 1209, 'Branch locations, owned', 'The number of branch locations owned by an entity.'),
+(1, 't', 1210, 'Judgements registered', 'The number of judgements registered against an entity.'),
+(1, 't', 1211, 'Split quantity', 'Part of the whole quantity.'),
+(1, 't', 1212, 'Despatch quantity', 'Quantity despatched by the seller.'),
+(1, 't', 1213, 'Liens registered', 'The number of liens registered against an entity.'),
+(1, 't', 1214, 'Livestock', 'The number of animals kept for use or profit.'),
+(1, 't', 1215, 'Insufficient funds returned cheques', 'The number of cheques returned due to insufficient funds.'),
+(1, 't', 1216, 'Stolen cheques', 'The number of stolen cheques.'),
+(1, 't', 1217, 'Quantity on hand', 'The total quantity of a product on hand at a location. This includes as well units awaiting return to manufacturer, units unavailable due to inspection procedures and undamaged stock available for despatch, resale or use.'),
+(1, 't', 1218, 'Previous quantity', 'Quantity previously referenced.'),
+(1, 't', 1219, 'Paid-in security shares', 'The number of security shares issued and for which full payment has been made.'),
+(1, 't', 1220, 'Unusable quantity', 'Quantity not usable.'),
+(1, 't', 1221, 'Ordered quantity', '[6024] The quantity which has been ordered.'),
+(1, 't', 1222, 'Quantity at 100%', 'Equivalent quantity at 100% purity.'),
+(1, 't', 1223, 'Active ingredient', 'Quantity at 100% active agent content.'),
+(1, 't', 1224, 'Inventory quantity at supplier''s not subject to inspection', 'by customer Quantity of goods which the customer requires the supplier to have in inventory but which will not be checked by the customer.'),
+(1, 't', 1225, 'Retail sales', 'Quantity of retail point of sale activity.'),
+(1, 't', 1226, 'Promotion quantity', 'A quantity associated with a promotional event.'),
+(1, 't', 1227, 'On hold for shipment', 'Article received which cannot be shipped in its present form.'),
+(1, 't', 1228, 'Military sales quantity', 'Quantity of goods or services sold to a military organization.'),
+(1, 't', 1229, 'On premises sales',  'Sale of product in restaurants or bars.'),
+(1, 't', 1230, 'Off premises sales', 'Sale of product directly to a store.'),
+(1, 't', 1231, 'Estimated annual volume', 'Volume estimated for a year.'),
+(1, 't', 1232, 'Minimum delivery batch', 'Minimum quantity of goods delivered at one time.'),
+(1, 't', 1233, 'Maximum delivery batch', 'Maximum quantity of goods delivered at one time.'),
+(1, 't', 1234, 'Pipes', 'The number of tubes used to convey a substance.'),
+(1, 't', 1235, 'Price break from', 'The minimum quantity of a quantity range for a specified (unit) price.'),
+(1, 't', 1236, 'Price break to', 'Maximum quantity to which the price break applies.'),
+(1, 't', 1237, 'Poultry', 'The number of domestic fowl.'),
+(1, 't', 1238, 'Secured charges registered', 'The number of secured charges registered against an entity.'),
+(1, 't', 1239, 'Total properties owned', 'The total number of properties owned by an entity.'),
+(1, 't', 1240, 'Normal delivery', 'Quantity normally delivered by the seller.'),
+(1, 't', 1241, 'Sales quantity not included in the replenishment', 'calculation Sales which will not be included in the calculation of replenishment requirements.'),
+(1, 't', 1242, 'Maximum supply quantity, supplier endorsed', 'Maximum supply quantity endorsed by a supplier.'),
+(1, 't', 1243, 'Buyer', 'The number of buyers.'),
+(1, 't', 1244, 'Debenture bond', 'The number of fixed-interest bonds of an entity backed by general credit rather than specified assets.'),
+(1, 't', 1245, 'Debentures filed against directors', 'The number of notices of indebtedness filed against an entity''s directors.'),
+(1, 't', 1246, 'Pieces delivered', 'Number of pieces actually received at the final destination.'),
+(1, 't', 1247, 'Invoiced quantity', 'The quantity as per invoice.'),
+(1, 't', 1248, 'Received quantity', 'The quantity which has been received.'),
+(1, 't', 1249, 'Chargeable distance', '[6110] The distance between two points for which a specific tariff applies.'),
+(1, 't', 1250, 'Disposition undetermined quantity', 'Product quantity that has not yet had its disposition determined.'),
+(1, 't', 1251, 'Inventory category transfer', 'Inventory that has been moved from one inventory category to another.'),
+(1, 't', 1252, 'Quantity per pack', 'Quantity for each pack.'),
+(1, 't', 1253, 'Minimum order quantity', 'Minimum quantity of goods for an order.'),
+(1, 't', 1254, 'Maximum order quantity', 'Maximum quantity of goods for an order.'),
+(1, 't', 1255, 'Total sales', 'The summation of total quantity sales.'),
+(1, 't', 1256, 'Wholesaler to wholesaler sales', 'Sale of product to other wholesalers by a wholesaler.'),
+(1, 't', 1257, 'In transit quantity', 'A quantity that is en route.'),
+(1, 't', 1258, 'Quantity withdrawn', 'Quantity withdrawn from a location.'),
+(1, 't', 1259, 'Numbers of consumer units in the traded unit', 'Number of units for consumer sales in a unit for trading.'),
+(1, 't', 1260, 'Current inventory quantity available for shipment', 'Current inventory quantity available for shipment.'),
+(1, 't', 1261, 'Return quantity', 'Quantity of goods returned.'),
+(1, 't', 1262, 'Sorted quantity', 'The quantity that is sorted.'),
+(1, 'f', 1263, 'Sorted quantity rejected', 'The sorted quantity that is rejected.'),
+(1, 't', 1264, 'Scrap quantity', 'Remainder of the total quantity after split deliveries.'),
+(1, 'f', 1265, 'Destroyed quantity', 'Quantity of goods destroyed.'),
+(1, 't', 1266, 'Committed quantity', 'Quantity a party is committed to.'),
+(1, 't', 1267, 'Estimated reading quantity', 'The value that is estimated to be the reading of a measuring device (e.g. meter).'),
+(1, 't', 1268, 'End quantity', 'The quantity recorded at the end of an agreement or period.'),
+(1, 't', 1269, 'Start quantity', 'The quantity recorded at the start of an agreement or period.'),
+(1, 't', 1270, 'Cumulative quantity received', 'Cumulative quantity of all deliveries of this article received by the buyer.'),
+(1, 't', 1271, 'Cumulative quantity ordered', 'Cumulative quantity of all deliveries, outstanding and scheduled orders.'),
+(1, 't', 1272, 'Cumulative quantity received end of prior year', 'Cumulative quantity of all deliveries of the product received by the buyer till end of prior year.'),
+(1, 't', 1273, 'Outstanding quantity', 'Difference between quantity ordered and quantity received.'),
+(1, 't', 1274, 'Latest cumulative quantity', 'Cumulative quantity after complete delivery of all scheduled quantities of the product.'),
+(1, 't', 1275, 'Previous highest cumulative quantity', 'Cumulative quantity after complete delivery of all scheduled quantities of the product from a prior schedule period.'),
+(1, 't', 1276, 'Adjusted corrector reading', 'A corrector reading after it has been adjusted.'),
+(1, 't', 1277, 'Work days', 'Number of work days, e.g. per respective period.'),
+(1, 't', 1278, 'Cumulative quantity scheduled', 'Adding the quantity actually scheduled to previous cumulative quantity.'),
+(1, 't', 1279, 'Previous cumulative quantity', 'Cumulative quantity prior the actual order.'),
+(1, 't', 1280, 'Unadjusted corrector reading', 'A corrector reading before it has been adjusted.'),
+(1, 't', 1281, 'Extra unplanned delivery', 'Non scheduled additional quantity.'),
+(1, 't', 1282, 'Quantity requirement for sample inspection', 'Required quantity for sample inspection.'),
+(1, 't', 1283, 'Backorder quantity', 'The quantity of goods that is on back-order.'),
+(1, 't', 1284, 'Urgent delivery quantity', 'Quantity for urgent delivery.'),
+(1, 'f', 1285, 'Previous order quantity to be cancelled', 'Quantity ordered previously to be cancelled.'),
+(1, 't', 1286, 'Normal reading quantity', 'The value recorded or read from a measuring device (e.g. meter) in the normal conditions.'),
+(1, 't', 1287, 'Customer reading quantity', 'The value recorded or read from a measuring device (e.g. meter) by the customer.'),
+(1, 't', 1288, 'Information reading quantity', 'The value recorded or read from a measuring device (e.g. meter) for information purposes.'),
+(1, 't', 1289, 'Quality control held', 'Quantity of goods held pending completion of a quality control assessment.'),
+(1, 't', 1290, 'As is quantity', 'Quantity as it is in the existing circumstances.'),
+(1, 't', 1291, 'Open quantity', 'Quantity remaining after partial delivery.'),
+(1, 't', 1292, 'Final delivery quantity', 'Quantity of final delivery to a respective order.'),
+(1, 't', 1293, 'Subsequent delivery quantity', 'Quantity delivered to a respective order after it''s final delivery.'),
+(1, 't', 1294, 'Substitutional quantity', 'Quantity delivered replacing previous deliveries.'),
+(1, 't', 1295, 'Redelivery after post processing', 'Quantity redelivered after post processing.'),
+(1, 'f', 1296, 'Quality control failed', 'Quantity of goods which have failed quality control.'),
+(1, 't', 1297, 'Minimum inventory', 'Minimum stock quantity on which replenishment is based.'),
+(1, 't', 1298, 'Maximum inventory', 'Maximum stock quantity on which replenishment is based.'),
+(1, 't', 1299, 'Estimated quantity', 'Quantity estimated.'),
+(1, 't', 1300, 'Chargeable weight', 'The weight on which charges are based.'),
+(1, 't', 1301, 'Chargeable gross weight', 'The gross weight on which charges are based.'),
+(1, 't', 1302, 'Chargeable tare weight', 'The tare weight on which charges are based.'),
+(1, 't', 1303, 'Chargeable number of axles', 'The number of axles on which charges are based.'),
+(1, 't', 1304, 'Chargeable number of containers', 'The number of containers on which charges are based.'),
+(1, 't', 1305, 'Chargeable number of rail wagons', 'The number of rail wagons on which charges are based.'),
+(1, 't', 1306, 'Chargeable number of packages', 'The number of packages on which charges are based.'),
+(1, 't', 1307, 'Chargeable number of units', 'The number of units on which charges are based.'),
+(1, 't', 1308, 'Chargeable period', 'The period of time on which charges are based.'),
+(1, 't', 1309, 'Chargeable volume', 'The volume on which charges are based.'),
+(1, 't', 1310, 'Chargeable cubic measurements', 'The cubic measurements on which charges are based.'),
+(1, 't', 1311, 'Chargeable surface', 'The surface area on which charges are based.'),
+(1, 't', 1312, 'Chargeable length', 'The length on which charges are based.'),
+(1, 't', 1313, 'Quantity to be delivered', 'The quantity to be delivered.'),
+(1, 't', 1314, 'Number of passengers', 'Total number of passengers on the conveyance.'),
+(1, 't', 1315, 'Number of crew', 'Total number of crew members on the conveyance.'),
+(1, 't', 1316, 'Number of transport documents', 'Total number of air waybills, bills of lading, etc. being reported for a specific conveyance.'),
+(1, 't', 1317, 'Quantity landed', 'Quantity of goods actually arrived.'),
+(1, 't', 1318, 'Quantity manifested', 'Quantity of goods contracted for delivery by the carrier.'),
+(1, 't', 1319, 'Short shipped', 'Indication that part of the consignment was not shipped.'),
+(1, 't', 1320, 'Split shipment', 'Indication that the consignment has been split into two or more shipments.'),
+(1, 't', 1321, 'Over shipped', 'The quantity of goods shipped that exceeds the quantity contracted.'),
+(1, 't', 1322, 'Short-landed goods', 'If quantity of goods actually landed is less than the quantity which appears in the documentation. This quantity is the difference between these quantities.'),
+(1, 't', 1323, 'Surplus goods', 'If quantity of goods actually landed is more than the quantity which appears in the documentation. This quantity is the difference between these quantities.'),
+(1, 'f', 1324, 'Damaged goods', 'Quantity of goods which have deteriorated in transport such that they cannot be used for the purpose for which they were originally intended.'),
+(1, 'f', 1325, 'Pilferage goods', 'Quantity of goods stolen during transport.'),
+(1, 'f', 1326, 'Lost goods', 'Quantity of goods that disappeared in transport.'),
+(1, 't', 1327, 'Report difference', 'The quantity concerning the same transaction differs between two documents/messages and the source of this difference is a typing error.'),
+(1, 't', 1328, 'Quantity loaded', 'Quantity of goods loaded onto a means of transport.'),
+(1, 't', 1329, 'Units per unit price', 'Number of units per unit price.'),
+(1, 't', 1330, 'Allowance', 'Quantity relevant for allowance.'),
+(1, 't', 1331, 'Delivery quantity', 'Quantity required by buyer to be delivered.'),
+(1, 't', 1332, 'Cumulative quantity, preceding period, planned', 'Cumulative quantity originally planned for the preceding period.'),
+(1, 't', 1333, 'Cumulative quantity, preceding period, reached', 'Cumulative quantity reached in the preceding period.'),
+(1, 't', 1334, 'Cumulative quantity, actual planned',            'Cumulative quantity planned for now.'),
+(1, 't', 1335, 'Period quantity, planned', 'Quantity planned for this period.'),
+(1, 't', 1336, 'Period quantity, reached', 'Quantity reached during this period.'),
+(1, 't', 1337, 'Cumulative quantity, preceding period, estimated', 'Estimated cumulative quantity reached in the preceding period.'),
+(1, 't', 1338, 'Cumulative quantity, actual estimated',            'Estimated cumulative quantity reached now.'),
+(1, 't', 1339, 'Cumulative quantity, preceding period, measured', 'Surveyed cumulative quantity reached in the preceding period.'),
+(1, 't', 1340, 'Cumulative quantity, actual measured', 'Surveyed cumulative quantity reached now.'),
+(1, 't', 1341, 'Period quantity, measured',            'Surveyed quantity reached during this period.'),
+(1, 't', 1342, 'Total quantity, planned', 'Total quantity planned.'),
+(1, 't', 1343, 'Quantity, remaining', 'Quantity remaining.'),
+(1, 't', 1344, 'Tolerance', 'Plus or minus tolerance expressed as a monetary amount.'),
+(1, 't', 1345, 'Actual stock',          'The stock on hand, undamaged, and available for despatch, sale or use.'),
+(1, 't', 1346, 'Model or target stock', 'The stock quantity required or planned to have on hand, undamaged and available for use.'),
+(1, 't', 1347, 'Direct shipment quantity', 'Quantity to be shipped directly to a customer from a manufacturing site.'),
+(1, 't', 1348, 'Amortization total quantity',     'Indication of final quantity for amortization.'),
+(1, 't', 1349, 'Amortization order quantity',     'Indication of actual share of the order quantity for amortization.'),
+(1, 't', 1350, 'Amortization cumulated quantity', 'Indication of actual cumulated quantity of previous and actual amortization order quantity.'),
+(1, 't', 1351, 'Quantity advised',  'Quantity advised by supplier or shipper, in contrast to quantity actually received.'),
+(1, 't', 1352, 'Consignment stock', 'Quantity of goods with an external customer which is still the property of the supplier. Payment for these goods is only made to the supplier when the ownership has been transferred between the trading partners.'),
+(1, 't', 1353, 'Statistical sales quantity', 'Quantity of goods sold in a specified period.'),
+(1, 't', 1354, 'Sales quantity planned',     'Quantity of goods required to meet future demands. - Market intelligence quantity.'),
+(1, 't', 1355, 'Replenishment quantity',     'Quantity required to maintain the requisite on-hand stock of goods.'),
+(1, 't', 1356, 'Inventory movement quantity', 'To specify the quantity of an inventory movement.'),
+(1, 't', 1357, 'Opening stock balance quantity', 'To specify the quantity of an opening stock balance.'),
+(1, 't', 1358, 'Closing stock balance quantity', 'To specify the quantity of a closing stock balance.'),
+(1, 't', 1359, 'Number of stops', 'Number of times a means of transport stops before arriving at destination.'),
+(1, 't', 1360, 'Minimum production batch', 'The quantity specified is the minimum output from a single production run.'),
+(1, 't', 1361, 'Dimensional sample quantity', 'The quantity defined is a sample for the purpose of validating dimensions.'),
+(1, 't', 1362, 'Functional sample quantity', 'The quantity defined is a sample for the purpose of validating function and performance.'),
+(1, 't', 1363, 'Pre-production quantity', 'Quantity of the referenced item required prior to full production.'),
+(1, 't', 1364, 'Delivery batch', 'Quantity of the referenced item which constitutes a standard batch for deliver purposes.'),
+(1, 't', 1365, 'Delivery batch multiple', 'The multiples in which delivery batches can be supplied.'),
+(1, 't', 1366, 'All time buy',             'The total quantity of the referenced covering all future needs. Further orders of the referenced item are not expected.'),
+(1, 't', 1367, 'Total delivery quantity',  'The total quantity required by the buyer to be delivered.'),
+(1, 't', 1368, 'Single delivery quantity', 'The quantity required by the buyer to be delivered in a single shipment.'),
+(1, 't', 1369, 'Supplied quantity',  'Quantity of the referenced item actually shipped.'),
+(1, 't', 1370, 'Allocated quantity', 'Quantity of the referenced item allocated from available stock for delivery.'),
+(1, 't', 1371, 'Maximum stackability', 'The number of pallets/handling units which can be safely stacked one on top of another.'),
+(1, 't', 1372, 'Amortisation quantity', 'The quantity of the referenced item which has a cost for tooling amortisation included in the item price.'),
+(1, 't', 1373, 'Previously amortised quantity', 'The cumulative quantity of the referenced item which had a cost for tooling amortisation included in the item price.'),
+(1, 't', 1374, 'Total amortisation quantity', 'The total quantity of the referenced item which has a cost for tooling amortisation included in the item price.'),
+(1, 't', 1375, 'Number of moulds', 'The number of pressing moulds contained within a single piece of the referenced tooling.'),
+(1, 't', 1376, 'Concurrent item output of tooling', 'The number of related items which can be produced simultaneously with a single piece of the referenced tooling.'),
+(1, 't', 1377, 'Periodic capacity of tooling', 'Maximum production output of the referenced tool over a period of time.'),
+(1, 't', 1378, 'Lifetime capacity of tooling', 'Maximum production output of the referenced tool over its productive lifetime.'),
+(1, 't', 1379, 'Number of deliveries per despatch period', 'The number of deliveries normally expected to be despatched within each despatch period.'),
+(1, 't', 1380, 'Provided quantity', 'The quantity of a referenced component supplied by the buyer for manufacturing of an ordered item.'),
+(1, 't', 1381, 'Maximum production batch', 'The quantity specified is the maximum output from a single production run.'),
+(1, 'f', 1382, 'Cancelled quantity', 'Quantity of the referenced item which has previously been ordered and is now cancelled.'),
+(1, 't', 1383, 'No delivery requirement in this instruction', 'This delivery instruction does not contain any delivery requirements.'),
+(1, 't', 1384, 'Quantity of material in ordered time', 'Quantity of the referenced material within the ordered time.'),
+(1, 'f', 1385, 'Rejected quantity', 'The quantity of received goods rejected for quantity reasons.'),
+(1, 't', 1386, 'Cumulative quantity scheduled up to accumulation start date', 'The cumulative quantity scheduled up to the accumulation start date.'),
+(1, 't', 1387, 'Quantity scheduled', 'The quantity scheduled for delivery.'),
+(1, 't', 1388, 'Number of identical handling units', 'Number of identical handling units in terms of type and contents.'),
+(1, 't', 1389, 'Number of packages in handling unit', 'The number of packages contained in one handling unit.'),
+(1, 't', 1390, 'Despatch note quantity', 'The item quantity specified on the despatch note.'),
+(1, 't', 1391, 'Adjustment to inventory quantity', 'An adjustment to inventory quantity.'),
+(1, 't', 1392, 'Free goods quantity',    'Quantity of goods which are free of charge.'),
+(1, 't', 1393, 'Free quantity included', 'Quantity included to which no charge is applicable.'),
+(1, 't', 1394, 'Received and accepted',  'Quantity which has been received and accepted at a given location.'),
+(1, 'f', 1395, 'Received, not accepted, to be returned',  'Quantity which has been received but not accepted at a given location and which will consequently be returned to the relevant party.'),
+(1, 'f', 1396, 'Received, not accepted, to be destroyed', 'Quantity which has been received but not accepted at a given location and which will consequently be destroyed.'),
+(1, 't', 1397, 'Reordering level', 'Quantity at which an order may be triggered to replenish.'),
+(1, 't', 1399, 'Inventory withdrawal quantity', 'Quantity which has been withdrawn from inventory since the last inventory report.'),
+(1, 't', 1400, 'Free quantity not included', 'Free quantity not included in ordered quantity.'),
+(1, 't', 1401, 'Recommended overhaul and repair quantity', 'To indicate the recommended quantity of an article required to support overhaul and repair activities.'),
+(1, 't', 1402, 'Quantity per next higher assembly', 'To indicate the quantity required for the next higher assembly.'),
+(1, 't', 1403, 'Quantity per unit of issue', 'Provides the standard quantity of an article in which one unit can be issued.'),
+(1, 't', 1404, 'Cumulative scrap quantity',  'Provides the cumulative quantity of an item which has been identified as scrapped.'),
+(1, 't', 1405, 'Publication turn size', 'The quantity of magazines or newspapers grouped together with the spine facing alternate directions in a bundle.'),
+(1, 't', 1406, 'Recommended maintenance quantity', 'Recommended quantity of an article which is required to meet an agreed level of maintenance.'),
+(1, 't', 1407, 'Labour hours', 'Number of labour hours.'),
+(1, 't', 1408, 'Quantity requirement for maintenance and repair of', 'equipment Quantity of the material needed to maintain and repair equipment.'),
+(1, 't', 1409, 'Additional replenishment demand quantity', 'Incremental needs over and above normal replenishment calculations, but not intended to permanently change the model parameters.'),
+(1, 't', 1410, 'Returned by consumer quantity', 'Quantity returned by a consumer.'),
+(1, 't', 1411, 'Replenishment override quantity', 'Quantity to override the normal replenishment model calculations, but not intended to permanently change the model parameters.'),
+(1, 't', 1412, 'Quantity sold, net', 'Net quantity sold which includes returns of saleable inventory and other adjustments.'),
+(1, 't', 1413, 'Transferred out quantity',   'Quantity which was transferred out of this location.'),
+(1, 't', 1414, 'Transferred in quantity',    'Quantity which was transferred into this location.'),
+(1, 't', 1415, 'Unsaleable quantity',        'Quantity of inventory received which cannot be sold in its present condition.'),
+(1, 't', 1416, 'Consumer reserved quantity', 'Quantity reserved for consumer delivery or pickup and not yet withdrawn from inventory.'),
+(1, 't', 1417, 'Out of inventory quantity',  'Quantity of inventory which was requested but was not available.'),
+(1, 't', 1418, 'Quantity returned, defective or damaged', 'Quantity returned in a damaged or defective condition.'),
+(1, 't', 1419, 'Taxable quantity',           'Quantity subject to taxation.'),
+(1, 't', 1420, 'Meter reading', 'The numeric value of measure units counted by a meter.'),
+(1, 't', 1421, 'Maximum requestable quantity', 'The maximum quantity which may be requested.'),
+(1, 't', 1422, 'Minimum requestable quantity', 'The minimum quantity which may be requested.'),
+(1, 't', 1423, 'Daily average quantity', 'The quantity for a defined period divided by the number of days of the period.'),
+(1, 't', 1424, 'Budgeted hours',     'The number of budgeted hours.'),
+(1, 't', 1425, 'Actual hours',       'The number of actual hours.'),
+(1, 't', 1426, 'Earned value hours', 'The number of earned value hours.'),
+(1, 't', 1427, 'Estimated hours',    'The number of estimated hours.'),
+(1, 't', 1428, 'Level resource task quantity', 'Quantity of a resource that is level for the duration of the task.'),
+(1, 't', 1429, 'Available resource task quantity', 'Quantity of a resource available to complete a task.'),
+(1, 't', 1430, 'Work time units',   'Quantity of work units of time.'),
+(1, 't', 1431, 'Daily work shifts', 'Quantity of work shifts per day.'),
+(1, 't', 1432, 'Work time units per shift', 'Work units of time per work shift.'),
+(1, 't', 1433, 'Work calendar units',       'Work calendar units of time.'),
+(1, 't', 1434, 'Elapsed duration',   'Quantity representing the elapsed duration.'),
+(1, 't', 1435, 'Remaining duration', 'Quantity representing the remaining duration.'),
+(1, 't', 1436, 'Original duration',  'Quantity representing the original duration.'),
+(1, 't', 1437, 'Current duration',   'Quantity representing the current duration.'),
+(1, 't', 1438, 'Total float time',   'Quantity representing the total float time.'),
+(1, 't', 1439, 'Free float time',    'Quantity representing the free float time.'),
+(1, 't', 1440, 'Lag time',           'Quantity representing lag time.'),
+(1, 't', 1441, 'Lead time',          'Quantity representing lead time.'),
+(1, 't', 1442, 'Number of months', 'The number of months.'),
+(1, 't', 1443, 'Reserved quantity customer direct delivery sales', 'Quantity of products reserved for sales delivered direct to the customer.'),
+(1, 't', 1444, 'Reserved quantity retail sales', 'Quantity of products reserved for retail sales.'),
+(1, 't', 1445, 'Consolidated discount inventory', 'A quantity of inventory supplied at consolidated discount terms.'),
+(1, 't', 1446, 'Returns replacement quantity',    'A quantity of goods issued as a replacement for a returned quantity.'),
+(1, 't', 1447, 'Additional promotion sales forecast quantity', 'A forecast of additional quantity which will be sold during a period of promotional activity.'),
+(1, 't', 1448, 'Reserved quantity', 'Quantity reserved for specific purposes.'),
+(1, 't', 1449, 'Quantity displayed not available for sale', 'Quantity displayed within a retail outlet but not available for sale.'),
+(1, 't', 1450, 'Inventory discrepancy', 'The difference recorded between theoretical and physical inventory.'),
+(1, 't', 1451, 'Incremental order quantity', 'The incremental quantity by which ordering is carried out.'),
+(1, 't', 1452, 'Quantity requiring manipulation before despatch', 'A quantity of goods which needs manipulation before despatch.'),
+(1, 't', 1453, 'Quantity in quarantine',              'A quantity of goods which are held in a restricted area for quarantine purposes.'),
+(1, 't', 1454, 'Quantity withheld by owner of goods', 'A quantity of goods which has been withheld by the owner of the goods.'),
+(1, 't', 1455, 'Quantity not available for despatch', 'A quantity of goods not available for despatch.'),
+(1, 't', 1456, 'Quantity awaiting delivery', 'Quantity of goods which are awaiting delivery.'),
+(1, 't', 1457, 'Quantity in physical inventory',      'A quantity of goods held in physical inventory.'),
+(1, 't', 1458, 'Quantity held by logistic service provider', 'Quantity of goods under the control of a logistic service provider.'),
+(1, 't', 1459, 'Optimal quantity', 'The optimal quantity for a given purpose.'),
+(1, 't', 1460, 'Delivery quantity balance', 'The difference between the scheduled quantity and the quantity delivered to the consignee at a given date.'),
+(1, 't', 1461, 'Cumulative quantity shipped', 'Cumulative quantity of all shipments.'),
+(1, 't', 1462, 'Quantity suspended', 'The quantity of something which is suspended.'),
+(1, 't', 1463, 'Control quantity', 'The quantity designated for control purposes.'),
+(1, 't', 1464, 'Equipment quantity', 'A count of a quantity of equipment.'),
+(1, 't', 1465, 'Factor', 'Number by which the measured unit has to be multiplied to calculate the units used.'),
+(1, 't', 1466, 'Unsold quantity held by wholesaler', 'Unsold quantity held by the wholesaler.'),
+(1, 't', 1467, 'Quantity held by delivery vehicle', 'Quantity of goods held by the delivery vehicle.'),
+(1, 't', 1468, 'Quantity held by retail outlet', 'Quantity held by the retail outlet.'),
+(1, 'f', 1469, 'Rejected return quantity', 'A quantity for return which has been rejected.'),
+(1, 't', 1470, 'Accounts', 'The number of accounts.'),
+(1, 't', 1471, 'Accounts placed for collection', 'The number of accounts placed for collection.'),
+(1, 't', 1472, 'Activity codes', 'The number of activity codes.'),
+(1, 't', 1473, 'Agents', 'The number of agents.'),
+(1, 't', 1474, 'Airline attendants', 'The number of airline attendants.'),
+(1, 't', 1475, 'Authorised shares',  'The number of shares authorised for issue.'),
+(1, 't', 1476, 'Employee average',   'The average number of employees.'),
+(1, 't', 1477, 'Branch locations',   'The number of branch locations.'),
+(1, 't', 1478, 'Capital changes',    'The number of capital changes made.'),
+(1, 't', 1479, 'Clerks', 'The number of clerks.'),
+(1, 't', 1480, 'Companies in same activity', 'The number of companies doing business in the same activity category.'),
+(1, 't', 1481, 'Companies included in consolidated financial statement', 'The number of companies included in a consolidated financial statement.'),
+(1, 't', 1482, 'Cooperative shares', 'The number of cooperative shares.'),
+(1, 't', 1483, 'Creditors',   'The number of creditors.'),
+(1, 't', 1484, 'Departments', 'The number of departments.'),
+(1, 't', 1485, 'Design employees', 'The number of employees involved in the design process.'),
+(1, 't', 1486, 'Physicians', 'The number of medical doctors.'),
+(1, 't', 1487, 'Domestic affiliated companies', 'The number of affiliated companies located within the country.'),
+(1, 't', 1488, 'Drivers', 'The number of drivers.'),
+(1, 't', 1489, 'Employed at location',     'The number of employees at the specified location.'),
+(1, 't', 1490, 'Employed by this company', 'The number of employees at the specified company.'),
+(1, 't', 1491, 'Total employees',    'The total number of employees.'),
+(1, 't', 1492, 'Employees shared',   'The number of employees shared among entities.'),
+(1, 't', 1493, 'Engineers',          'The number of engineers.'),
+(1, 't', 1494, 'Estimated accounts', 'The estimated number of accounts.'),
+(1, 't', 1495, 'Estimated employees at location', 'The estimated number of employees at the specified location.'),
+(1, 't', 1496, 'Estimated total employees',       'The total estimated number of employees.'),
+(1, 't', 1497, 'Executives', 'The number of executives.'),
+(1, 't', 1498, 'Agricultural workers',   'The number of agricultural workers.'),
+(1, 't', 1499, 'Financial institutions', 'The number of financial institutions.'),
+(1, 't', 1500, 'Floors occupied', 'The number of floors occupied.'),
+(1, 't', 1501, 'Foreign related entities', 'The number of related entities located outside the country.'),
+(1, 't', 1502, 'Group employees',    'The number of employees within the group.'),
+(1, 't', 1503, 'Indirect employees', 'The number of employees not associated with direct production.'),
+(1, 't', 1504, 'Installers',    'The number of employees involved with the installation process.'),
+(1, 't', 1505, 'Invoices',      'The number of invoices.'),
+(1, 't', 1506, 'Issued shares', 'The number of shares actually issued.'),
+(1, 't', 1507, 'Labourers',     'The number of labourers.'),
+(1, 't', 1508, 'Manufactured units', 'The number of units manufactured.'),
+(1, 't', 1509, 'Maximum number of employees', 'The maximum number of people employed.'),
+(1, 't', 1510, 'Maximum number of employees at location', 'The maximum number of people employed at a location.'),
+(1, 't', 1511, 'Members in group', 'The number of members within a group.'),
+(1, 't', 1512, 'Minimum number of employees at location', 'The minimum number of people employed at a location.'),
+(1, 't', 1513, 'Minimum number of employees', 'The minimum number of people employed.'),
+(1, 't', 1514, 'Non-union employees', 'The number of employees not belonging to a labour union.'),
+(1, 't', 1515, 'Floors', 'The number of floors in a building.'),
+(1, 't', 1516, 'Nurses', 'The number of nurses.'),
+(1, 't', 1517, 'Office workers', 'The number of workers in an office.'),
+(1, 't', 1518, 'Other employees', 'The number of employees otherwise categorised.'),
+(1, 't', 1519, 'Part time employees', 'The number of employees working on a part time basis.'),
+(1, 't', 1520, 'Accounts payable average overdue days', 'The average number of days accounts payable are overdue.'),
+(1, 't', 1521, 'Pilots', 'The number of pilots.'),
+(1, 't', 1522, 'Plant workers', 'The number of workers within a plant.'),
+(1, 't', 1523, 'Previous number of accounts', 'The number of accounts which preceded the current count.'),
+(1, 't', 1524, 'Previous number of branch locations', 'The number of branch locations which preceded the current count.'),
+(1, 't', 1525, 'Principals included as employees', 'The number of principals which are included in the count of employees.'),
+(1, 't', 1526, 'Protested bills', 'The number of bills which are protested.'),
+(1, 't', 1527, 'Registered brands distributed', 'The number of registered brands which are being distributed.'),
+(1, 't', 1528, 'Registered brands manufactured', 'The number of registered brands which are being manufactured.'),
+(1, 't', 1529, 'Related business entities', 'The number of related business entities.'),
+(1, 't', 1530, 'Relatives employed', 'The number of relatives which are counted as employees.'),
+(1, 't', 1531, 'Rooms',        'The number of rooms.'),
+(1, 't', 1532, 'Salespersons', 'The number of salespersons.'),
+(1, 't', 1533, 'Seats',        'The number of seats.'),
+(1, 't', 1534, 'Shareholders', 'The number of shareholders.'),
+(1, 't', 1535, 'Shares of common stock', 'The number of shares of common stock.'),
+(1, 't', 1536, 'Shares of preferred stock', 'The number of shares of preferred stock.'),
+(1, 't', 1537, 'Silent partners', 'The number of silent partners.'),
+(1, 't', 1538, 'Subcontractors',  'The number of subcontractors.'),
+(1, 't', 1539, 'Subsidiaries',    'The number of subsidiaries.'),
+(1, 't', 1540, 'Law suits',       'The number of law suits.'),
+(1, 't', 1541, 'Suppliers',       'The number of suppliers.'),
+(1, 't', 1542, 'Teachers',        'The number of teachers.'),
+(1, 't', 1543, 'Technicians',     'The number of technicians.'),
+(1, 't', 1544, 'Trainees',        'The number of trainees.'),
+(1, 't', 1545, 'Union employees', 'The number of employees who are members of a labour union.'),
+(1, 't', 1546, 'Number of units', 'The quantity of units.'),
+(1, 't', 1547, 'Warehouse employees', 'The number of employees who work in a warehouse setting.'),
+(1, 't', 1548, 'Shareholders holding remainder of shares', 'Number of shareholders owning the remainder of shares.'),
+(1, 't', 1549, 'Payment orders filed', 'Number of payment orders filed.'),
+(1, 't', 1550, 'Uncovered cheques', 'Number of uncovered cheques.'),
+(1, 't', 1551, 'Auctions', 'Number of auctions.'),
+(1, 't', 1552, 'Units produced', 'The number of units produced.'),
+(1, 't', 1553, 'Added employees', 'Number of employees that were added to the workforce.'),
+(1, 't', 1554, 'Number of added locations', 'Number of locations that were added.'),
+(1, 't', 1555, 'Total number of foreign subsidiaries not included in', 'financial statement The total number of foreign subsidiaries not included in the financial statement.'),
+(1, 't', 1556, 'Number of closed locations', 'Number of locations that were closed.'),
+(1, 't', 1557, 'Counter clerks', 'The number of clerks that work behind a flat-topped fitment.'),
+(1, 't', 1558, 'Payment experiences in the last 3 months', 'The number of payment experiences received for an entity over the last 3 months.'),
+(1, 't', 1559, 'Payment experiences in the last 12 months', 'The number of payment experiences received for an entity over the last 12 months.'),
+(1, 't', 1560, 'Total number of subsidiaries not included in the financial', 'statement The total number of subsidiaries not included in the financial statement.'),
+(1, 't', 1561, 'Paid-in common shares', 'The number of paid-in common shares.'),
+(1, 't', 1562, 'Total number of domestic subsidiaries not included in', 'financial statement The total number of domestic subsidiaries not included in the financial statement.'),
+(1, 't', 1563, 'Total number of foreign subsidiaries included in financial statement', 'The total number of foreign subsidiaries included in the financial statement.'),
+(1, 't', 1564, 'Total number of domestic subsidiaries included in financial statement', 'The total number of domestic subsidiaries included in the financial statement.'),
+(1, 't', 1565, 'Total transactions', 'The total number of transactions.'),
+(1, 't', 1566, 'Paid-in preferred shares', 'The number of paid-in preferred shares.'),
+(1, 't', 1567, 'Employees', 'Code specifying the quantity of persons working for a company, whose services are used for pay.'),
+(1, 't', 1568, 'Active ingredient dose per unit, dispensed', 'The dosage of active ingredient per dispensed unit.'),
+(1, 't', 1569, 'Budget', 'Budget quantity.'),
+(1, 't', 1570, 'Budget, cumulative to date', 'Budget quantity, cumulative to date.'),
+(1, 't', 1571, 'Actual units', 'The number of actual units.'),
+(1, 't', 1572, 'Actual units, cumulative to date', 'The number of cumulative to date actual units.'),
+(1, 't', 1573, 'Earned value', 'Earned value quantity.'),
+(1, 't', 1574, 'Earned value, cumulative to date', 'Earned value quantity accumulated to date.'),
+(1, 't', 1575, 'At completion quantity, estimated', 'The estimated quantity when a project is complete.'),
+(1, 't', 1576, 'To complete quantity, estimated', 'The estimated quantity required to complete a project.'),
+(1, 't', 1577, 'Adjusted units', 'The number of adjusted units.'),
+(1, 't', 1578, 'Number of limited partnership shares', 'Number of shares held in a limited partnership.'),
+(1, 't', 1579, 'National business failure incidences', 'Number of firms in a country that discontinued with a loss to creditors.'),
+(1, 't', 1580, 'Industry business failure incidences', 'Number of firms in a specific industry that discontinued with a loss to creditors.'),
+(1, 't', 1581, 'Business class failure incidences', 'Number of firms in a specific class that discontinued with a loss to creditors.'),
+(1, 't', 1582, 'Mechanics', 'Number of mechanics.'),
+(1, 't', 1583, 'Messengers', 'Number of messengers.'),
+(1, 't', 1584, 'Primary managers', 'Number of primary managers.'),
+(1, 't', 1585, 'Secretaries', 'Number of secretaries.'),
+(1, 't', 1586, 'Detrimental legal filings', 'Number of detrimental legal filings.'),
+(1, 't', 1587, 'Branch office locations, estimated', 'Estimated number of branch office locations.'),
+(1, 't', 1588, 'Previous number of employees', 'The number of employees for a previous period.'),
+(1, 't', 1589, 'Asset seizers', 'Number of entities that seize assets of another entity.'),
+(1, 't', 1590, 'Out-turned quantity', 'The quantity discharged.'),
+(1, 't', 1591, 'Material on-board quantity, prior to loading', 'The material in vessel tanks, void spaces, and pipelines prior to loading.'),
+(1, 't', 1592, 'Supplier estimated previous meter reading', 'Previous meter reading estimated by the supplier.'),
+(1, 't', 1593, 'Supplier estimated latest meter reading',   'Latest meter reading estimated by the supplier.'),
+(1, 't', 1594, 'Customer estimated previous meter reading', 'Previous meter reading estimated by the customer.'),
+(1, 't', 1595, 'Customer estimated latest meter reading',   'Latest meter reading estimated by the customer.'),
+(1, 't', 1596, 'Supplier previous meter reading',           'Previous meter reading done by the supplier.'),
+(1, 't', 1597, 'Supplier latest meter reading',             'Latest meter reading recorded by the supplier.'),
+(1, 't', 1598, 'Maximum number of purchase orders allowed', 'Maximum number of purchase orders that are allowed.'),
+(1, 't', 1599, 'File size before compression', 'The size of a file before compression.'),
+(1, 't', 1600, 'File size after compression', 'The size of a file after compression.'),
+(1, 't', 1601, 'Securities shares', 'Number of shares of securities.'),
+(1, 't', 1602, 'Patients',         'Number of patients.'),
+(1, 't', 1603, 'Completed projects', 'Number of completed projects.'),
+(1, 't', 1604, 'Promoters',        'Number of entities who finance or organize an event or a production.'),
+(1, 't', 1605, 'Administrators',   'Number of administrators.'),
+(1, 't', 1606, 'Supervisors',      'Number of supervisors.'),
+(1, 't', 1607, 'Professionals',    'Number of professionals.'),
+(1, 't', 1608, 'Debt collectors',  'Number of debt collectors.'),
+(1, 't', 1609, 'Inspectors',       'Number of individuals who perform inspections.'),
+(1, 't', 1610, 'Operators',        'Number of operators.'),
+(1, 't', 1611, 'Trainers',         'Number of trainers.'),
+(1, 't', 1612, 'Active accounts',  'Number of accounts in a current or active status.'),
+(1, 't', 1613, 'Trademarks used',  'Number of trademarks used.'),
+(1, 't', 1614, 'Machines',         'Number of machines.'),
+(1, 't', 1615, 'Fuel pumps',       'Number of fuel pumps.'),
+(1, 't', 1616, 'Tables available', 'Number of tables available for use.'),
+(1, 't', 1617, 'Directors',        'Number of directors.'),
+(1, 't', 1618, 'Freelance debt collectors', 'Number of debt collectors who work on a freelance basis.'),
+(1, 't', 1619, 'Freelance salespersons',    'Number of salespersons who work on a freelance basis.'),
+(1, 't', 1620, 'Travelling employees',      'Number of travelling employees.'),
+(1, 't', 1621, 'Foremen', 'Number of workers with limited supervisory responsibilities.'),
+(1, 't', 1622, 'Production workers', 'Number of employees engaged in production.'),
+(1, 't', 1623, 'Employees not including owners', 'Number of employees excluding business owners.'),
+(1, 't', 1624, 'Beds', 'Number of beds.'),
+(1, 't', 1625, 'Resting quantity', 'A quantity of product that is at rest before it can be used.'),
+(1, 't', 1626, 'Production requirements', 'Quantity needed to meet production requirements.'),
+(1, 't', 1627, 'Corrected quantity', 'The quantity has been corrected.'),
+(1, 't', 1628, 'Operating divisions', 'Number of divisions operating.'),
+(1, 't', 1629, 'Quantitative incentive scheme base', 'Quantity constituting the base for the quantitative incentive scheme.'),
+(1, 't', 1630, 'Petitions filed', 'Number of petitions that have been filed.'),
+(1, 't', 1631, 'Bankruptcy petitions filed', 'Number of bankruptcy petitions that have been filed.'),
+(1, 't', 1632, 'Projects in process', 'Number of projects in process.'),
+(1, 't', 1633, 'Changes in capital structure', 'Number of modifications made to the capital structure of an entity.'),
+(1, 't', 1634, 'Detrimental legal filings against directors', 'The number of legal filings that are of a detrimental nature that have been filed against the directors.'),
+(1, 't', 1635, 'Number of failed businesses of directors', 'The number of failed businesses with which the directors have been associated.'),
+(1, 't', 1636, 'Professor', 'The number of professors.'),
+(1, 't', 1637, 'Seller',    'The number of sellers.'),
+(1, 't', 1638, 'Skilled worker', 'The number of skilled workers.'),
+(1, 't', 1639, 'Trademark represented', 'The number of trademarks represented.'),
+(1, 't', 1640, 'Number of quantitative incentive scheme units', 'Number of units allocated to a quantitative incentive scheme.'),
+(1, 't', 1641, 'Quantity in manufacturing process', 'Quantity currently in the manufacturing process.'),
+(1, 't', 1642, 'Number of units in the width of a layer', 'Number of units which make up the width of a layer.'),
+(1, 't', 1643, 'Number of units in the depth of a layer', 'Number of units which make up the depth of a layer.'),
+(1, 't', 1644, 'Return to warehouse', 'A quantity of products sent back to the warehouse.'),
+(1, 't', 1645, 'Return to the manufacturer', 'A quantity of products sent back from the manufacturer.'),
+(1, 't', 1646, 'Delta quantity', 'An increment or decrement to a quantity.'),
+(1, 't', 1647, 'Quantity moved between outlets', 'A quantity of products moved between outlets.'),
+(1, 't', 1648, 'Pre-paid invoice annual consumption, estimated', 'The estimated annual consumption used for a prepayment invoice.'),
+(1, 't', 1649, 'Total quoted quantity', 'The sum of quoted quantities.'),
+(1, 't', 1650, 'Requests pertaining to entity in last 12 months', 'Number of requests received in last 12 months pertaining to the entity.'),
+(1, 't', 1651, 'Total inquiry matches', 'Number of instances which correspond with the inquiry.'),
+(1, 't', 1652, 'En route to warehouse quantity',   'A quantity of products that is en route to a warehouse.'),
+(1, 't', 1653, 'En route from warehouse quantity', 'A quantity of products that is en route from a warehouse.'),
+(1, 't', 1654, 'Quantity ordered but not yet allocated from stock', 'A quantity of products which has been ordered but which has not yet been allocated from stock.'),
+(1, 't', 1655, 'Not yet ordered quantity', 'The quantity which has not yet been ordered.'),
+(1, 't', 1656, 'Net reserve power', 'The reserve power available for the net.'),
+(1, 't', 1657, 'Maximum number of units per shelf', 'Maximum number of units of a product that can be placed on a shelf.'),
+(1, 't', 1658, 'Stowaway', 'Number of stowaway(s) on a conveyance.'),
+(1, 't', 1659, 'Tug', 'The number of tugboat(s).'),
+(1, 't', 1660, 'Maximum quantity capability of the package', 'Maximum quantity of a product that can be contained in a package.'),
+(1, 't', 1661, 'Calculated', 'The calculated quantity.'),
+(1, 't', 1662, 'Monthly volume, estimated', 'Volume estimated for a month.'),
+(1, 't', 1663, 'Total number of persons', 'Quantity representing the total number of persons.'),
+(1, 't', 1664, 'Tariff Quantity', 'Quantity of the goods in the unit as required by Customs for duty/tax/fee assessment. These quantities may also be used for other fiscal or statistical purposes.'),
+(1, 't', 1665, 'Deducted tariff quantity',   'Quantity deducted from tariff quantity to reckon duty/tax/fee assessment bases.'),
+(1, 't', 1666, 'Advised but not arrived',    'Goods are advised by the consignor or supplier, but have not yet arrived at the destination.'),
+(1, 't', 1667, 'Received but not available', 'Goods have been received in the arrival area but are not yet available.'),
+(1, 't', 1668, 'Goods blocked for transshipment process', 'Goods are physically present, but can not be ordered because they are scheduled for a transshipment process.'),
+(1, 't', 1669, 'Goods blocked for cross docking process', 'Goods are physically present, but can not be ordered because they are scheduled for a cross docking process.'),
+(1, 't', 1670, 'Chargeable number of trailers', 'The number of trailers on which charges are based.'),
+(1, 't', 1671, 'Number of packages for a set', 'Number of packages used to pack the individual items in a grouping of merchandise that is sold together as a single trade item.'),
+(1, 't', 1672, 'Number of items in a set', 'The number of individual items in a grouping of merchandise that is sold together as a single trade item.'),
+(1, 't', 1673, 'Order sizing factor', 'A trade item specification other than gross, net weight, or volume for a trade item or a transaction, used for order sizing and pricing purposes.'),
+(1, 't', 1674, 'Number of different next lower level trade items', 'Value indicates the number of differrent next lower level trade items contained in a complex trade item.'),
+(1, 't', 1675, 'Agreed maximum buying quantity', 'The agreed maximum quantity of the trade item that may be purchased.'),
+(1, 't', 1676, 'Agreed minimum buying quantity', 'The agreed minimum quantity of the trade item that may be purchased.'),
+(1, 't', 1677, 'Free quantity of next lower level trade item', 'The numeric quantity of free items in a combination pack. The unit of measure used for the free quantity of the next lower level must be the same as the unit of measure of the Net Content of the Child Trade Item.'),
+(1, 't', 1678, 'Marine Diesel Oil bunkers on board, on arrival',     'Number of Marine Diesel Oil (MDO) bunkers on board when the vessel arrives in the port.'),
+(1, 't', 1679, 'Marine Diesel Oil bunkers, loaded',                  'Number of Marine Diesel Oil (MDO) bunkers taken on in the port.'),
+(1, 't', 1680, 'Intermediate Fuel Oil bunkers on board, on arrival', 'Number of Intermediate Fuel Oil (IFO) bunkers on board when the vessel arrives in the port.'),
+(1, 't', 1681, 'Intermediate Fuel Oil bunkers, loaded',              'Number of Intermediate Fuel Oil (IFO) bunkers taken on in the port.'),
+(1, 't', 1682, 'Bunker C bunkers on board, on arrival',              'Number of Bunker C, or Number 6 fuel oil bunkers on board when the vessel arrives in the port.'),
+(1, 't', 1683, 'Bunker C bunkers, loaded', 'Number of Bunker C, or Number 6 fuel oil bunkers, taken on in the port.'),
+(1, 't', 1684, 'Number of individual units within the smallest packaging', 'unit Total number of individual units contained within the smallest unit of packaging.'),
+(1, 't', 1685, 'Percentage of constituent element', 'The part of a product or material that is composed of the constituent element, as a percentage.'),
+(1, 't', 1686, 'Quantity to be decremented (LPCO)', 'Quantity to be decremented from the allowable quantity on a License, Permit, Certificate, or Other document (LPCO).'),
+(1, 't', 1687, 'Regulated commodity count', 'The number of regulated items.'),
+(1, 't', 1688, 'Number of passengers, embarking', 'The number of passengers going aboard a conveyance.'),
+(1, 't', 1689, 'Number of passengers, disembarking', 'The number of passengers disembarking the conveyance.'),
+(1, 't', 1690, 'Constituent element or component quantity', 'The specific quantity of the identified constituent element.')
+;
+-- ZZZ, 'Mutually defined', 'As agreed by the trading partners.'),
+
+CREATE TABLE acq.serial_claim (
+    id     SERIAL           PRIMARY KEY,
+    type   INT              NOT NULL REFERENCES acq.claim_type
+                                     DEFERRABLE INITIALLY DEFERRED,
+    item    BIGINT          NOT NULL REFERENCES serial.item
+                                     DEFERRABLE INITIALLY DEFERRED
+);
+
+CREATE INDEX serial_claim_lid_idx ON acq.serial_claim( item );
+
+CREATE TABLE acq.serial_claim_event (
+    id             BIGSERIAL        PRIMARY KEY,
+    type           INT              NOT NULL REFERENCES acq.claim_event_type
+                                             DEFERRABLE INITIALLY DEFERRED,
+    claim          SERIAL           NOT NULL REFERENCES acq.serial_claim
+                                             DEFERRABLE INITIALLY DEFERRED,
+    event_date     TIMESTAMPTZ      NOT NULL DEFAULT now(),
+    creator        INT              NOT NULL REFERENCES actor.usr
+                                             DEFERRABLE INITIALLY DEFERRED,
+    note           TEXT
+);
+
+CREATE INDEX serial_claim_event_claim_date_idx ON acq.serial_claim_event( claim, event_date );
+
+ALTER TABLE asset.stat_cat ADD COLUMN required BOOL NOT NULL DEFAULT FALSE;
+
+-- now what about the auditor.*_lifecycle views??
+
+INSERT INTO config.metabib_field ( id, field_class, name, label, format, xpath ) VALUES
+    (26, 'identifier', 'tcn', oils_i18n_gettext(26, 'Title Control Number', 'cmf', 'label'), 'marcxml', $$//marc:datafield[@tag='901']/marc:subfield[@code='a']$$ );
+INSERT INTO config.metabib_field ( id, field_class, name, label, format, xpath ) VALUES
+    (27, 'identifier', 'bibid', oils_i18n_gettext(27, 'Internal ID', 'cmf', 'label'), 'marcxml', $$//marc:datafield[@tag='901']/marc:subfield[@code='c']$$ );
+INSERT INTO config.metabib_search_alias (alias,field_class,field) VALUES ('eg.tcn','identifier', 26);
+INSERT INTO config.metabib_search_alias (alias,field_class,field) VALUES ('eg.bibid','identifier', 27);
+
+CREATE TABLE asset.call_number_class (
+    id             bigserial     PRIMARY KEY,
+    name           TEXT          NOT NULL,
+    normalizer     TEXT          NOT NULL DEFAULT 'asset.normalize_generic',
+    field          TEXT          NOT NULL DEFAULT '050ab,055ab,060ab,070ab,080ab,082ab,086ab,088ab,090,092,096,098,099'
+);
+
+COMMENT ON TABLE asset.call_number_class IS $$
+Defines the call number normalization database functions in the "normalizer"
+column and the tag/subfield combinations to use to lookup the call number in
+the "field" column for a given classification scheme. Tag/subfield combinations
+are delimited by commas.
+$$;
+
+INSERT INTO asset.call_number_class (name, normalizer) VALUES 
+    ('Generic', 'asset.label_normalizer_generic'),
+    ('Dewey (DDC)', 'asset.label_normalizer_dewey'),
+    ('Library of Congress (LC)', 'asset.label_normalizer_lc')
+;
+
+-- Generic fields
+UPDATE asset.call_number_class
+    SET field = '050ab,055ab,060ab,070ab,080ab,082ab,086ab,088ab,090,092,096,098,099'
+    WHERE id = 1
+;
+
+-- Dewey fields
+UPDATE asset.call_number_class
+    SET field = '080ab,082ab'
+    WHERE id = 2
+;
+
+-- LC fields
+UPDATE asset.call_number_class
+    SET field = '050ab,055ab'
+    WHERE id = 3
+;
+ 
+ALTER TABLE asset.call_number
+	ADD COLUMN label_class BIGINT DEFAULT 1 NOT NULL
+		REFERENCES asset.call_number_class(id)
+		DEFERRABLE INITIALLY DEFERRED;
+
+ALTER TABLE asset.call_number
+	ADD COLUMN label_sortkey TEXT;
+
+CREATE INDEX asset_call_number_label_sortkey
+	ON asset.call_number(label_sortkey);
+
+ALTER TABLE auditor.asset_call_number_history
+	ADD COLUMN label_class BIGINT;
+
+ALTER TABLE auditor.asset_call_number_history
+	ADD COLUMN label_sortkey TEXT;
+
+-- Pick up the new columns in dependent views
+
+DROP VIEW auditor.asset_call_number_lifecycle;
+
+SELECT auditor.create_auditor_lifecycle( 'asset', 'call_number' );
+
+DROP VIEW auditor.asset_call_number_lifecycle;
+
+SELECT auditor.create_auditor_lifecycle( 'asset', 'call_number' );
+
+DROP VIEW IF EXISTS stats.fleshed_call_number;
+
+CREATE VIEW stats.fleshed_call_number AS
+        SELECT  cn.*,
+            CAST(cn.create_date AS DATE) AS create_date_day,
+        CAST(cn.edit_date AS DATE) AS edit_date_day,
+        DATE_TRUNC('hour', cn.create_date) AS create_date_hour,
+        DATE_TRUNC('hour', cn.edit_date) AS edit_date_hour,
+            rd.item_lang,
+                rd.item_type,
+                rd.item_form
+        FROM    asset.call_number cn
+                JOIN metabib.rec_descriptor rd ON (rd.record = cn.record);
+
+CREATE OR REPLACE FUNCTION asset.label_normalizer() RETURNS TRIGGER AS $func$
+DECLARE
+    sortkey        TEXT := '';
+BEGIN
+    sortkey := NEW.label_sortkey;
+
+    EXECUTE 'SELECT ' || acnc.normalizer || '(' || 
+       quote_literal( NEW.label ) || ')'
+       FROM asset.call_number_class acnc
+       WHERE acnc.id = NEW.label_class
+       INTO sortkey;
+
+    NEW.label_sortkey = sortkey;
+
+    RETURN NEW;
+END;
+$func$ LANGUAGE PLPGSQL;
+
+CREATE OR REPLACE FUNCTION asset.label_normalizer_generic(TEXT) RETURNS TEXT AS $func$
+    # Created after looking at the Koha C4::ClassSortRoutine::Generic module,
+    # thus could probably be considered a derived work, although nothing was
+    # directly copied - but to err on the safe side of providing attribution:
+    # Copyright (C) 2007 LibLime
+    # Licensed under the GPL v2 or later
+
+    use strict;
+    use warnings;
+
+    # Converts the callnumber to uppercase
+    # Strips spaces from start and end of the call number
+    # Converts anything other than letters, digits, and periods into underscores
+    # Collapses multiple underscores into a single underscore
+    my $callnum = uc(shift);
+    $callnum =~ s/^\s//g;
+    $callnum =~ s/\s$//g;
+    $callnum =~ s/[^A-Z0-9_.]/_/g;
+    $callnum =~ s/_{2,}/_/g;
+
+    return $callnum;
+$func$ LANGUAGE PLPERLU;
+
+CREATE OR REPLACE FUNCTION asset.label_normalizer_dewey(TEXT) RETURNS TEXT AS $func$
+    # Derived from the Koha C4::ClassSortRoutine::Dewey module
+    # Copyright (C) 2007 LibLime
+    # Licensed under the GPL v2 or later
+
+    use strict;
+    use warnings;
+
+    my $init = uc(shift);
+    $init =~ s/^\s+//;
+    $init =~ s/\s+$//;
+    $init =~ s!/!!g;
+    $init =~ s/^([\p{IsAlpha}]+)/$1 /;
+    my @tokens = split /\.|\s+/, $init;
+    my $digit_group_count = 0;
+    for (my $i = 0; $i <= $#tokens; $i++) {
+        if ($tokens[$i] =~ /^\d+$/) {
+            $digit_group_count++;
+            if (2 == $digit_group_count) {
+                $tokens[$i] = sprintf("%-15.15s", $tokens[$i]);
+                $tokens[$i] =~ tr/ /0/;
+            }
+        }
+    }
+    my $key = join("_", @tokens);
+    $key =~ s/[^\p{IsAlnum}_]//g;
+
+    return $key;
+
+$func$ LANGUAGE PLPERLU;
+
+CREATE OR REPLACE FUNCTION asset.label_normalizer_lc(TEXT) RETURNS TEXT AS $func$
+    use strict;
+    use warnings;
+
+    # Library::CallNumber::LC is currently hosted at http://code.google.com/p/library-callnumber-lc/
+    # The author hopes to upload it to CPAN some day, which would make our lives easier
+    use Library::CallNumber::LC;
+
+    my $callnum = Library::CallNumber::LC->new(shift);
+    return $callnum->normalize();
+
+$func$ LANGUAGE PLPERLU;
+
+CREATE OR REPLACE FUNCTION asset.opac_ou_record_copy_count (org INT, record BIGINT) RETURNS TABLE (depth INT, org_unit INT, visible BIGINT, available BIGINT, unshadow BIGINT, transcendant INT) AS $f$
+DECLARE
+    ans RECORD;
+    trans INT;
+BEGIN
+    SELECT 1 INTO trans FROM biblio.record_entry b JOIN config.bib_source src ON (b.source = src.id) WHERE src.transcendant AND b.id = record;
+
+    FOR ans IN SELECT u.id, t.depth FROM actor.org_unit_ancestors(org) AS u JOIN actor.org_unit_type t ON (u.ou_type = t.id) LOOP
+        RETURN QUERY
+        SELECT  ans.depth,
+                ans.id,
+                COUNT( av.id ),
+                SUM( CASE WHEN cp.status IN (0,7,12) THEN 1 ELSE 0 END ),
+                COUNT( av.id ),
+                trans
+          FROM
+                actor.org_unit_descendants(ans.id) d
+                JOIN asset.opac_visible_copies av ON (av.record = record AND av.circ_lib = d.id)
+                JOIN asset.copy cp ON (cp.id = av.id)
+          GROUP BY 1,2,6;
+
+        IF NOT FOUND THEN
+            RETURN QUERY SELECT ans.depth, ans.id, 0::BIGINT, 0::BIGINT, 0::BIGINT, trans;
+        END IF;
+
+    END LOOP;
+
+    RETURN;
+END;
+$f$ LANGUAGE PLPGSQL;
+
+CREATE OR REPLACE FUNCTION asset.opac_lasso_record_copy_count (i_lasso INT, record BIGINT) RETURNS TABLE (depth INT, org_unit INT, visible BIGINT, available BIGINT, unshadow BIGINT, transcendant INT) AS $f$
+DECLARE
+    ans RECORD;
+    trans INT;
+BEGIN
+    SELECT 1 INTO trans FROM biblio.record_entry b JOIN config.bib_source src ON (b.source = src.id) WHERE src.transcendant AND b.id = record;
+
+    FOR ans IN SELECT u.org_unit AS id FROM actor.org_lasso_map AS u WHERE lasso = i_lasso LOOP
+        RETURN QUERY
+        SELECT  -1,
+                ans.id,
+                COUNT( av.id ),
+                SUM( CASE WHEN cp.status IN (0,7,12) THEN 1 ELSE 0 END ),
+                COUNT( av.id ),
+                trans
+          FROM
+                actor.org_unit_descendants(ans.id) d
+                JOIN asset.opac_visible_copies av ON (av.record = record AND av.circ_lib = d.id)
+                JOIN asset.copy cp ON (cp.id = av.id)
+          GROUP BY 1,2,6;
+
+        IF NOT FOUND THEN
+            RETURN QUERY SELECT ans.depth, ans.id, 0::BIGINT, 0::BIGINT, 0::BIGINT, trans;
+        END IF;
+
+    END LOOP;
+
+    RETURN;
+END;
+$f$ LANGUAGE PLPGSQL;
+
+CREATE OR REPLACE FUNCTION asset.staff_ou_record_copy_count (org INT, record BIGINT) RETURNS TABLE (depth INT, org_unit INT, visible BIGINT, available BIGINT, unshadow BIGINT, transcendant INT) AS $f$
+DECLARE
+    ans RECORD;
+    trans INT;
+BEGIN
+    SELECT 1 INTO trans FROM biblio.record_entry b JOIN config.bib_source src ON (b.source = src.id) WHERE src.transcendant AND b.id = record;
+
+    FOR ans IN SELECT u.id, t.depth FROM actor.org_unit_ancestors(org) AS u JOIN actor.org_unit_type t ON (u.ou_type = t.id) LOOP
+        RETURN QUERY
+        SELECT  ans.depth,
+                ans.id,
+                COUNT( cp.id ),
+                SUM( CASE WHEN cp.status IN (0,7,12) THEN 1 ELSE 0 END ),
+                COUNT( cp.id ),
+                trans
+          FROM
+                actor.org_unit_descendants(ans.id) d
+                JOIN asset.copy cp ON (cp.circ_lib = d.id)
+                JOIN asset.call_number cn ON (cn.record = record AND cn.id = cp.call_number)
+          GROUP BY 1,2,6;
+
+        IF NOT FOUND THEN
+            RETURN QUERY SELECT ans.depth, ans.id, 0::BIGINT, 0::BIGINT, 0::BIGINT, trans;
+        END IF;
+
+    END LOOP;
+
+    RETURN;
+END;
+$f$ LANGUAGE PLPGSQL;
+
+CREATE OR REPLACE FUNCTION asset.staff_lasso_record_copy_count (i_lasso INT, record BIGINT) RETURNS TABLE (depth INT, org_unit INT, visible BIGINT, available BIGINT, unshadow BIGINT, transcendant INT) AS $f$
+DECLARE
+    ans RECORD;
+    trans INT;
+BEGIN
+    SELECT 1 INTO trans FROM biblio.record_entry b JOIN config.bib_source src ON (b.source = src.id) WHERE src.transcendant AND b.id = record;
+
+    FOR ans IN SELECT u.org_unit AS id FROM actor.org_lasso_map AS u WHERE lasso = i_lasso LOOP
+        RETURN QUERY
+        SELECT  -1,
+                ans.id,
+                COUNT( cp.id ),
+                SUM( CASE WHEN cp.status IN (0,7,12) THEN 1 ELSE 0 END ),
+                COUNT( cp.id ),
+                trans
+          FROM
+                actor.org_unit_descendants(ans.id) d
+                JOIN asset.copy cp ON (cp.circ_lib = d.id)
+                JOIN asset.call_number cn ON (cn.record = record AND cn.id = cp.call_number)
+          GROUP BY 1,2,6;
+
+        IF NOT FOUND THEN
+            RETURN QUERY SELECT ans.depth, ans.id, 0::BIGINT, 0::BIGINT, 0::BIGINT, trans;
+        END IF;
+
+    END LOOP;
+
+    RETURN;
+END;
+$f$ LANGUAGE PLPGSQL;
+
+CREATE OR REPLACE FUNCTION asset.record_copy_count ( place INT, record BIGINT, staff BOOL) RETURNS TABLE (depth INT, org_unit INT, visible BIGINT, available BIGINT, unshadow BIGINT, transcendant INT) AS $f$
+BEGIN
+    IF staff IS TRUE THEN
+        IF place > 0 THEN
+            RETURN QUERY SELECT * FROM asset.staff_ou_record_copy_count( place, record );
+        ELSE
+            RETURN QUERY SELECT * FROM asset.staff_lasso_record_copy_count( -place, record );
+        END IF;
+    ELSE
+        IF place > 0 THEN
+            RETURN QUERY SELECT * FROM asset.opac_ou_record_copy_count( place, record );
+        ELSE
+            RETURN QUERY SELECT * FROM asset.opac_lasso_record_copy_count( -place, record );
+        END IF;
+    END IF;
+
+    RETURN;
+END;
+$f$ LANGUAGE PLPGSQL;
+
+CREATE OR REPLACE FUNCTION asset.opac_ou_metarecord_copy_count (org INT, record BIGINT) RETURNS TABLE (depth INT, org_unit INT, visible BIGINT, available BIGINT, unshadow BIGINT, transcendant INT) AS $f$
+DECLARE
+    ans RECORD;
+    trans INT;
+BEGIN
+    SELECT 1 INTO trans FROM biblio.record_entry b JOIN config.bib_source src ON (b.source = src.id) WHERE src.transcendant AND b.id = record;
+
+    FOR ans IN SELECT u.id, t.depth FROM actor.org_unit_ancestors(org) AS u JOIN actor.org_unit_type t ON (u.ou_type = t.id) LOOP
+        RETURN QUERY
+        SELECT  ans.depth,
+                ans.id,
+                COUNT( av.id ),
+                SUM( CASE WHEN cp.status IN (0,7,12) THEN 1 ELSE 0 END ),
+                COUNT( av.id ),
+                trans
+          FROM
+                actor.org_unit_descendants(ans.id) d
+                JOIN asset.opac_visible_copies av ON (av.record = record AND av.circ_lib = d.id)
+                JOIN asset.copy cp ON (cp.id = av.id)
+                JOIN metabib.metarecord_source_map m ON (m.source = av.record)
+          GROUP BY 1,2,6;
+
+        IF NOT FOUND THEN
+            RETURN QUERY SELECT ans.depth, ans.id, 0::BIGINT, 0::BIGINT, 0::BIGINT, trans;
+        END IF;
+
+    END LOOP;
+
+    RETURN;
+END;
+$f$ LANGUAGE PLPGSQL;
+
+CREATE OR REPLACE FUNCTION asset.opac_lasso_metarecord_copy_count (i_lasso INT, record BIGINT) RETURNS TABLE (depth INT, org_unit INT, visible BIGINT, available BIGINT, unshadow BIGINT, transcendant INT) AS $f$
+DECLARE
+    ans RECORD;
+    trans INT;
+BEGIN
+    SELECT 1 INTO trans FROM biblio.record_entry b JOIN config.bib_source src ON (b.source = src.id) WHERE src.transcendant AND b.id = record;
+
+    FOR ans IN SELECT u.org_unit AS id FROM actor.org_lasso_map AS u WHERE lasso = i_lasso LOOP
+        RETURN QUERY
+        SELECT  -1,
+                ans.id,
+                COUNT( av.id ),
+                SUM( CASE WHEN cp.status IN (0,7,12) THEN 1 ELSE 0 END ),
+                COUNT( av.id ),
+                trans
+          FROM
+                actor.org_unit_descendants(ans.id) d
+                JOIN asset.opac_visible_copies av ON (av.record = record AND av.circ_lib = d.id)
+                JOIN asset.copy cp ON (cp.id = av.id)
+                JOIN metabib.metarecord_source_map m ON (m.source = av.record)
+          GROUP BY 1,2,6;
+
+        IF NOT FOUND THEN
+            RETURN QUERY SELECT ans.depth, ans.id, 0::BIGINT, 0::BIGINT, 0::BIGINT, trans;
+        END IF;
+
+    END LOOP;
+
+    RETURN;
+END;
+$f$ LANGUAGE PLPGSQL;
+
+CREATE OR REPLACE FUNCTION asset.staff_ou_metarecord_copy_count (org INT, record BIGINT) RETURNS TABLE (depth INT, org_unit INT, visible BIGINT, available BIGINT, unshadow BIGINT, transcendant INT) AS $f$
+DECLARE
+    ans RECORD;
+    trans INT;
+BEGIN
+    SELECT 1 INTO trans FROM biblio.record_entry b JOIN config.bib_source src ON (b.source = src.id) WHERE src.transcendant AND b.id = record;
+
+    FOR ans IN SELECT u.id, t.depth FROM actor.org_unit_ancestors(org) AS u JOIN actor.org_unit_type t ON (u.ou_type = t.id) LOOP
+        RETURN QUERY
+        SELECT  ans.depth,
+                ans.id,
+                COUNT( cp.id ),
+                SUM( CASE WHEN cp.status IN (0,7,12) THEN 1 ELSE 0 END ),
+                COUNT( cp.id ),
+                trans
+          FROM
+                actor.org_unit_descendants(ans.id) d
+                JOIN asset.copy cp ON (cp.circ_lib = d.id)
+                JOIN asset.call_number cn ON (cn.record = record AND cn.id = cp.call_number)
+                JOIN metabib.metarecord_source_map m ON (m.source = cn.record)
+          GROUP BY 1,2,6;
+
+        IF NOT FOUND THEN
+            RETURN QUERY SELECT ans.depth, ans.id, 0::BIGINT, 0::BIGINT, 0::BIGINT, trans;
+        END IF;
+
+    END LOOP;
+
+    RETURN;
+END;
+$f$ LANGUAGE PLPGSQL;
+
+CREATE OR REPLACE FUNCTION asset.staff_lasso_metarecord_copy_count (i_lasso INT, record BIGINT) RETURNS TABLE (depth INT, org_unit INT, visible BIGINT, available BIGINT, unshadow BIGINT, transcendant INT) AS $f$
+DECLARE
+    ans RECORD;
+    trans INT;
+BEGIN
+    SELECT 1 INTO trans FROM biblio.record_entry b JOIN config.bib_source src ON (b.source = src.id) WHERE src.transcendant AND b.id = record;
+
+    FOR ans IN SELECT u.org_unit AS id FROM actor.org_lasso_map AS u WHERE lasso = i_lasso LOOP
+        RETURN QUERY
+        SELECT  -1,
+                ans.id,
+                COUNT( cp.id ),
+                SUM( CASE WHEN cp.status IN (0,7,12) THEN 1 ELSE 0 END ),
+                COUNT( cp.id ),
+                trans
+          FROM
+                actor.org_unit_descendants(ans.id) d
+                JOIN asset.copy cp ON (cp.circ_lib = d.id)
+                JOIN asset.call_number cn ON (cn.record = record AND cn.id = cp.call_number)
+                JOIN metabib.metarecord_source_map m ON (m.source = cn.record)
+          GROUP BY 1,2,6;
+
+        IF NOT FOUND THEN
+            RETURN QUERY SELECT ans.depth, ans.id, 0::BIGINT, 0::BIGINT, 0::BIGINT, trans;
+        END IF;
+
+    END LOOP;
+
+    RETURN;
+END;
+$f$ LANGUAGE PLPGSQL;
+
+CREATE OR REPLACE FUNCTION asset.metarecord_copy_count ( place INT, record BIGINT, staff BOOL) RETURNS TABLE (depth INT, org_unit INT, visible BIGINT, available BIGINT, unshadow BIGINT, transcendant INT) AS $f$
+BEGIN
+    IF staff IS TRUE THEN
+        IF place > 0 THEN
+            RETURN QUERY SELECT * FROM asset.staff_ou_metarecord_copy_count( place, record );
+        ELSE
+            RETURN QUERY SELECT * FROM asset.staff_lasso_metarecord_copy_count( -place, record );
+        END IF;
+    ELSE
+        IF place > 0 THEN
+            RETURN QUERY SELECT * FROM asset.opac_ou_metarecord_copy_count( place, record );
+        ELSE
+            RETURN QUERY SELECT * FROM asset.opac_lasso_metarecord_copy_count( -place, record );
+        END IF;
+    END IF;
+
+    RETURN;
+END;
+$f$ LANGUAGE PLPGSQL;
+
+-- No transaction is required
+
+-- Triggers on the vandelay.queued_*_record tables delete entries from
+-- the associated vandelay.queued_*_record_attr tables based on the record's
+-- ID; create an index on that column to avoid sequential scans for each
+-- queued record that is deleted
+CREATE INDEX queued_bib_record_attr_record_idx ON vandelay.queued_bib_record_attr (record);
+CREATE INDEX queued_authority_record_attr_record_idx ON vandelay.queued_authority_record_attr (record);
+
+-- Avoid sequential scans for queue retrieval operations by providing an
+-- index on the queue column
+CREATE INDEX queued_bib_record_queue_idx ON vandelay.queued_bib_record (queue);
+CREATE INDEX queued_authority_record_queue_idx ON vandelay.queued_authority_record (queue);
+
+-- Start picking up call number label prefixes and suffixes
+-- from asset.copy_location
+ALTER TABLE asset.copy_location ADD COLUMN label_prefix TEXT;
+ALTER TABLE asset.copy_location ADD COLUMN label_suffix TEXT;
+
+DROP VIEW auditor.asset_copy_lifecycle;
+
+SELECT auditor.create_auditor_lifecycle( 'asset', 'copy' );
+
+ALTER TABLE reporter.report RENAME COLUMN recurance TO recurrence;
+
+-- Let's not break existing reports
+UPDATE reporter.template SET data = REGEXP_REPLACE(data, E'^(.*)recuring(.*)$', E'\\1recurring\\2') WHERE data LIKE '%recuring%';
+UPDATE reporter.template SET data = REGEXP_REPLACE(data, E'^(.*)recurance(.*)$', E'\\1recurrence\\2') WHERE data LIKE '%recurance%';
+
+-- Need to recreate this view with DISTINCT calls to ARRAY_ACCUM, thus avoiding duplicated ISBN and ISSN values
+CREATE OR REPLACE VIEW reporter.old_super_simple_record AS
+SELECT  r.id,
+    r.fingerprint,
+    r.quality,
+    r.tcn_source,
+    r.tcn_value,
+    FIRST(title.value) AS title,
+    FIRST(author.value) AS author,
+    ARRAY_TO_STRING(ARRAY_ACCUM( DISTINCT publisher.value), ', ') AS publisher,
+    ARRAY_TO_STRING(ARRAY_ACCUM( DISTINCT SUBSTRING(pubdate.value FROM $$\d+$$) ), ', ') AS pubdate,
+    ARRAY_ACCUM( DISTINCT SUBSTRING(isbn.value FROM $$^\S+$$) ) AS isbn,
+    ARRAY_ACCUM( DISTINCT SUBSTRING(issn.value FROM $$^\S+$$) ) AS issn
+  FROM  biblio.record_entry r
+    LEFT JOIN metabib.full_rec title ON (r.id = title.record AND title.tag = '245' AND title.subfield = 'a')
+    LEFT JOIN metabib.full_rec author ON (r.id = author.record AND author.tag IN ('100','110','111') AND author.subfield = 'a')
+    LEFT JOIN metabib.full_rec publisher ON (r.id = publisher.record AND publisher.tag = '260' AND publisher.subfield = 'b')
+    LEFT JOIN metabib.full_rec pubdate ON (r.id = pubdate.record AND pubdate.tag = '260' AND pubdate.subfield = 'c')
+    LEFT JOIN metabib.full_rec isbn ON (r.id = isbn.record AND isbn.tag IN ('024', '020') AND isbn.subfield IN ('a','z'))
+    LEFT JOIN metabib.full_rec issn ON (r.id = issn.record AND issn.tag = '022' AND issn.subfield = 'a')
+  GROUP BY 1,2,3,4,5;
+
+-- Correct the ISSN array definition for reporter.simple_record
+
+CREATE OR REPLACE VIEW reporter.simple_record AS
+SELECT	r.id,
+	s.metarecord,
+	r.fingerprint,
+	r.quality,
+	r.tcn_source,
+	r.tcn_value,
+	title.value AS title,
+	uniform_title.value AS uniform_title,
+	author.value AS author,
+	publisher.value AS publisher,
+	SUBSTRING(pubdate.value FROM $$\d+$$) AS pubdate,
+	series_title.value AS series_title,
+	series_statement.value AS series_statement,
+	summary.value AS summary,
+	ARRAY_ACCUM( SUBSTRING(isbn.value FROM $$^\S+$$) ) AS isbn,
+	ARRAY_ACCUM( REGEXP_REPLACE(issn.value, E'^\\S*(\\d{4})[-\\s](\\d{3,4}x?)', E'\\1 \\2') ) AS issn,
+	ARRAY((SELECT DISTINCT value FROM metabib.full_rec WHERE tag = '650' AND subfield = 'a' AND record = r.id)) AS topic_subject,
+	ARRAY((SELECT DISTINCT value FROM metabib.full_rec WHERE tag = '651' AND subfield = 'a' AND record = r.id)) AS geographic_subject,
+	ARRAY((SELECT DISTINCT value FROM metabib.full_rec WHERE tag = '655' AND subfield = 'a' AND record = r.id)) AS genre,
+	ARRAY((SELECT DISTINCT value FROM metabib.full_rec WHERE tag = '600' AND subfield = 'a' AND record = r.id)) AS name_subject,
+	ARRAY((SELECT DISTINCT value FROM metabib.full_rec WHERE tag = '610' AND subfield = 'a' AND record = r.id)) AS corporate_subject,
+	ARRAY((SELECT value FROM metabib.full_rec WHERE tag = '856' AND subfield IN ('3','y','u') AND record = r.id ORDER BY CASE WHEN subfield IN ('3','y') THEN 0 ELSE 1 END)) AS external_uri
+  FROM	biblio.record_entry r
+	JOIN metabib.metarecord_source_map s ON (s.source = r.id)
+	LEFT JOIN metabib.full_rec uniform_title ON (r.id = uniform_title.record AND uniform_title.tag = '240' AND uniform_title.subfield = 'a')
+	LEFT JOIN metabib.full_rec title ON (r.id = title.record AND title.tag = '245' AND title.subfield = 'a')
+	LEFT JOIN metabib.full_rec author ON (r.id = author.record AND author.tag = '100' AND author.subfield = 'a')
+	LEFT JOIN metabib.full_rec publisher ON (r.id = publisher.record AND publisher.tag = '260' AND publisher.subfield = 'b')
+	LEFT JOIN metabib.full_rec pubdate ON (r.id = pubdate.record AND pubdate.tag = '260' AND pubdate.subfield = 'c')
+	LEFT JOIN metabib.full_rec isbn ON (r.id = isbn.record AND isbn.tag IN ('024', '020') AND isbn.subfield IN ('a','z'))
+	LEFT JOIN metabib.full_rec issn ON (r.id = issn.record AND issn.tag = '022' AND issn.subfield = 'a')
+	LEFT JOIN metabib.full_rec series_title ON (r.id = series_title.record AND series_title.tag IN ('830','440') AND series_title.subfield = 'a')
+	LEFT JOIN metabib.full_rec series_statement ON (r.id = series_statement.record AND series_statement.tag = '490' AND series_statement.subfield = 'a')
+	LEFT JOIN metabib.full_rec summary ON (r.id = summary.record AND summary.tag = '520' AND summary.subfield = 'a')
+  GROUP BY 1,2,3,4,5,6,7,8,9,10,11,12,13,14;
+
+CREATE OR REPLACE FUNCTION reporter.disable_materialized_simple_record_trigger () RETURNS VOID AS $$
+    DROP TRIGGER IF EXISTS zzz_update_materialized_simple_record_tgr ON metabib.real_full_rec;
+$$ LANGUAGE SQL;
+
+CREATE OR REPLACE FUNCTION reporter.simple_rec_trigger () RETURNS TRIGGER AS $func$
+BEGIN
+    IF TG_OP = 'DELETE' THEN
+        PERFORM reporter.simple_rec_delete(NEW.id);
+    ELSE
+        PERFORM reporter.simple_rec_update(NEW.id);
+    END IF;
+
+    RETURN NEW;
+END;
+$func$ LANGUAGE PLPGSQL;
+
+CREATE TRIGGER bbb_simple_rec_trigger AFTER INSERT OR UPDATE ON biblio.record_entry FOR EACH ROW EXECUTE PROCEDURE reporter.simple_rec_trigger ();
+
+ALTER TABLE extend_reporter.legacy_circ_count DROP CONSTRAINT legacy_circ_count_id_fkey;
+
+CREATE INDEX asset_copy_note_owning_copy_idx ON asset.copy_note ( owning_copy );
+
+UPDATE config.org_unit_setting_type
+    SET view_perm = (SELECT id FROM permission.perm_list
+        WHERE code = 'VIEW_CREDIT_CARD_PROCESSING' LIMIT 1)
+    WHERE name LIKE 'credit.processor%' AND view_perm IS NULL;
+
+UPDATE config.org_unit_setting_type
+    SET update_perm = (SELECT id FROM permission.perm_list
+        WHERE code = 'ADMIN_CREDIT_CARD_PROCESSING' LIMIT 1)
+    WHERE name LIKE 'credit.processor%' AND update_perm IS NULL;
+
+INSERT INTO config.org_unit_setting_type (name, label, description, datatype)
+    VALUES (
+        'opac.fully_compressed_serial_holdings',
+        'OPAC: Use fully compressed serial holdings',
+        'Show fully compressed serial holdings for all libraries at and below
+        the current context unit',
+        'bool'
+    );
+
+CREATE OR REPLACE FUNCTION authority.normalize_heading( TEXT ) RETURNS TEXT AS $func$
+    use strict;
+    use warnings;
+
+    use utf8;
+    use MARC::Record;
+    use MARC::File::XML (BinaryEncoding => 'UTF8');
+    use UUID::Tiny ':std';
+
+    my $xml = shift() or return undef;
+
+    my $r;
+
+    # Prevent errors in XML parsing from blowing out ungracefully
+    eval {
+        $r = MARC::Record->new_from_xml( $xml );
+        1;
+    } or do {
+       return 'BAD_MARCXML_' . create_uuid_as_string(UUID_MD5, $xml);
+    };
+
+    if (!$r) {
+       return 'BAD_MARCXML_' . create_uuid_as_string(UUID_MD5, $xml);
+    }
+
+    # From http://www.loc.gov/standards/sourcelist/subject.html
+    my $thes_code_map = {
+        a => 'lcsh',
+        b => 'lcshac',
+        c => 'mesh',
+        d => 'nal',
+        k => 'cash',
+        n => 'notapplicable',
+        r => 'aat',
+        s => 'sears',
+        v => 'rvm',
+    };
+
+    # Default to "No attempt to code" if the leader is horribly broken
+    my $fixed_field = $r->field('008');
+    my $thes_char = '|';
+    if ($fixed_field) {
+        $thes_char = substr($fixed_field->data(), 11, 1) || '|';
+    }
+
+    my $thes_code = 'UNDEFINED';
+
+    if ($thes_char eq 'z') {
+        # Grab the 040 $f per http://www.loc.gov/marc/authority/ad040.html
+        $thes_code = $r->subfield('040', 'f') || 'UNDEFINED';
+    } elsif ($thes_code_map->{$thes_char}) {
+        $thes_code = $thes_code_map->{$thes_char};
+    }
+
+    my $auth_txt = '';
+    my $head = $r->field('1..');
+    if ($head) {
+        # Concatenate all of these subfields together, prefixed by their code
+        # to prevent collisions along the lines of "Fiction, North Carolina"
+        foreach my $sf ($head->subfields()) {
+            $auth_txt .= '‡' . $sf->[0] . ' ' . $sf->[1];
+        }
+    }
+
+    # Perhaps better to parameterize the spi and pass as a parameter
+    $auth_txt =~ s/'//go;
+
+    if ($auth_txt) {
+        my $result = spi_exec_query("SELECT public.naco_normalize('$auth_txt') AS norm_text");
+        my $norm_txt = $result->{rows}[0]->{norm_text};
+        return $head->tag() . "_" . $thes_code . " " . $norm_txt;
+    }
+
+    return 'NOHEADING_' . $thes_code . ' ' . create_uuid_as_string(UUID_MD5, $xml);
+$func$ LANGUAGE 'plperlu' IMMUTABLE;
+
+COMMENT ON FUNCTION authority.normalize_heading( TEXT ) IS $$
+/**
+* Extract the authority heading, thesaurus, and NACO-normalized values
+* from an authority record. The primary purpose is to build a unique
+* index to defend against duplicated authority records from the same
+* thesaurus.
+*/
+$$;
+
+DROP INDEX authority.authority_record_unique_tcn;
+ALTER TABLE authority.record_entry DROP COLUMN arn_value;
+ALTER TABLE authority.record_entry DROP COLUMN arn_source;
+
+DROP INDEX IF EXISTS authority.unique_by_heading_and_thesaurus;
+
+CREATE INDEX by_heading_and_thesaurus
+    ON authority.record_entry (authority.normalize_heading(marc))
+    WHERE deleted IS FALSE or deleted = FALSE
+;
+
+ALTER TABLE acq.provider_contact
+	ALTER COLUMN name SET NOT NULL;
+
+ALTER TABLE actor.stat_cat
+	ADD COLUMN usr_summary BOOL NOT NULL DEFAULT FALSE;
+
+-- Recreate some foreign keys that were somehow dropped, probably
+-- by some kind of cascade from an inherited table:
+
+ALTER TABLE action.reservation_transit_copy
+	ADD CONSTRAINT artc_tc_fkey FOREIGN KEY (target_copy)
+		REFERENCES booking.resource(id)
+		ON DELETE CASCADE
+		DEFERRABLE INITIALLY DEFERRED,
+	ADD CONSTRAINT reservation_transit_copy_reservation_fkey FOREIGN KEY (reservation)
+		REFERENCES booking.reservation(id)
+		ON DELETE SET NULL
+		DEFERRABLE INITIALLY DEFERRED;
+
+CREATE INDEX user_bucket_item_target_user_idx
+	ON container.user_bucket_item ( target_user );
+
+CREATE INDEX m_c_t_collector_idx
+	ON money.collections_tracker ( collector );
+
+CREATE INDEX aud_actor_usr_address_hist_id_idx
+	ON auditor.actor_usr_address_history ( id );
+
+CREATE INDEX aud_actor_usr_hist_id_idx
+	ON auditor.actor_usr_history ( id );
+
+CREATE INDEX aud_asset_cn_hist_creator_idx
+	ON auditor.asset_call_number_history ( creator );
+
+CREATE INDEX aud_asset_cn_hist_editor_idx
+	ON auditor.asset_call_number_history ( editor );
+
+CREATE INDEX aud_asset_cp_hist_creator_idx
+	ON auditor.asset_copy_history ( creator );
+
+CREATE INDEX aud_asset_cp_hist_editor_idx
+	ON auditor.asset_copy_history ( editor );
+
+CREATE INDEX aud_bib_rec_entry_hist_creator_idx
+	ON auditor.biblio_record_entry_history ( creator );
+
+CREATE INDEX aud_bib_rec_entry_hist_editor_idx
+	ON auditor.biblio_record_entry_history ( editor );
+
+COMMIT;
+
+-- Some operations go outside of the transaction, because they may
+-- legitimately fail.
+
+\qecho ALTERs of auditor.action_hold_request_history will fail if the table
+\qecho doesn't exist; ignore those errors if they occur.
+
+ALTER TABLE auditor.action_hold_request_history ADD COLUMN cut_in_line BOOL;
+
+ALTER TABLE auditor.action_hold_request_history
+ADD COLUMN mint_condition boolean NOT NULL DEFAULT TRUE;
+
+ALTER TABLE auditor.action_hold_request_history
+ADD COLUMN shelf_expire_time TIMESTAMPTZ;
+
+\qecho Outside of the transaction: adding indexes that may or may not exist.
+\qecho If any of these CREATE INDEX statements fails because the index already
+\qecho exists, ignore the failure.
+
+CREATE INDEX serial_subscription_record_idx ON serial.subscription (record_entry);
+CREATE INDEX serial_subscription_owner_idx ON serial.subscription (owning_lib);
+CREATE INDEX serial_caption_and_pattern_sub_idx ON serial.caption_and_pattern (subscription);
+CREATE INDEX serial_distribution_sub_idx ON serial.distribution (subscription);
+CREATE INDEX serial_distribution_holding_lib_idx ON serial.distribution (holding_lib);
+CREATE INDEX serial_distribution_note_dist_idx ON serial.distribution_note (distribution);
+CREATE INDEX serial_stream_dist_idx ON serial.stream (distribution);
+CREATE INDEX serial_routing_list_user_stream_idx ON serial.routing_list_user (stream);
+CREATE INDEX serial_routing_list_user_reader_idx ON serial.routing_list_user (reader);
+CREATE INDEX serial_issuance_sub_idx ON serial.issuance (subscription);
+CREATE INDEX serial_issuance_caption_and_pattern_idx ON serial.issuance (caption_and_pattern);
+CREATE INDEX serial_issuance_date_published_idx ON serial.issuance (date_published);
+CREATE UNIQUE INDEX unit_barcode_key ON serial.unit (barcode) WHERE deleted = FALSE OR deleted IS FALSE;
+CREATE INDEX unit_cn_idx ON serial.unit (call_number);
+CREATE INDEX unit_avail_cn_idx ON serial.unit (call_number);
+CREATE INDEX unit_creator_idx  ON serial.unit ( creator );
+CREATE INDEX unit_editor_idx   ON serial.unit ( editor );
+CREATE INDEX serial_item_stream_idx ON serial.item (stream);
+CREATE INDEX serial_item_issuance_idx ON serial.item (issuance);
+CREATE INDEX serial_item_unit_idx ON serial.item (unit);
+CREATE INDEX serial_item_uri_idx ON serial.item (uri);
+CREATE INDEX serial_item_date_received_idx ON serial.item (date_received);
+CREATE INDEX serial_item_status_idx ON serial.item (status);
+CREATE INDEX serial_item_note_item_idx ON serial.item_note (item);
+CREATE INDEX serial_basic_summary_dist_idx ON serial.basic_summary (distribution);
+CREATE INDEX serial_supplement_summary_dist_idx ON serial.supplement_summary (distribution);
+CREATE INDEX serial_index_summary_dist_idx ON serial.index_summary (distribution);
+
+CREATE INDEX actor_card_barcode_lower_idx ON actor.card (lower(barcode));
+
+\qecho if the following CREATE INDEX fails, It will be necessary to do some
+\qecho data cleanup as described in the comments.
+
+-- If the unique index fails, uncomment the following to create
+-- a regular index that will help find the duplicates in a hurry:
+--CREATE INDEX by_heading_and_thesaurus
+--    ON authority.record_entry (authority.normalize_heading(marc))
+--    WHERE deleted IS FALSE or deleted = FALSE
+--;
+
+-- Then find the duplicates like so to get an idea of how much
+-- pain you're looking at to clean things up:
+--SELECT id, authority.normalize_heading(marc)
+--    FROM authority.record_entry
+--    WHERE authority.normalize_heading(marc) IN (
+--        SELECT authority.normalize_heading(marc)
+--        FROM authority.record_entry
+--        GROUP BY authority.normalize_heading(marc)
+--        HAVING COUNT(*) > 1
+--    )
+--;
+
+-- Once you have removed the duplicates and the CREATE UNIQUE INDEX
+-- statement succeeds, drop the temporary index to avoid unnecessary
+-- duplication:
+-- DROP INDEX authority.by_heading_and_thesaurus;
+
+\qecho Upgrade script completed.

Modified: branches/serials-integration/Open-ILS/src/sql/Pg/100.circ_matrix.sql
===================================================================
--- branches/serials-integration/Open-ILS/src/sql/Pg/100.circ_matrix.sql	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/src/sql/Pg/100.circ_matrix.sql	2010-10-18 13:46:56 UTC (rev 18371)
@@ -181,6 +181,10 @@
                     CASE WHEN m.usr_age_lower_bound    IS NOT NULL THEN 0.5 ELSE 0 END +
                     CASE WHEN m.usr_age_upper_bound    IS NOT NULL THEN 0.5 ELSE 0 END DESC LOOP
 
+            IF current_mp.is_renewal IS NOT NULL THEN
+                CONTINUE WHEN current_mp.is_renewal <> renewal;
+            END IF;
+
             IF current_mp.circ_modifier IS NOT NULL THEN
                 CONTINUE WHEN current_mp.circ_modifier <> item_object.circ_modifier OR item_object.circ_modifier IS NULL;
             END IF;

Modified: branches/serials-integration/Open-ILS/src/sql/Pg/110.hold_matrix.sql
===================================================================
--- branches/serials-integration/Open-ILS/src/sql/Pg/110.hold_matrix.sql	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/src/sql/Pg/110.hold_matrix.sql	2010-10-18 13:46:56 UTC (rev 18371)
@@ -75,8 +75,15 @@
     SELECT INTO item_object * FROM asset.copy WHERE id = match_item;
     SELECT INTO item_cn_object * FROM asset.call_number WHERE id = item_object.call_number;
     SELECT INTO rec_descriptor r.* FROM metabib.rec_descriptor r WHERE r.record = item_cn_object.record;
-    SELECT INTO current_requestor_group * FROM permission.grp_tree WHERE id = requestor_object.profile;
 
+    PERFORM * FROM config.internal_flag WHERE name = 'circ.holds.usr_not_requestor' AND enabled;
+
+    IF NOT FOUND THEN
+        SELECT INTO current_requestor_group * FROM permission.grp_tree WHERE id = requestor_object.profile;
+    ELSE
+        SELECT INTO current_requestor_group * FROM permission.grp_tree WHERE id = user_object.profile;
+    END IF;
+
     LOOP 
         -- for each potential matchpoint for this ou and group ...
         FOR current_mp IN

Modified: branches/serials-integration/Open-ILS/src/sql/Pg/200.schema.acq.sql
===================================================================
--- branches/serials-integration/Open-ILS/src/sql/Pg/200.schema.acq.sql	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/src/sql/Pg/200.schema.acq.sql	2010-10-18 13:46:56 UTC (rev 18371)
@@ -106,7 +106,7 @@
 CREATE TABLE acq.provider_contact (
 	id		SERIAL	PRIMARY KEY,
     provider    INT NOT NULL REFERENCES acq.provider (id) DEFERRABLE INITIALLY DEFERRED,
-    name    TEXT NULL NULL,
+    name    TEXT NOT NULL,
     role    TEXT, -- free-form.. e.g. "our sales guy"
     email   TEXT,
     phone   TEXT
@@ -673,9 +673,9 @@
     src_fund         INT            NOT NULL REFERENCES acq.fund( id )
                                     DEFERRABLE INITIALLY DEFERRED,
     src_amount       NUMERIC        NOT NULL,
-    dest_fund        INT            NOT NULL REFERENCES acq.fund( id )
+    dest_fund        INT            REFERENCES acq.fund( id )
                                     DEFERRABLE INITIALLY DEFERRED,
-    dest_amount      NUMERIC        NOT NULL,
+    dest_amount      NUMERIC,
     transfer_time    TIMESTAMPTZ    NOT NULL DEFAULT now(),
     transfer_user    INT            NOT NULL REFERENCES actor.usr( id )
                                     DEFERRABLE INITIALLY DEFERRED,

Modified: branches/serials-integration/Open-ILS/src/sql/Pg/210.schema.serials.sql
===================================================================
--- branches/serials-integration/Open-ILS/src/sql/Pg/210.schema.serials.sql	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/src/sql/Pg/210.schema.serials.sql	2010-10-18 13:46:56 UTC (rev 18371)
@@ -39,6 +39,8 @@
 	expected_date_offset   INTERVAL
 	-- acquisitions/business-side tables link to here
 );
+CREATE INDEX serial_subscription_record_idx ON serial.subscription (record_entry);
+CREATE INDEX serial_subscription_owner_idx ON serial.subscription (owning_lib);
 
 CREATE TABLE serial.subscription_note (
 	id           SERIAL PRIMARY KEY,
@@ -54,6 +56,7 @@
 	title        TEXT   NOT NULL,
 	value        TEXT   NOT NULL
 );
+CREATE INDEX serial_subscription_note_sub_idx ON serial.subscription_note (subscription);
 
 CREATE TABLE serial.caption_and_pattern (
 	id           SERIAL       PRIMARY KEY,
@@ -65,6 +68,8 @@
 	                          CONSTRAINT cap_type CHECK ( type in
 	                          ( 'basic', 'supplement', 'index' )),
 	create_date  TIMESTAMPTZ  NOT NULL DEFAULT now(),
+	start_date   TIMESTAMPTZ  NOT NULL DEFAULT now(),
+	end_date     TIMESTAMPTZ,
 	active       BOOL         NOT NULL DEFAULT FALSE,
 	pattern_code TEXT         NOT NULL,       -- must contain JSON
 	enum_1       TEXT,
@@ -79,6 +84,7 @@
 	chron_4      TEXT,
 	chron_5      TEXT
 );
+CREATE INDEX serial_caption_and_pattern_sub_idx ON serial.caption_and_pattern (subscription);
 
 --at least one distribution per org_unit holding issues
 CREATE TABLE serial.distribution (
@@ -86,6 +92,11 @@
 	record_entry          BIGINT  REFERENCES serial.record_entry (id)
 								  ON DELETE SET NULL
 								  DEFERRABLE INITIALLY DEFERRED,
+	summary_method        TEXT    CONSTRAINT sdist_summary_method_check
+	                              CHECK (summary_method IS NULL
+	                              OR summary_method IN ( 'add_to_sre',
+	                              'merge_with_sre', 'use_sre_only',
+	                              'use_sdist_only')),
 	subscription          INT     NOT NULL
 	                              REFERENCES serial.subscription (id)
 								  ON DELETE CASCADE
@@ -106,6 +117,8 @@
 	unit_label_suffix     TEXT
 );
 CREATE UNIQUE INDEX one_dist_per_sre_idx ON serial.distribution (record_entry);
+CREATE INDEX serial_distribution_sub_idx ON serial.distribution (subscription);
+CREATE INDEX serial_distribution_holding_lib_idx ON serial.distribution (holding_lib);
 
 CREATE TABLE serial.distribution_note (
 	id           SERIAL PRIMARY KEY,
@@ -121,6 +134,7 @@
 	title        TEXT   NOT NULL,
 	value        TEXT   NOT NULL
 );
+CREATE INDEX serial_distribution_note_dist_idx ON serial.distribution_note (distribution);
 
 CREATE TABLE serial.stream (
 	id              SERIAL  PRIMARY KEY,
@@ -130,6 +144,7 @@
 	                        DEFERRABLE INITIALLY DEFERRED,
 	routing_label   TEXT
 );
+CREATE INDEX serial_stream_dist_idx ON serial.stream (distribution);
 
 CREATE UNIQUE INDEX label_once_per_dist
 	ON serial.stream (distribution, routing_label)
@@ -155,6 +170,8 @@
 		(reader IS NULL AND department IS NOT NULL)
 	)
 );
+CREATE INDEX serial_routing_list_user_stream_idx ON serial.routing_list_user (stream);
+CREATE INDEX serial_routing_list_user_reader_idx ON serial.routing_list_user (reader);
 
 CREATE TABLE serial.issuance (
 	id              SERIAL    PRIMARY KEY,
@@ -183,14 +200,21 @@
 	holding_link_id INT -- probably defunct
 	-- TODO: add columns for separate enumeration/chronology values
 );
+CREATE INDEX serial_issuance_sub_idx ON serial.issuance (subscription);
+CREATE INDEX serial_issuance_caption_and_pattern_idx ON serial.issuance (caption_and_pattern);
+CREATE INDEX serial_issuance_date_published_idx ON serial.issuance (date_published);
 
 CREATE TABLE serial.unit (
 	sort_key          TEXT,
 	detailed_contents TEXT    NOT NULL,
 	summary_contents  TEXT    NOT NULL
 ) INHERITS (asset.copy);
-
 ALTER TABLE serial.unit ADD PRIMARY KEY (id);
+CREATE UNIQUE INDEX unit_barcode_key ON serial.unit (barcode) WHERE deleted = FALSE OR deleted IS FALSE;
+CREATE INDEX unit_cn_idx ON serial.unit (call_number);
+CREATE INDEX unit_avail_cn_idx ON serial.unit (call_number);
+CREATE INDEX unit_creator_idx  ON serial.unit ( creator );
+CREATE INDEX unit_editor_idx   ON serial.unit ( editor );
 
 -- must create this rule explicitly; it is not inherited from asset.copy
 CREATE RULE protect_serial_unit_delete AS ON DELETE TO serial.unit DO INSTEAD UPDATE serial.unit SET deleted = TRUE WHERE OLD.id = serial.unit.id;
@@ -227,6 +251,12 @@
 	                        ) DEFAULT 'Expected',
 	shadowed        BOOL    NOT NULL DEFAULT FALSE -- ignore when generating summaries/labels
 );
+CREATE INDEX serial_item_stream_idx ON serial.item (stream);
+CREATE INDEX serial_item_issuance_idx ON serial.item (issuance);
+CREATE INDEX serial_item_unit_idx ON serial.item (unit);
+CREATE INDEX serial_item_uri_idx ON serial.item (uri);
+CREATE INDEX serial_item_date_received_idx ON serial.item (date_received);
+CREATE INDEX serial_item_status_idx ON serial.item (status);
 
 CREATE TABLE serial.item_note (
 	id          SERIAL  PRIMARY KEY,
@@ -242,6 +272,7 @@
 	title       TEXT    NOT NULL,
 	value       TEXT    NOT NULL
 );
+CREATE INDEX serial_item_note_item_idx ON serial.item_note (item);
 
 CREATE TABLE serial.basic_summary (
 	id                  SERIAL  PRIMARY KEY,
@@ -250,8 +281,10 @@
 	                            ON DELETE CASCADE
 	                            DEFERRABLE INITIALLY DEFERRED,
 	generated_coverage  TEXT    NOT NULL,
-	textual_holdings    TEXT
+	textual_holdings    TEXT,
+	show_generated      BOOL    NOT NULL DEFAULT TRUE
 );
+CREATE INDEX serial_basic_summary_dist_idx ON serial.basic_summary (distribution);
 
 CREATE TABLE serial.supplement_summary (
 	id                  SERIAL  PRIMARY KEY,
@@ -260,8 +293,10 @@
 	                            ON DELETE CASCADE
 	                            DEFERRABLE INITIALLY DEFERRED,
 	generated_coverage  TEXT    NOT NULL,
-	textual_holdings    TEXT
+	textual_holdings    TEXT,
+	show_generated      BOOL    NOT NULL DEFAULT TRUE
 );
+CREATE INDEX serial_supplement_summary_dist_idx ON serial.supplement_summary (distribution);
 
 CREATE TABLE serial.index_summary (
 	id                  SERIAL  PRIMARY KEY,
@@ -270,8 +305,10 @@
 	                            ON DELETE CASCADE
 	                            DEFERRABLE INITIALLY DEFERRED,
 	generated_coverage  TEXT    NOT NULL,
-	textual_holdings    TEXT
+	textual_holdings    TEXT,
+	show_generated      BOOL    NOT NULL DEFAULT TRUE
 );
+CREATE INDEX serial_index_summary_dist_idx ON serial.index_summary (distribution);
 
 COMMIT;
 

Modified: branches/serials-integration/Open-ILS/src/sql/Pg/800.fkeys.sql
===================================================================
--- branches/serials-integration/Open-ILS/src/sql/Pg/800.fkeys.sql	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/src/sql/Pg/800.fkeys.sql	2010-10-18 13:46:56 UTC (rev 18371)
@@ -114,7 +114,9 @@
 
 ALTER TABLE config.remote_account ADD CONSTRAINT config_remote_account_owner_fkey FOREIGN KEY (owner) REFERENCES actor.org_unit (id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
 
-ALTER TABLE config.org_unit_setting_type ADD CONSTRAINT view_perm_fkey FOREIGN KEY (view_perm) REFERENCES permission.perm_list (id) ON DELETE SET NULL DEFERRABLE INITIALLY DEFERRED;
-ALTER TABLE config.org_unit_setting_type ADD CONSTRAINT update_perm_fkey FOREIGN KEY (update_perm) REFERENCES permission.perm_list (id) DEFERRABLE INITIALLY DEFERRED;
+ALTER TABLE config.org_unit_setting_type ADD CONSTRAINT view_perm_fkey FOREIGN KEY (view_perm) REFERENCES permission.perm_list (id) ON UPDATE CASCADE ON DELETE RESTRICT DEFERRABLE INITIALLY DEFERRED;
+ALTER TABLE config.org_unit_setting_type ADD CONSTRAINT update_perm_fkey FOREIGN KEY (update_perm) REFERENCES permission.perm_list (id) ON UPDATE CASCADE DEFERRABLE INITIALLY DEFERRED;
 
+CREATE INDEX by_heading_and_thesaurus ON authority.record_entry (authority.normalize_heading(marc)) WHERE deleted IS FALSE or deleted = FALSE;
+
 COMMIT;

Modified: branches/serials-integration/Open-ILS/src/sql/Pg/950.data.seed-values.sql
===================================================================
--- branches/serials-integration/Open-ILS/src/sql/Pg/950.data.seed-values.sql	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/src/sql/Pg/950.data.seed-values.sql	2010-10-18 13:46:56 UTC (rev 18371)
@@ -955,9 +955,11 @@
     (9, 6, 5, 'BM1', oils_i18n_gettext(9, 'Example Bookmobile 1', 'aou', 'name'));
 SELECT SETVAL('actor.org_unit_id_seq'::TEXT, 100);
 
-INSERT INTO actor.org_address VALUES (DEFAULT,DEFAULT,DEFAULT,1,'123 Main St.',NULL,'Anywhere',NULL,'GA','US','30303');
+INSERT INTO actor.org_address (org_unit, street1, city, state, country, post_code)
+SELECT id, '123 Main St.', 'Anywhere', 'GA', 'US', '30303'
+FROM actor.org_unit;
 
-UPDATE actor.org_unit SET holds_address = 1, ill_address = 1, billing_address = 1, mailing_address = 1;
+UPDATE actor.org_unit SET holds_address = id, ill_address = id, billing_address = id, mailing_address = id;
 
 INSERT INTO config.billing_type (id, name, owner) VALUES
 	( 1, oils_i18n_gettext(1, 'Overdue Materials', 'cbt', 'name'), 1);
@@ -1258,7 +1260,7 @@
     (277,'UPDATE_VOLUME_NOTE', oils_i18n_gettext(277,'FIXME: Need description for UPDATE_VOLUME_NOTE', 'ppl', 'description')),
     (278,'UPDATE_VR_FORMAT', oils_i18n_gettext(278,'FIXME: Need description for UPDATE_VR_FORMAT', 'ppl', 'description')),
     (279,'UPDATE_XML_TRANSFORM', oils_i18n_gettext(279,'FIXME: Need description for UPDATE_XML_TRANSFORM', 'ppl', 'description')),
-    (280,'MERGE_BIB_RECORDS', oils_i18n_gettext(280,'FIXME: Need description for MERGE_BIB_RECORDS', 'ppl', 'description')),
+    (280,'MERGE_BIB_RECORDS', oils_i18n_gettext(280,'Allow a user to merge bibliographic records and associated assets', 'ppl', 'description')),
     (281,'UPDATE_PICKUP_LIB_FROM_HOLDS_SHELF', oils_i18n_gettext(281,'FIXME: Need description for UPDATE_PICKUP_LIB_FROM_HOLDS_SHELF', 'ppl', 'description')),
     (282,'CREATE_ACQ_FUNDING_SOURCE', oils_i18n_gettext(282,'FIXME: Need description for CREATE_ACQ_FUNDING_SOURCE', 'ppl', 'description')),
     (283,'CREATE_AUTHORITY_IMPORT_IMPORT_FIELD_DEF', oils_i18n_gettext(283,'FIXME: Need description for CREATE_AUTHORITY_IMPORT_IMPORT_FIELD_DEF', 'ppl', 'description')),
@@ -1379,8 +1381,18 @@
     (390, 'OVERRIDE_HOLD_HAS_LOCAL_COPY', oils_i18n_gettext( 390, 'Allow a user to override the circ.holds.hold_has_copy_at.block setting', 'ppl', 'description' ))
     ,(391, 'UPDATE_PICKUP_LIB_FROM_TRANSIT', oils_i18n_gettext( 391, 'Allow a user to change the pickup and transit destination for a captured hold item already in transit', 'ppl', 'description' ))
     ,(392, 'COPY_NEEDED_FOR_HOLD.override', oils_i18n_gettext( 392, 'Allow a user to force renewal of an item that could fulfill a hold request', 'ppl', 'description' ))
+    ,(393, 'MERGE_AUTH_RECORDS', oils_i18n_gettext( 393, 'Allow a user to merge authority records together', 'ppl', 'description' ))
+    ,(394, 'ISSUANCE_HOLDS', oils_i18n_gettext( 394, 'Allow a user to place holds on serials issuances', 'ppl', 'description' ))
+    ,(395, 'VIEW_CREDIT_CARD_PROCESSING', oils_i18n_gettext( 395, 'View org unit settings related to credit card processing', 'ppl', 'description' ))
+    ,(396, 'ADMIN_CREDIT_CARD_PROCESSING', oils_i18n_gettext( 396, 'Update org unit settings related to credit card processing', 'ppl', 'description' ))
+    ,(397, 'ADMIN_SERIAL_CAPTION_PATTERN', oils_i18n_gettext(397, 'Create/update/delete serial caption and pattern objects', 'ppl', 'description'))
+    ,(398, 'ADMIN_SERIAL_SUBSCRIPTION', oils_i18n_gettext(398, 'Create/update/delete serial subscription objects', 'ppl', 'description'))
+    ,(399, 'ADMIN_SERIAL_DISTRIBUTION', oils_i18n_gettext(399, 'Create/update/delete serial distribution objects', 'ppl', 'description'))
+    ,(400, 'ADMIN_SERIAL_STREAM', oils_i18n_gettext(400, 'Create/update/delete serial stream objects', 'ppl', 'description'))
+    ,(401, 'RECEIVE_SERIAL', oils_i18n_gettext(401, 'Receive serial items', 'ppl', 'description'))
 ;
 
+
 SELECT SETVAL('permission.perm_list_id_seq'::TEXT, 1000);
 
 INSERT INTO permission.grp_tree (id, name, parent, description, perm_interval, usergroup, application_perm) VALUES
@@ -1514,6 +1526,7 @@
 INSERT INTO permission.grp_perm_map (grp, perm, depth, grantable) VALUES (4, (SELECT id FROM permission.perm_list WHERE code = 'UPDATE_MFHD_RECORD'), 1, false);
 INSERT INTO permission.grp_perm_map (grp, perm, depth, grantable) VALUES (4, (SELECT id FROM permission.perm_list WHERE code = 'DELETE_MFHD_RECORD'), 1, false);
 INSERT INTO permission.grp_perm_map (grp, perm, depth, grantable) VALUES (4, (SELECT id FROM permission.perm_list WHERE code = 'UPDATE_RECORD'), 1, false);
+INSERT INTO permission.grp_perm_map (grp, perm, depth, grantable) VALUES (4, (SELECT id FROM permission.perm_list WHERE code = 'MERGE_AUTH_RECORDS'), 1, false);
 
 -- Add basic circulation permissions to the Circulators group
 INSERT INTO permission.grp_perm_map (grp, perm, depth, grantable) VALUES (5, (SELECT id FROM permission.perm_list WHERE code = 'CREATE_TRANSACTION'), 0, false);
@@ -1688,7 +1701,7 @@
 
 ( 'circ.hold_stalling.soft',
   'Holds: Soft stalling interval',
-  'How long to wait before allowing remote items to be opportunisticaly captured for a hold.  Example "5 days"',
+  'How long to wait before allowing remote items to be opportunistically captured for a hold.  Example "5 days"',
   'interval' ),
 
 ( 'circ.hold_stalling_hard',
@@ -1718,12 +1731,12 @@
 
 ( 'circ.item_checkout_history.max',
   'Maximum previous checkouts displayed',
-  'This is maximum number of previous circulations the staff client will display when investigating item details',
+  'This is the maximum number of previous circulations the staff client will display when investigating item details',
   'integer' ),
 
 ( 'circ.reshelving_complete.interval',
   'Change reshelving status interval',
-  'Amount of time to wait before changing an item from "reshelving" status to "available".  Examples "1 day", "6 hours"',
+  'Amount of time to wait before changing an item from "reshelving" status to "available".  Examples: "1 day", "6 hours"',
   'interval' ),
 
 ( 'circ.holds.default_estimated_wait_interval',
@@ -1738,7 +1751,7 @@
 
 ( 'circ.selfcheck.patron_login_timeout',
   'Selfcheck: Patron Login Timeout (in seconds)',
-  'Number of seconds of inactivity before the patron is logged out of the selfcheck interfacer',
+  'Number of seconds of inactivity before the patron is logged out of the selfcheck interface',
   'integer' ),
 
 ( 'circ.selfcheck.alert.popup',
@@ -1966,6 +1979,36 @@
     'Credit card processing: PayPal test mode',
     '',
     'bool' ),
+('credit.processor.payflowpro.enabled',
+    'Credit card processing: Enable PayflowPro payments',
+    'This is NOT the same thing as the settings labeled with just "PayPal."',
+    'bool'
+),
+('credit.processor.payflowpro.login',
+    'Credit card processing: PayflowPro login/merchant ID',
+    'Often the same thing as the PayPal manager login',
+    'string'
+),
+('credit.processor.payflowpro.password',
+    'Credit card processing: PayflowPro password',
+    'PayflowPro password',
+    'string'
+),
+('credit.processor.payflowpro.testmode',
+    'Credit card processing: PayflowPro test mode',
+    'Do not really process transactions, but stay in test mode - uses pilot-payflowpro.paypal.com instead of the usual host',
+    'bool'
+),
+('credit.processor.payflowpro.vendor',
+    'Credit card processing: PayflowPro vendor',
+    'Often the same thing as the login',
+    'string'
+),
+('credit.processor.payflowpro.partner',
+    'Credit card processing: PayflowPro partner',
+    'Often "PayPal" or "VeriSign", sometimes others',
+    'string'
+),
 
 ( 'ui.admin.work_log.max_entries',
     oils_i18n_gettext('ui.admin.work_log.max_entries', 'GUI: Work Log: Maximum Actions Logged', 'coust', 'label'),
@@ -2000,9 +2043,25 @@
 ( 'circ.password_reset_request_throttle',
     oils_i18n_gettext('circ.password_reset_request_throttle', 'Circulation: Maximum concurrently active self-serve password reset requests', 'coust', 'label'),
     oils_i18n_gettext('circ.password_reset_request_throttle', 'Prevent the creation of new self-serve password reset requests until the number of active requests drops back below this number.', 'coust', 'description'),
-    'string')
+    'string'),
+
+( 'opac.fully_compressed_serial_holdings',
+    'OPAC: Use fully compressed serial holdings',
+    'Show fully compressed serial holdings for all libraries at and below
+    the current context unit',
+    'bool')
 ;
 
+UPDATE config.org_unit_setting_type
+    SET view_perm = (SELECT id FROM permission.perm_list
+        WHERE code = 'VIEW_CREDIT_CARD_PROCESSING' LIMIT 1)
+    WHERE name LIKE 'credit.processor%' AND view_perm IS NULL;
+
+UPDATE config.org_unit_setting_type
+    SET update_perm = (SELECT id FROM permission.perm_list
+        WHERE code = 'ADMIN_CREDIT_CARD_PROCESSING' LIMIT 1)
+    WHERE name LIKE 'credit.processor%' AND update_perm IS NULL;
+
 -- 0234.data.org-setting-ui.circ.suppress_checkin_popups.sql
 INSERT INTO config.org_unit_setting_type ( name, label, description, datatype ) VALUES (
         'ui.circ.suppress_checkin_popups',
@@ -2215,7 +2274,7 @@
 INSERT INTO vandelay.bib_attr_definition ( id, code, description, xpath ) VALUES (12, 'publisher',oils_i18n_gettext(12, 'Publisher', 'vqbrad', 'description'),'//*[@tag="260"]/*[@code="b"][1]');
 INSERT INTO vandelay.bib_attr_definition ( id, code, description, xpath, remove ) VALUES (13, 'pubdate',oils_i18n_gettext(13, 'Publication Date', 'vqbrad', 'description'),'//*[@tag="260"]/*[@code="c"][1]',$r$\D$r$);
 INSERT INTO vandelay.bib_attr_definition ( id, code, description, xpath ) VALUES (14, 'edition',oils_i18n_gettext(14, 'Edition', 'vqbrad', 'description'),'//*[@tag="250"]/*[@code="a"][1]');
-INSERT INTO vandelay.bib_attr_definition ( id, code, description, xpath ) VALUES (15, 'item_barcode',oils_i18n_gettext(15, 'Item Barcode', 'vqbrad', 'description'),'//*[@tag="852p"]/*[@code="a"][1]');
+INSERT INTO vandelay.bib_attr_definition ( id, code, description, xpath ) VALUES (15, 'item_barcode',oils_i18n_gettext(15, 'Item Barcode', 'vqbrad', 'description'),'//*[@tag="852"]/*[@code="p"][1]');
 SELECT SETVAL('vandelay.bib_attr_definition_id_seq'::TEXT, 100);
 
 INSERT INTO vandelay.import_item_attr_definition (
@@ -3370,7 +3429,7 @@
   [% END %]
   <tr>
     <td/><td/><td/><td/>
-    <td>Sub Total</td>
+    <td>Subtotal</td>
     <td>[% subtotal %]</td>
   </tr>
   </tbody>
@@ -3534,7 +3593,7 @@
 
 You requested hold(s) on the following item(s), but unfortunately
 we have not been able to fulfill your request after a considerable
-length of time.  If you would still like to recieve these items,
+length of time.  If you would still like to receive these items,
 no action is required.
 
 [% FOR hold IN target %]
@@ -4154,13 +4213,13 @@
 INSERT INTO action_trigger.hook (key,core_type,description) VALUES (
     'hold_request.cancel.expire_holds_shelf',
     'ahr',
-    'A hold is cancelled becuase it was on the holds shelf too long'
+    'A hold is cancelled because it was on the holds shelf too long'
 );
 
 INSERT INTO action_trigger.hook (key,core_type,description) VALUES (
     'hold_request.cancel.staff',
     'ahr',
-    'A hold is cancelled becuase it was cancelled by staff'
+    'A hold is cancelled because it was cancelled by staff'
 );
 
 INSERT INTO action_trigger.hook (key,core_type,description) VALUES (
@@ -4267,7 +4326,7 @@
 
 INSERT INTO config.index_normalizer (name, description, func, param_count) VALUES (
 	'Replace',
-	'Replace all occurances of first parameter in the string with the second parameter.',
+	'Replace all occurences of first parameter in the string with the second parameter.',
 	'replace',
 	2
 );
@@ -4368,7 +4427,7 @@
     VALUES (
         'circ.holds.uncancel.reset_request_time',
         'Holds: Reset request time on un-cancel',
-        'When a holds is uncanceled, reset the request time to push it to the end of the queue',
+        'When a hold is uncanceled, reset the request time to push it to the end of the queue',
         'bool'
     );
 
@@ -4417,7 +4476,7 @@
 (   'ApplyPatronPenalty',
     oils_i18n_gettext(
         'ApplyPatronPenalty',
-        'Applies the conifigured penalty to a patron.  Required named environment variables are "user", which refers to the user object, and "context_org", which refers to the org_unit object that acts as the focus for the penalty.',
+        'Applies the configured penalty to a patron.  Required named environment variables are "user", which refers to the user object, and "context_org", which refers to the org_unit object that acts as the focus for the penalty.',
         'atreact',
         'description'
     )
@@ -5575,7 +5634,7 @@
 INSERT INTO acq.invoice_item_type (code,name) VALUES ('SHP',oils_i18n_gettext('SHP', 'Shipping Charge', 'aiit', 'name'));
 INSERT INTO acq.invoice_item_type (code,name) VALUES ('HND',oils_i18n_gettext('HND', 'Handling Charge', 'aiit', 'name'));
 INSERT INTO acq.invoice_item_type (code,name) VALUES ('ITM',oils_i18n_gettext('ITM', 'Non-library Item', 'aiit', 'name'));
-INSERT INTO acq.invoice_item_type (code,name) VALUES ('SUB',oils_i18n_gettext('SUB', 'Searial Subscription', 'aiit', 'name'));
+INSERT INTO acq.invoice_item_type (code,name) VALUES ('SUB',oils_i18n_gettext('SUB', 'Serial Subscription', 'aiit', 'name'));
 
 INSERT INTO acq.invoice_method (code,name) VALUES ('EDI',oils_i18n_gettext('EDI', 'EDI', 'acqim', 'name'));
 INSERT INTO acq.invoice_method (code,name) VALUES ('PPR',oils_i18n_gettext('PPR', 'Paper', 'acqit', 'name'));
@@ -6216,6 +6275,30 @@
         'bool'
     );
 
+INSERT INTO config.global_flag (name, label, enabled)
+    VALUES (
+        'circ.holds.usr_not_requestor',
+        oils_i18n_gettext(
+            'circ.holds.usr_not_requestor',
+            'Holds: When testing hold matrix matchpoints, use the profile group of the receiving user instead of that of the requestor (affects staff-placed holds)',
+            'cgf',
+            'label'
+        ),
+        TRUE
+    );
+
+INSERT INTO config.global_flag (name, label, enabled)
+    VALUES (
+        'circ.holds.empty_issuance_ok',
+        oils_i18n_gettext(
+            'circ.holds.empty_issuance_ok',
+            'Holds: Allow holds on empty issuances',
+            'cgf',
+            'label'
+        ),
+        TRUE
+    );
+
 INSERT INTO config.global_flag (name, label) -- defaults to enabled=FALSE
     VALUES (
         'ingest.disable_authority_linking',
@@ -6447,13 +6530,13 @@
 VALUES (
     'serial.prev_issuance_copy_location',
     oils_i18n_gettext(
-        'setting.name',
+        'serial.prev_issuance_copy_location',
         'Serials: Previous Issuance Copy Location',
         'coust',
         'label'
     ),
     oils_i18n_gettext(
-        'setting.name',
+        'serial.prev_issuance_copy_location',
         'When a serial issuance is received, copies (units) of the previous issuance will be automatically moved into the configured shelving location',
         'coust',
         'descripton'
@@ -6466,13 +6549,13 @@
 VALUES (
     'cat.default_classification_scheme',
     oils_i18n_gettext(
-        'setting.name',
+        'cat.default_classification_scheme',
         'Cataloging: Default Classification Scheme',
         'coust',
         'label'
     ),
     oils_i18n_gettext(
-        'setting.name',
+        'cat.default_classification_scheme',
         'Defines the default classification scheme for new call numbers: 1 = Generic; 2 = Dewey; 3 = LC',
         'coust',
         'descripton'
@@ -6621,3 +6704,310 @@
         'integer'
 );
 
+INSERT INTO config.org_unit_setting_type (name, label, description, datatype)
+    VALUES
+        ('circ.holds.alert_if_local_avail',
+         oils_i18n_gettext('circ.holds.alert_if_local_avail',
+             'Holds: Local available alert', 'coust', 'label'),
+         oils_i18n_gettext('circ.holds.alert_if_local_avail',
+            'If local copy is available, alert the person making the hold', 'coust', 'description'),
+         'bool'),
+
+        ('circ.holds.deny_if_local_avail',
+         oils_i18n_gettext('circ.holds.deny_if_local_avail',
+            'Holds: Local available block', 'coust', 'label'),
+         oils_i18n_gettext('circ.holds.deny_if_local_avail',
+            'If local copy is available, deny the creation of the hold', 'coust', 'description'),
+         'bool'),
+
+        ('circ.holds.clear_shelf.no_capture_holds',
+        oils_i18n_gettext( 'circ.holds.clear_shelf.no_capture_holds',
+            'Holds: Bypass hold capture during clear shelf process', 'coust', 'label'),
+        oils_i18n_gettext( 'circ.holds.clear_shelf.no_capture_holds',
+            'During the clear shelf process, avoid capturing new holds on cleared items.', 'coust', 'description'),
+        'bool')
+;
+
+-- 0379.data.org-setting-circ.missing_pieces.copy_status.sql
+INSERT INTO config.org_unit_setting_type ( name, label, description, datatype, fm_class ) VALUES (
+        'circ.missing_pieces.copy_status',
+        oils_i18n_gettext(
+            'circ.missing_pieces.copy_status',
+            'Circulation: Item Status for Missing Pieces', 
+            'coust', 
+            'label'),
+        oils_i18n_gettext(
+            'circ.missing_pieces.copy_status',
+            'This is the Item Status to use for items that have been marked or scanned as having Missing Pieces.  In the absence of this setting, the Damaged status is used.',
+            'coust', 
+            'description'),
+        'link',
+        'ccs'
+);
+
+-- 0380.data.spine_label.sql Add spine label preferences
+INSERT INTO config.org_unit_setting_type (name, label, description, datatype)
+    VALUES
+        ('cat.label.font.size',
+            oils_i18n_gettext('cat.label.font.size',
+                'Cataloging: Spine and pocket label font size', 'coust', 'label'),
+            oils_i18n_gettext('cat.label.font.size',
+                'Set the default font size for spine and pocket labels', 'coust', 'description'),
+            'integer'
+        )
+        ,('cat.label.font.family',
+            oils_i18n_gettext('cat.label.font.family',
+                'Cataloging: Spine and pocket label font family', 'coust', 'label'),
+            oils_i18n_gettext('cat.label.font.family',
+                'Set the preferred font family for spine and pocket labels. You can specify a list of fonts, separated by commas, in order of preference; the system will use the first font it finds with a matching name. For example, "Arial, Helvetica, serif".',
+                'coust', 'description'),
+            'string'
+        )
+        ,('cat.spine.line.width',
+            oils_i18n_gettext('cat.spine.line.width',
+                'Cataloging: Spine label line width', 'coust', 'label'),
+            oils_i18n_gettext('cat.spine.line.width',
+                'Set the default line width for spine labels in number of characters. This specifies the boundary at which lines must be wrapped.',
+                'coust', 'description'),
+            'integer'
+        )
+        ,('cat.spine.line.height',
+            oils_i18n_gettext('cat.spine.line.height',
+                'Cataloging: Spine label maximum lines', 'coust', 'label'),
+            oils_i18n_gettext('cat.spine.line.height',
+                'Set the default maximum number of lines for spine labels.',
+                'coust', 'description'),
+            'integer'
+        )
+        ,('cat.spine.line.margin',
+            oils_i18n_gettext('cat.spine.line.margin',
+                'Cataloging: Spine label left margin', 'coust', 'label'),
+            oils_i18n_gettext('cat.spine.line.margin',
+                'Set the left margin for spine labels in number of characters.',
+                'coust', 'description'),
+            'integer'
+        )
+        ,('cat.label.font.weight',
+            oils_i18n_gettext('cat.label.font.weight',
+                'Cataloging: Spine and pocket label font weight', 'coust', 'label'),
+            oils_i18n_gettext('cat.label.font.weight',
+                'Set the preferred font weight for spine and pocket labels. You can specify "normal", "bold", "bolder", or "lighter".',
+                'coust', 'description'),
+            'string'
+        )
+;
+
+INSERT INTO actor.org_unit_setting (org_unit, name, value) VALUES
+    (1, 'cat.spine.line.margin', 0)
+    ,(1, 'cat.spine.line.height', 9)
+    ,(1, 'cat.spine.line.width', 8)
+    ,(1, 'cat.label.font.family', '"monospace"')
+    ,(1, 'cat.label.font.size', 10)
+    ,(1, 'cat.label.font.weight', '"normal"')
+;
+
+-- 0383.data.org-setting-circ.do_not_tally_claims_returned.sql
+
+INSERT INTO config.org_unit_setting_type ( name, label, description, datatype ) VALUES (
+        'circ.do_not_tally_claims_returned',
+        oils_i18n_gettext(
+            'circ.do_not_tally_claims_returned',
+            'Circulation: Do not include outstanding Claims Returned circulations in lump sum tallies in Patron Display.', 
+            'coust', 
+            'label'),
+        oils_i18n_gettext(
+            'circ.do_not_tally_claims_returned',
+            'In the Patron Display interface, the number of total active circulations for a given patron is presented in the Summary sidebar and underneath the Items Out navigation button.  This setting will prevent Claims Returned circulations from counting toward these tallies.',
+            'coust', 
+            'description'),
+        'bool'
+);
+
+-- 0384.data.hold_pull_list_template.sql
+
+INSERT INTO action_trigger.hook (key,core_type,description,passive) 
+    VALUES (   
+        'ahr.format.pull_list',
+        'ahr', 
+        oils_i18n_gettext(
+            'ahr.format.pull_list',
+            'Format holds pull list for printing',
+            'ath',
+            'description'
+        ), 
+        FALSE
+    );
+
+INSERT INTO action_trigger.event_definition (
+        id,
+        active,
+        owner,
+        name,
+        hook,
+        validator,
+        reactor,
+        group_field,
+        granularity,
+        template
+    ) VALUES (
+        35,
+        TRUE,
+        1,
+        'Holds Pull List',
+        'ahr.format.pull_list',
+        'NOOP_True',
+        'ProcessTemplate',
+        'pickup_lib',
+        'print-on-demand',
+$$
+[%- USE date -%]
+<style>
+    table { border-collapse: collapse; } 
+    td { padding: 5px; border-bottom: 1px solid #888; } 
+    th { font-weight: bold; }
+</style>
+[% 
+    # Sort the holds into copy-location buckets
+    # In the main print loop, sort each bucket by callnumber before printing
+    SET holds_list = [];
+    SET loc_data = [];
+    SET current_location = target.0.current_copy.location.id;
+    FOR hold IN target;
+        IF current_location != hold.current_copy.location.id;
+            SET current_location = hold.current_copy.location.id;
+            holds_list.push(loc_data);
+            SET loc_data = [];
+        END;
+        SET hold_data = {
+            'hold' => hold,
+            'callnumber' => hold.current_copy.call_number.label
+        };
+        loc_data.push(hold_data);
+    END;
+    holds_list.push(loc_data)
+%]
+<table>
+    <thead>
+        <tr>
+            <th>Title</th>
+            <th>Author</th>
+            <th>Shelving Location</th>
+            <th>Call Number</th>
+            <th>Barcode</th>
+            <th>Patron</th>
+        </tr>
+    </thead>
+    <tbody>
+    [% FOR loc_data IN holds_list  %]
+        [% FOR hold_data IN loc_data.sort('callnumber') %]
+            [% 
+                SET hold = hold_data.hold;
+                SET copy_data = helpers.get_copy_bib_basics(hold.current_copy.id);
+            %]
+            <tr>
+                <td>[% copy_data.title | truncate %]</td>
+                <td>[% copy_data.author | truncate %]</td>
+                <td>[% hold.current_copy.location.name %]</td>
+                <td>[% hold.current_copy.call_number.label %]</td>
+                <td>[% hold.current_copy.barcode %]</td>
+                <td>[% hold.usr.card.barcode %]</td>
+            </tr>
+        [% END %]
+    [% END %]
+    <tbody>
+</table>
+$$
+);
+
+INSERT INTO action_trigger.environment (
+        event_def,
+        path
+    ) VALUES
+        (35, 'current_copy.location'),
+        (35, 'current_copy.call_number'),
+        (35, 'usr.card'),
+        (35, 'pickup_lib')
+;
+
+-- 0386.data.org-setting-patron-clone-copy-addr.sql
+
+INSERT INTO config.org_unit_setting_type ( name, label, description, datatype ) VALUES (
+        'circ.patron_edit.clone.copy_address',
+        oils_i18n_gettext(
+            'circ.patron_edit.clone.copy_address',
+            'Patron Registration: Cloned patrons get address copy',
+            'coust', 
+            'label'
+        ),
+        oils_i18n_gettext(
+            'circ.patron_edit.clone.copy_address',
+            'In the Patron editor, copy addresses from the cloned user instead of linking directly to the address',
+            'coust', 
+            'description'
+        ),
+        'bool'
+);
+
+-- 0388.data.org-setting-ui.patron.editor_defaults.sql
+
+INSERT INTO config.org_unit_setting_type ( name, label, description, datatype, fm_class ) VALUES (
+        'ui.patron.default_ident_type',
+        oils_i18n_gettext(
+            'ui.patron.default_ident_type',
+            'GUI: Default Ident Type for Patron Registration', 
+            'coust', 
+            'label'),
+        oils_i18n_gettext(
+            'ui.patron.default_ident_type',
+            'This is the default Ident Type for new users in the patron editor.',
+            'coust', 
+            'description'),
+        'link',
+        'cit'
+);
+
+INSERT INTO config.org_unit_setting_type ( name, label, description, datatype ) VALUES (
+        'ui.patron.default_country',
+        oils_i18n_gettext(
+            'ui.patron.default_country',
+            'GUI: Default Country for New Addresses in Patron Editor', 
+            'coust', 
+            'label'),
+        oils_i18n_gettext(
+            'ui.patron.default_country',
+            'This is the default Country for new addresses in the patron editor.',
+            'coust', 
+            'description'),
+        'string'
+);
+
+-- 0392.data.org-setting-ui.patron.editor_address_requirement.sql
+
+INSERT INTO config.org_unit_setting_type ( name, label, description, datatype ) VALUES (
+        'ui.patron.registration.require_address',
+        oils_i18n_gettext(
+            'ui.patron.registration.require_address',
+            'GUI: Require at least one address for Patron Registration', 
+            'coust', 
+            'label'),
+        oils_i18n_gettext(
+            'ui.patron.registration.require_address',
+            'Enforces a requirement for having at least one address for a patron during registration.',
+            'coust', 
+            'description'),
+        'bool'
+);
+
+-- 0412.data.trigger.validator.HoldIsCancelled.sql
+
+INSERT INTO action_trigger.validator (module, description) VALUES (
+    'HoldIsCancelled',
+    oils_i18n_gettext(
+        'HoldIsCancelled',
+        'Check whether a hold request is cancelled.',
+        'atval',
+        'description'
+    )
+);
+
+

Copied: branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0376.data.merge_auth_perms.sql (from rev 17886, trunk/Open-ILS/src/sql/Pg/upgrade/0376.data.merge_auth_perms.sql)
===================================================================
--- branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0376.data.merge_auth_perms.sql	                        (rev 0)
+++ branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0376.data.merge_auth_perms.sql	2010-10-18 13:46:56 UTC (rev 18371)
@@ -0,0 +1,6 @@
+INSERT INTO config.upgrade_log (version) VALUES ('0376'); -- dbs
+
+-- Permission for merging auth records may already be defined
+-- so we do it outside of a transaction
+INSERT INTO permission.perm_list (code, description) VALUES ('MERGE_AUTH_RECORDS', 'Allow a user to merge authority records together');
+INSERT INTO permission.grp_perm_map (grp, perm, depth, grantable) VALUES (4, (SELECT id FROM permission.perm_list WHERE code = 'MERGE_AUTH_RECORDS'), 1, false);

Copied: branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0377.schema.actor.card.barcode-lower-index.sql (from rev 17886, trunk/Open-ILS/src/sql/Pg/upgrade/0377.schema.actor.card.barcode-lower-index.sql)
===================================================================
--- branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0377.schema.actor.card.barcode-lower-index.sql	                        (rev 0)
+++ branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0377.schema.actor.card.barcode-lower-index.sql	2010-10-18 13:46:56 UTC (rev 18371)
@@ -0,0 +1,4 @@
+
+INSERT INTO config.upgrade_log (version) VALUES ('0377'); -- miker .. no xact needed
+CREATE INDEX actor_card_barcode_lower_idx ON actor.card (lower(barcode));
+

Copied: branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0378.data.fix_org_unit_setting_types.sql (from rev 17886, trunk/Open-ILS/src/sql/Pg/upgrade/0378.data.fix_org_unit_setting_types.sql)
===================================================================
--- branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0378.data.fix_org_unit_setting_types.sql	                        (rev 0)
+++ branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0378.data.fix_org_unit_setting_types.sql	2010-10-18 13:46:56 UTC (rev 18371)
@@ -0,0 +1,39 @@
+BEGIN;
+
+INSERT INTO config.upgrade_log (version) VALUES ('0378'); -- Scott McKellar
+
+UPDATE config.org_unit_setting_type
+SET label = oils_i18n_gettext(
+	'acq.fund.balance_limit.block',
+	'Fund Spending Limit for Block',
+	'coust',
+	'label')
+WHERE name = 'acq.fund.balance_limit.block';
+
+UPDATE config.org_unit_setting_type
+SET label = oils_i18n_gettext(
+	'serial.prev_issuance_copy_location',
+	'Serials: Previous Issuance Copy Location',
+	'coust',
+	'label'),
+	description = oils_i18n_gettext(
+	'serial.prev_issuance_copy_location',
+	'When a serial issuance is received, copies (units) of the previous issuance will be automatically moved into the configured shelving location',
+	'coust',
+	'description')
+WHERE name = 'serial.prev_issuance_copy_location';
+
+UPDATE config.org_unit_setting_type
+SET label = oils_i18n_gettext(
+	'cat.default_classification_scheme',
+	'Cataloging: Default Classification Scheme',
+	'coust',
+	'label'),
+	description = oils_i18n_gettext(
+	'cat.default_classification_scheme',
+	'Defines the default classification scheme for new call numbers: 1 = Generic; 2 = Dewey; 3 = LC',
+	'coust',
+	'description')
+WHERE name = 'cat.default_classification_scheme';
+
+COMMIT;

Copied: branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0379.data.org-setting-circ.missing_pieces.copy_status.sql (from rev 17886, trunk/Open-ILS/src/sql/Pg/upgrade/0379.data.org-setting-circ.missing_pieces.copy_status.sql)
===================================================================
--- branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0379.data.org-setting-circ.missing_pieces.copy_status.sql	                        (rev 0)
+++ branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0379.data.org-setting-circ.missing_pieces.copy_status.sql	2010-10-18 13:46:56 UTC (rev 18371)
@@ -0,0 +1,21 @@
+BEGIN;
+
+INSERT INTO config.upgrade_log (version) VALUES ('0379'); -- phasefx
+
+INSERT INTO config.org_unit_setting_type ( name, label, description, datatype, fm_class ) VALUES (
+        'circ.missing_pieces.copy_status',
+        oils_i18n_gettext(
+            'circ.missing_pieces.copy_status',
+            'Circulation: Item Status for Missing Pieces', 
+            'coust', 
+            'label'),
+        oils_i18n_gettext(
+            'circ.missing_pieces.copy_status',
+            'This is the Item Status to use for items that have been marked or scanned as having Missing Pieces.  In absense of this setting, the Damaged status is used.',
+            'coust', 
+            'description'),
+        'link',
+        'ccs'
+);
+
+COMMIT;

Copied: branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0380.data.spine_label.sql (from rev 17886, trunk/Open-ILS/src/sql/Pg/upgrade/0380.data.spine_label.sql)
===================================================================
--- branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0380.data.spine_label.sql	                        (rev 0)
+++ branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0380.data.spine_label.sql	2010-10-18 13:46:56 UTC (rev 18371)
@@ -0,0 +1,56 @@
+BEGIN;
+
+INSERT INTO config.upgrade_log (version) VALUES ('0380'); -- dbs
+
+INSERT INTO config.org_unit_setting_type (name, label, description, datatype)
+    VALUES
+        ('cat.label.font.size',
+            oils_i18n_gettext('cat.label.font.size',
+                'Cataloging: Spine and pocket label font size', 'coust', 'label'),
+            oils_i18n_gettext('cat.label.font.size',
+                'Set the default font size for spine and pocket labels', 'coust', 'description'),
+            'integer'
+        )
+        ,('cat.label.font.family',
+            oils_i18n_gettext('cat.label.font.family',
+                'Cataloging: Spine and pocket label font family', 'coust', 'label'),
+            oils_i18n_gettext('cat.label.font.family',
+                'Set the preferred font family for spine and pocket labels. You can specify a list of fonts, separated by commas, in order of preference; the system will use the first font it finds with a matching name. For example, "Arial, Helvetica, serif".',
+                'coust', 'description'),
+            'string'
+        )
+        ,('cat.spine.line.width',
+            oils_i18n_gettext('cat.spine.line.width',
+                'Cataloging: Spine label line width', 'coust', 'label'),
+            oils_i18n_gettext('cat.spine.line.width',
+                'Set the default line width for spine labels in number of characters. This specifies the boundary at which lines must be wrapped.',
+                'coust', 'description'),
+            'integer'
+        )
+        ,('cat.spine.line.height',
+            oils_i18n_gettext('cat.spine.line.height',
+                'Cataloging: Spine label maximum lines', 'coust', 'label'),
+            oils_i18n_gettext('cat.spine.line.height',
+                'Set the default maximum number of lines for spine labels.',
+                'coust', 'description'),
+            'integer'
+        )
+        ,('cat.spine.line.margin',
+            oils_i18n_gettext('cat.spine.line.margin',
+                'Cataloging: Spine label left margin', 'coust', 'label'),
+            oils_i18n_gettext('cat.spine.line.margin',
+                'Set the left margin for spine labels in number of characters.',
+                'coust', 'description'),
+            'integer'
+        )
+;
+
+INSERT INTO actor.org_unit_setting (org_unit, name, value) VALUES
+    (1, 'cat.spine.line.margin', 0)
+    ,(1, 'cat.spine.line.height', 9)
+    ,(1, 'cat.spine.line.width', 8)
+    ,(1, 'cat.label.font.family', '"monospace"')
+    ,(1, 'cat.label.font.size', 10)
+;
+
+COMMIT;

Copied: branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0381.data.spine_label_font_weight.sql (from rev 17886, trunk/Open-ILS/src/sql/Pg/upgrade/0381.data.spine_label_font_weight.sql)
===================================================================
--- branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0381.data.spine_label_font_weight.sql	                        (rev 0)
+++ branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0381.data.spine_label_font_weight.sql	2010-10-18 13:46:56 UTC (rev 18371)
@@ -0,0 +1,21 @@
+BEGIN;
+
+INSERT INTO config.upgrade_log (version) VALUES ('0381'); -- dbs
+
+INSERT INTO config.org_unit_setting_type (name, label, description, datatype)
+    VALUES
+        ('cat.label.font.weight',
+            oils_i18n_gettext('cat.label.font.weight',
+                'Cataloging: Spine and pocket label font weight', 'coust', 'label'),
+            oils_i18n_gettext('cat.label.font.weight',
+                'Set the preferred font weight for spine and pocket labels. You can specify "normal", "bold", "bolder", or "lighter".',
+                'coust', 'description'),
+            'string'
+        )
+;
+
+INSERT INTO actor.org_unit_setting (org_unit, name, value) VALUES
+    (1, 'cat.label.font.weight', '"normal"')
+;
+
+COMMIT;

Copied: branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0382.schema.asset_copy_location_callnums.sql (from rev 17886, trunk/Open-ILS/src/sql/Pg/upgrade/0382.schema.asset_copy_location_callnums.sql)
===================================================================
--- branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0382.schema.asset_copy_location_callnums.sql	                        (rev 0)
+++ branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0382.schema.asset_copy_location_callnums.sql	2010-10-18 13:46:56 UTC (rev 18371)
@@ -0,0 +1,10 @@
+BEGIN;
+
+INSERT INTO config.upgrade_log (version) VALUES ('0382'); -- dbs
+
+-- Start picking up call number label prefixes and suffixes
+-- from asset.copy_location
+ALTER TABLE asset.copy_location ADD COLUMN label_prefix TEXT;
+ALTER TABLE asset.copy_location ADD COLUMN label_suffix TEXT;
+
+COMMIT;

Copied: branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0383.data.org-setting-circ.do_not_tally_claims_returned.sql (from rev 17886, trunk/Open-ILS/src/sql/Pg/upgrade/0383.data.org-setting-circ.do_not_tally_claims_returned.sql)
===================================================================
--- branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0383.data.org-setting-circ.do_not_tally_claims_returned.sql	                        (rev 0)
+++ branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0383.data.org-setting-circ.do_not_tally_claims_returned.sql	2010-10-18 13:46:56 UTC (rev 18371)
@@ -0,0 +1,20 @@
+BEGIN;
+
+INSERT INTO config.upgrade_log (version) VALUES ('0383'); -- phasefx
+
+INSERT INTO config.org_unit_setting_type ( name, label, description, datatype ) VALUES (
+        'circ.do_not_tally_claims_returned',
+        oils_i18n_gettext(
+            'circ.do_not_tally_claims_returned',
+            'Circulation: Do not include outstanding Claims Returned circulations in lump sum tallies in Patron Display.', 
+            'coust', 
+            'label'),
+        oils_i18n_gettext(
+            'circ.do_not_tally_claims_returned',
+            'In the Patron Display interface, the number of total active circulations for a given patron is presented in the Summary sidebar and underneath the Items Out navigation button.  This setting will prevent Claims Returned circulations from counting toward these tallies.',
+            'coust', 
+            'description'),
+        'bool'
+);
+
+COMMIT;

Copied: branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0384.data.hold_pull_list_template.sql (from rev 17886, trunk/Open-ILS/src/sql/Pg/upgrade/0384.data.hold_pull_list_template.sql)
===================================================================
--- branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0384.data.hold_pull_list_template.sql	                        (rev 0)
+++ branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0384.data.hold_pull_list_template.sql	2010-10-18 13:46:56 UTC (rev 18371)
@@ -0,0 +1,112 @@
+BEGIN;
+
+INSERT INTO config.upgrade_log (version) VALUES ('0384');
+
+INSERT INTO action_trigger.hook (key,core_type,description,passive) 
+    VALUES (   
+        'ahr.format.pull_list',
+        'ahr', 
+        oils_i18n_gettext(
+            'ahr.format.pull_list',
+            'Format holds pull list for printing',
+            'ath',
+            'description'
+        ), 
+        FALSE
+    );
+
+INSERT INTO action_trigger.event_definition (
+        id,
+        active,
+        owner,
+        name,
+        hook,
+        validator,
+        reactor,
+        group_field,
+        granularity,
+        template
+    ) VALUES (
+        35,
+        TRUE,
+        1,
+        'Holds Pull List',
+        'ahr.format.pull_list',
+        'NOOP_True',
+        'ProcessTemplate',
+        'pickup_lib',
+        'print-on-demand',
+$$
+[%- USE date -%]
+<style>
+    table { border-collapse: collapse; } 
+    td { padding: 5px; border-bottom: 1px solid #888; } 
+    th { font-weight: bold; }
+</style>
+[% 
+    # Sort the holds into copy-location buckets
+    # In the main print loop, sort each bucket by callnumber before printing
+    SET holds_list = [];
+    SET loc_data = [];
+    SET current_location = target.0.current_copy.location.id;
+    FOR hold IN target;
+        IF current_location != hold.current_copy.location.id;
+            SET current_location = hold.current_copy.location.id;
+            holds_list.push(loc_data);
+            SET loc_data = [];
+        END;
+        SET hold_data = {
+            'hold' => hold,
+            'callnumber' => hold.current_copy.call_number.label
+        };
+        loc_data.push(hold_data);
+    END;
+    holds_list.push(loc_data)
+%]
+<table>
+    <thead>
+        <tr>
+            <th>Title</th>
+            <th>Author</th>
+            <th>Shelving Location</th>
+            <th>Call Number</th>
+            <th>Barcode</th>
+            <th>Patron</th>
+        </tr>
+    </thead>
+    <tbody>
+    [% FOR loc_data IN holds_list  %]
+        [% FOR hold_data IN loc_data.sort('callnumber') %]
+            [% 
+                SET hold = hold_data.hold;
+                SET copy_data = helpers.get_copy_bib_basics(hold.current_copy.id);
+            %]
+            <tr>
+                <td>[% copy_data.title | truncate %]</td>
+                <td>[% copy_data.author | truncate %]</td>
+                <td>[% hold.current_copy.location.name %]</td>
+                <td>[% hold.current_copy.call_number.label %]</td>
+                <td>[% hold.current_copy.barcode %]</td>
+                <td>[% hold.usr.card.barcode %]</td>
+            </tr>
+        [% END %]
+    [% END %]
+    <tbody>
+</table>
+$$
+);
+
+INSERT INTO action_trigger.environment (
+        event_def,
+        path
+    ) VALUES
+        (35, 'current_copy.location'),
+        (35, 'current_copy.call_number'),
+        (35, 'usr.card'),
+        (35, 'pickup_lib')
+;
+
+-- DELETE FROM config.upgrade_log WHERE version = 'tmp'; DELETE FROM action_trigger.event WHERE event_def IN (35); DELETE FROM action_trigger.environment WHERE event_def IN (35); DELETE FROM action_trigger.event_definition WHERE id IN (35); DELETE FROM action_trigger.hook WHERE key IN ( 'ahr.format.pull_list' );
+
+COMMIT;
+

Copied: branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0385.schema.perm_list_fkeys.sql (from rev 17886, trunk/Open-ILS/src/sql/Pg/upgrade/0385.schema.perm_list_fkeys.sql)
===================================================================
--- branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0385.schema.perm_list_fkeys.sql	                        (rev 0)
+++ branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0385.schema.perm_list_fkeys.sql	2010-10-18 13:46:56 UTC (rev 18371)
@@ -0,0 +1,28 @@
+
+-- First drop the stuff we are going to (re)create.  If it fails for not existing, fine.
+-- Some constraints might have different names, so we try all of them.
+ALTER TABLE permission.grp_perm_map        DROP CONSTRAINT grp_perm_map_perm_fkey;
+ALTER TABLE permission.usr_perm_map        DROP CONSTRAINT usr_perm_map_perm_fkey;
+ALTER TABLE permission.usr_object_perm_map DROP CONSTRAINT usr_object_perm_map_perm_fkey;
+
+ALTER TABLE config.org_unit_setting_type   DROP CONSTRAINT view_perm_fkey;
+ALTER TABLE config.org_unit_setting_type   DROP CONSTRAINT update_perm_fkey;
+ALTER TABLE config.org_unit_setting_type   DROP CONSTRAINT org_unit_setting_type_view_perm_fkey;    -- alternate name
+ALTER TABLE config.org_unit_setting_type   DROP CONSTRAINT org_unit_setting_type_update_perm_fkey;  -- alternate name
+
+
+BEGIN;
+
+INSERT INTO config.upgrade_log (version) VALUES ('0385'); --gmc
+
+ALTER TABLE permission.grp_perm_map ADD CONSTRAINT grp_perm_map_perm_fkey FOREIGN KEY (perm)
+    REFERENCES permission.perm_list (id) ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
+ALTER TABLE permission.usr_perm_map ADD CONSTRAINT usr_perm_map_perm_fkey FOREIGN KEY (perm)
+    REFERENCES permission.perm_list (id) ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
+ALTER TABLE permission.usr_object_perm_map ADD CONSTRAINT usr_object_perm_map_perm_fkey FOREIGN KEY (perm)
+    REFERENCES permission.perm_list (id) ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
+
+ALTER TABLE config.org_unit_setting_type ADD CONSTRAINT view_perm_fkey   FOREIGN KEY (view_perm  ) REFERENCES permission.perm_list (id) ON UPDATE CASCADE ON DELETE SET NULL DEFERRABLE INITIALLY DEFERRED;
+ALTER TABLE config.org_unit_setting_type ADD CONSTRAINT update_perm_fkey FOREIGN KEY (update_perm) REFERENCES permission.perm_list (id) ON UPDATE CASCADE DEFERRABLE INITIALLY DEFERRED;
+
+COMMIT;

Copied: branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0386.data.org-setting-patron-clone-copy-addr.sql (from rev 17886, trunk/Open-ILS/src/sql/Pg/upgrade/0386.data.org-setting-patron-clone-copy-addr.sql)
===================================================================
--- branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0386.data.org-setting-patron-clone-copy-addr.sql	                        (rev 0)
+++ branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0386.data.org-setting-patron-clone-copy-addr.sql	2010-10-18 13:46:56 UTC (rev 18371)
@@ -0,0 +1,22 @@
+BEGIN;
+
+INSERT INTO config.upgrade_log (version) VALUES ('0386');
+
+INSERT INTO config.org_unit_setting_type ( name, label, description, datatype ) VALUES (
+        'circ.patron_edit.clone.copy_address',
+        oils_i18n_gettext(
+            'circ.patron_edit.clone.copy_address',
+            'Patron Registration: Cloned patrons get address copy',
+            'coust', 
+            'label'
+        ),
+        oils_i18n_gettext(
+            'circ.patron_edit.clone.copy_address',
+            'In the Patron editor, copy addresses from the cloned user instead of linking directly to the address',
+            'coust', 
+            'description'
+        ),
+        'bool'
+);
+
+COMMIT;

Copied: branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0387.schema.perm_list_fkeys_restrict_delete.sql (from rev 17886, trunk/Open-ILS/src/sql/Pg/upgrade/0387.schema.perm_list_fkeys_restrict_delete.sql)
===================================================================
--- branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0387.schema.perm_list_fkeys_restrict_delete.sql	                        (rev 0)
+++ branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0387.schema.perm_list_fkeys_restrict_delete.sql	2010-10-18 13:46:56 UTC (rev 18371)
@@ -0,0 +1,22 @@
+
+-- First drop the stuff we are going to (re)create.  If it fails for not existing, fine.
+
+ALTER TABLE permission.grp_perm_map        DROP CONSTRAINT grp_perm_map_perm_fkey;
+ALTER TABLE permission.usr_perm_map        DROP CONSTRAINT usr_perm_map_perm_fkey;
+ALTER TABLE permission.usr_object_perm_map DROP CONSTRAINT usr_object_perm_map_perm_fkey;
+ALTER TABLE config.org_unit_setting_type   DROP CONSTRAINT view_perm_fkey;
+
+BEGIN;
+
+INSERT INTO config.upgrade_log (version) VALUES ('0387'); --gmc
+
+ALTER TABLE permission.grp_perm_map ADD CONSTRAINT grp_perm_map_perm_fkey FOREIGN KEY (perm)
+    REFERENCES permission.perm_list (id) ON UPDATE CASCADE ON DELETE RESTRICT DEFERRABLE INITIALLY DEFERRED;
+ALTER TABLE permission.usr_perm_map ADD CONSTRAINT usr_perm_map_perm_fkey FOREIGN KEY (perm)
+    REFERENCES permission.perm_list (id) ON UPDATE CASCADE ON DELETE RESTRICT DEFERRABLE INITIALLY DEFERRED;
+ALTER TABLE permission.usr_object_perm_map ADD CONSTRAINT usr_object_perm_map_perm_fkey FOREIGN KEY (perm)
+    REFERENCES permission.perm_list (id) ON UPDATE CASCADE ON DELETE RESTRICT DEFERRABLE INITIALLY DEFERRED;
+
+ALTER TABLE config.org_unit_setting_type ADD CONSTRAINT view_perm_fkey FOREIGN KEY (view_perm) REFERENCES permission.perm_list (id) ON UPDATE CASCADE ON DELETE RESTRICT DEFERRABLE INITIALLY DEFERRED;
+
+COMMIT;

Copied: branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0388.data.org-setting-ui.patron.editor_defaults.sql (from rev 17886, trunk/Open-ILS/src/sql/Pg/upgrade/0388.data.org-setting-ui.patron.editor_defaults.sql)
===================================================================
--- branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0388.data.org-setting-ui.patron.editor_defaults.sql	                        (rev 0)
+++ branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0388.data.org-setting-ui.patron.editor_defaults.sql	2010-10-18 13:46:56 UTC (rev 18371)
@@ -0,0 +1,36 @@
+BEGIN;
+
+INSERT INTO config.upgrade_log (version) VALUES ('0388'); -- phasefx
+
+INSERT INTO config.org_unit_setting_type ( name, label, description, datatype, fm_class ) VALUES (
+        'ui.patron.default_ident_type',
+        oils_i18n_gettext(
+            'ui.patron.default_ident_type',
+            'GUI: Default Ident Type for Patron Registration', 
+            'coust', 
+            'label'),
+        oils_i18n_gettext(
+            'ui.patron.default_ident_type',
+            'This is the default Ident Type for new users in the patron editor.',
+            'coust', 
+            'description'),
+        'link',
+        'cit'
+);
+
+INSERT INTO config.org_unit_setting_type ( name, label, description, datatype ) VALUES (
+        'ui.patron.default_country',
+        oils_i18n_gettext(
+            'ui.patron.default_country',
+            'GUI: Default Country for New Addresses in Patron Editor', 
+            'coust', 
+            'label'),
+        oils_i18n_gettext(
+            'ui.patron.default_country',
+            'This is the default Country for new addresses in the patron editor.',
+            'coust', 
+            'description'),
+        'string'
+);
+
+COMMIT;

Copied: branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0389.data.issuance-holds.sql (from rev 17886, trunk/Open-ILS/src/sql/Pg/upgrade/0389.data.issuance-holds.sql)
===================================================================
--- branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0389.data.issuance-holds.sql	                        (rev 0)
+++ branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0389.data.issuance-holds.sql	2010-10-18 13:46:56 UTC (rev 18371)
@@ -0,0 +1,21 @@
+BEGIN;
+
+INSERT INTO config.upgrade_log (version) VALUES ('0389'); -- miker
+
+-- Making this a global_flag (UI accessible) instead of an internal_flag
+INSERT INTO config.global_flag (name, label, enabled)
+    VALUES (
+        'circ.holds.empty_issuance_ok',
+        oils_i18n_gettext(
+            'circ.holds.empty_issuance_ok',
+            'Holds: Allow holds on empty issuances',
+            'cgf',
+            'label'
+        ),
+        TRUE
+    );
+
+INSERT INTO permission.perm_list (code, description) VALUES ('ISSUANCE_HOLDS', 'Allow a user to place holds on serials issuances');
+
+COMMIT;
+

Copied: branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0390.schema.usrgroup-index.sql (from rev 17886, trunk/Open-ILS/src/sql/Pg/upgrade/0390.schema.usrgroup-index.sql)
===================================================================
--- branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0390.schema.usrgroup-index.sql	                        (rev 0)
+++ branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0390.schema.usrgroup-index.sql	2010-10-18 13:46:56 UTC (rev 18371)
@@ -0,0 +1,7 @@
+BEGIN;
+
+INSERT INTO config.upgrade_log (version) VALUES ('0390'); -- miker
+CREATE INDEX actor_usr_usrgroup_idx ON actor.usr (usrgroup);
+
+COMMIT;
+

Copied: branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0391.schema.copy_note_owner_index.sql (from rev 17886, trunk/Open-ILS/src/sql/Pg/upgrade/0391.schema.copy_note_owner_index.sql)
===================================================================
--- branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0391.schema.copy_note_owner_index.sql	                        (rev 0)
+++ branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0391.schema.copy_note_owner_index.sql	2010-10-18 13:46:56 UTC (rev 18371)
@@ -0,0 +1,7 @@
+BEGIN;
+
+INSERT INTO config.upgrade_log (version) VALUES ('0391'); -- miker
+CREATE INDEX asset_copy_note_owning_copy_idx ON asset.copy_note ( owning_copy );
+
+COMMIT;
+

Copied: branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0392.data.org-setting-ui.patron.editor_address_requirement.sql (from rev 17886, trunk/Open-ILS/src/sql/Pg/upgrade/0392.data.org-setting-ui.patron.editor_address_requirement.sql)
===================================================================
--- branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0392.data.org-setting-ui.patron.editor_address_requirement.sql	                        (rev 0)
+++ branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0392.data.org-setting-ui.patron.editor_address_requirement.sql	2010-10-18 13:46:56 UTC (rev 18371)
@@ -0,0 +1,20 @@
+BEGIN;
+
+INSERT INTO config.upgrade_log (version) VALUES ('0392'); -- phasefx
+
+INSERT INTO config.org_unit_setting_type ( name, label, description, datatype ) VALUES (
+        'ui.patron.registration.require_address',
+        oils_i18n_gettext(
+            'ui.patron.registration.require_address',
+            'GUI: Require at least one address for Patron Registration', 
+            'coust', 
+            'label'),
+        oils_i18n_gettext(
+            'ui.patron.registration.require_address',
+            'Enforces a requirement for having at least one address for a patron during registration.',
+            'coust', 
+            'description'),
+        'bool'
+);
+
+COMMIT;

Copied: branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0393.schema.perm-id-change-i18n-protection.sql (from rev 17886, trunk/Open-ILS/src/sql/Pg/upgrade/0393.schema.perm-id-change-i18n-protection.sql)
===================================================================
--- branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0393.schema.perm-id-change-i18n-protection.sql	                        (rev 0)
+++ branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0393.schema.perm-id-change-i18n-protection.sql	2010-10-18 13:46:56 UTC (rev 18371)
@@ -0,0 +1,38 @@
+BEGIN;
+
+INSERT INTO config.upgrade_log (version) VALUES ('0393'); -- miker
+
+CREATE OR REPLACE FUNCTION oils_i18n_update_apply(old_ident TEXT, new_ident TEXT, hint TEXT) RETURNS VOID AS $_$
+BEGIN
+
+    EXECUTE $$
+        UPDATE  config.i18n_core
+          SET   identity_value = $$ || new_ident || $$ 
+          WHERE fq_field LIKE '$$ || hint || $$.%' 
+                AND identity_value = $$ || old_ident || $$;$$;
+
+    RETURN;
+
+END;
+$_$ LANGUAGE PLPGSQL;
+
+CREATE OR REPLACE FUNCTION oils_i18n_id_tracking(/* hint */) RETURNS TRIGGER AS $_$
+BEGIN
+    PERFORM oils_i18n_update_apply( OLD.id::TEXT, NEW.id::TEXT, TG_ARGV[0]::TEXT );
+    RETURN NEW;
+END;
+$_$ LANGUAGE PLPGSQL;
+
+CREATE OR REPLACE FUNCTION oils_i18n_code_tracking(/* hint */) RETURNS TRIGGER AS $_$
+BEGIN
+    PERFORM oils_i18n_update_apply( OLD.code::TEXT, NEW.code::TEXT, TG_ARGV[0]::TEXT );
+    RETURN NEW;
+END;
+$_$ LANGUAGE PLPGSQL;
+
+
+CREATE TRIGGER maintain_perm_i18n_tgr
+    AFTER UPDATE ON permission.perm_list
+    FOR EACH ROW EXECUTE PROCEDURE oils_i18n_id_tracking('ppl');
+
+COMMIT;

Copied: branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0394.data.org-setting-cat.default_classification_scheme.sql (from rev 17886, trunk/Open-ILS/src/sql/Pg/upgrade/0394.data.org-setting-cat.default_classification_scheme.sql)
===================================================================
--- branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0394.data.org-setting-cat.default_classification_scheme.sql	                        (rev 0)
+++ branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0394.data.org-setting-cat.default_classification_scheme.sql	2010-10-18 13:46:56 UTC (rev 18371)
@@ -0,0 +1,25 @@
+BEGIN;
+
+INSERT INTO config.upgrade_log (version) VALUES ('0394'); -- gmc
+
+INSERT INTO config.org_unit_setting_type ( name, label, description, datatype, fm_class )
+SELECT DISTINCT
+    'cat.default_classification_scheme',
+    oils_i18n_gettext(
+        'cat.default_classification_scheme',
+        'Cataloging: Default Classification Scheme',
+        'coust',
+        'label'
+    ),
+    oils_i18n_gettext(
+        'cat.default_classification_scheme',
+        'Defines the default classification scheme for new call numbers: 1 = Generic; 2 = Dewey; 3 = LC',
+        'coust',
+        'descripton'
+        ),
+    'link',
+    'acnc'
+FROM config.org_unit_setting_type
+WHERE NOT EXISTS (SELECT 1 FROM config.org_unit_setting_type WHERE name = 'cat.default_classification_scheme');
+
+COMMIT;

Copied: branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0395.schema.fix-i18n-fixer.sql (from rev 17886, trunk/Open-ILS/src/sql/Pg/upgrade/0395.schema.fix-i18n-fixer.sql)
===================================================================
--- branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0395.schema.fix-i18n-fixer.sql	                        (rev 0)
+++ branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0395.schema.fix-i18n-fixer.sql	2010-10-18 13:46:56 UTC (rev 18371)
@@ -0,0 +1,19 @@
+BEGIN;
+
+INSERT INTO config.upgrade_log (version) VALUES ('0395'); -- Scott McKellar
+
+CREATE OR REPLACE FUNCTION oils_i18n_update_apply(old_ident TEXT, new_ident TEXT, hint TEXT) RETURNS VOID AS $_$
+BEGIN
+
+    EXECUTE $$
+        UPDATE  config.i18n_core
+          SET   identity_value = $$ || quote_literal( new_ident ) || $$ 
+          WHERE fq_field LIKE '$$ || hint || $$.%' 
+                AND identity_value = $$ || quote_literal( old_ident ) || $$;$$;
+
+    RETURN;
+
+END;
+$_$ LANGUAGE PLPGSQL;
+
+COMMIT;

Copied: branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0396.data.org-setting-payflowpro.sql (from rev 17886, trunk/Open-ILS/src/sql/Pg/upgrade/0396.data.org-setting-payflowpro.sql)
===================================================================
--- branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0396.data.org-setting-payflowpro.sql	                        (rev 0)
+++ branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0396.data.org-setting-payflowpro.sql	2010-10-18 13:46:56 UTC (rev 18371)
@@ -0,0 +1,59 @@
+BEGIN;
+
+INSERT INTO config.upgrade_log (version) VALUES ('0396'); -- senator
+
+INSERT INTO permission.perm_list (code, description) VALUES
+    ('VIEW_CREDIT_CARD_PROCESSING',
+        'View org unit settings related to credit card processing'),
+    ('ADMIN_CREDIT_CARD_PROCESSING',
+        'Update org unit settings related to credit card processing');
+
+INSERT INTO config.org_unit_setting_type (
+    name, label, description, datatype
+) VALUES
+    ('credit.processor.payflowpro.enabled',
+        'Credit card processing: Enable PayflowPro payments',
+        'This is NOT the same thing as the settings labeled with just "PayPal."',
+        'bool'
+    ),
+    ('credit.processor.payflowpro.login',
+        'Credit card processing: PayflowPro login/merchant ID',
+        'Often the same thing as the PayPal manager login',
+        'string'
+    ),
+    ('credit.processor.payflowpro.password',
+        'Credit card processing: PayflowPro password',
+        'PayflowPro password',
+        'string'
+    ),
+    ('credit.processor.payflowpro.testmode',
+        'Credit card processing: PayflowPro test mode',
+        'Do not really process transactions, but stay in test mode - uses pilot-payflowpro.paypal.com instead of the usual host',
+        'bool'
+    ),
+    ('credit.processor.payflowpro.vendor',
+        'Credit card processing: PayflowPro vendor',
+        'Often the same thing as the login',
+        'string'
+    ),
+    ('credit.processor.payflowpro.partner',
+        'Credit card processing: PayflowPro partner',
+        'Often "PayPal" or "VeriSign", sometimes others',
+        'string'
+    );
+
+UPDATE config.org_unit_setting_type
+    SET description = 'This can be "AuthorizeNet", "PayPal" (for the Website Payment Pro API), or "PayflowPro".'
+    WHERE name = 'credit.processor.default';
+
+UPDATE config.org_unit_setting_type
+    SET view_perm = (SELECT id FROM permission.perm_list
+        WHERE code = 'VIEW_CREDIT_CARD_PROCESSING' LIMIT 1)
+    WHERE name LIKE 'credit.processor%' AND view_perm IS NULL;
+
+UPDATE config.org_unit_setting_type
+    SET update_perm = (SELECT id FROM permission.perm_list
+        WHERE code = 'ADMIN_CREDIT_CARD_PROCESSING' LIMIT 1)
+    WHERE name LIKE 'credit.processor%' AND update_perm IS NULL;
+
+COMMIT;

Copied: branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0397.data.coust.opac_fully_compresssed.sql (from rev 17886, trunk/Open-ILS/src/sql/Pg/upgrade/0397.data.coust.opac_fully_compresssed.sql)
===================================================================
--- branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0397.data.coust.opac_fully_compresssed.sql	                        (rev 0)
+++ branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0397.data.coust.opac_fully_compresssed.sql	2010-10-18 13:46:56 UTC (rev 18371)
@@ -0,0 +1,14 @@
+BEGIN;
+
+INSERT INTO config.upgrade_log (version) VALUES ('0397');
+
+INSERT INTO config.org_unit_setting_type (name, label, description, datatype)
+    VALUES (
+        'opac.fully_compressed_serial_holdings',
+        'OPAC: Use fully compressed serial holdings',
+        'Show fully compressed serial holdings for all libraries at and below
+        the current context unit',
+        'bool'
+    );
+
+COMMIT;

Copied: branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0398.schema.serials-indexes.sql (from rev 17886, trunk/Open-ILS/src/sql/Pg/upgrade/0398.schema.serials-indexes.sql)
===================================================================
--- branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0398.schema.serials-indexes.sql	                        (rev 0)
+++ branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0398.schema.serials-indexes.sql	2010-10-18 13:46:56 UTC (rev 18371)
@@ -0,0 +1,33 @@
+
+-- No transaction, just creating indexes if they don't exist
+
+INSERT INTO config.upgrade_log (version) VALUES ('0398'); -- miker
+
+CREATE INDEX serial_subscription_record_idx ON serial.subscription (record_entry);
+CREATE INDEX serial_subscription_owner_idx ON serial.subscription (owning_lib);
+CREATE INDEX serial_caption_and_pattern_sub_idx ON serial.caption_and_pattern (subscription);
+CREATE INDEX serial_distribution_sub_idx ON serial.distribution (subscription);
+CREATE INDEX serial_distribution_holding_lib_idx ON serial.distribution (holding_lib);
+CREATE INDEX serial_distribution_note_dist_idx ON serial.distribution_note (distribution);
+CREATE INDEX serial_stream_dist_idx ON serial.stream (distribution);
+CREATE INDEX serial_routing_list_user_stream_idx ON serial.routing_list_user (stream);
+CREATE INDEX serial_routing_list_user_reader_idx ON serial.routing_list_user (reader);
+CREATE INDEX serial_issuance_sub_idx ON serial.issuance (subscription);
+CREATE INDEX serial_issuance_caption_and_pattern_idx ON serial.issuance (caption_and_pattern);
+CREATE INDEX serial_issuance_date_published_idx ON serial.issuance (date_published);
+CREATE UNIQUE INDEX unit_barcode_key ON serial.unit (barcode) WHERE deleted = FALSE OR deleted IS FALSE;
+CREATE INDEX unit_cn_idx ON serial.unit (call_number);
+CREATE INDEX unit_avail_cn_idx ON serial.unit (call_number);
+CREATE INDEX unit_creator_idx  ON serial.unit ( creator );
+CREATE INDEX unit_editor_idx   ON serial.unit ( editor );
+CREATE INDEX serial_item_stream_idx ON serial.item (stream);
+CREATE INDEX serial_item_issuance_idx ON serial.item (issuance);
+CREATE INDEX serial_item_unit_idx ON serial.item (unit);
+CREATE INDEX serial_item_uri_idx ON serial.item (uri);
+CREATE INDEX serial_item_date_received_idx ON serial.item (date_received);
+CREATE INDEX serial_item_status_idx ON serial.item (status);
+CREATE INDEX serial_item_note_item_idx ON serial.item_note (item);
+CREATE INDEX serial_basic_summary_dist_idx ON serial.basic_summary (distribution);
+CREATE INDEX serial_supplement_summary_dist_idx ON serial.supplement_summary (distribution);
+CREATE INDEX serial_index_summary_dist_idx ON serial.index_summary (distribution);
+ 

Copied: branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0399.schema.strict-renewal-test.sql (from rev 17886, trunk/Open-ILS/src/sql/Pg/upgrade/0399.schema.strict-renewal-test.sql)
===================================================================
--- branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0399.schema.strict-renewal-test.sql	                        (rev 0)
+++ branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0399.schema.strict-renewal-test.sql	2010-10-18 13:46:56 UTC (rev 18371)
@@ -0,0 +1,109 @@
+
+BEGIN;
+
+INSERT INTO config.upgrade_log (version) VALUES ('0399'); -- miker
+
+CREATE OR REPLACE FUNCTION action.find_circ_matrix_matchpoint( context_ou INT, match_item BIGINT, match_user INT, renewal BOOL ) RETURNS config.circ_matrix_matchpoint AS $func$
+DECLARE
+    current_group    permission.grp_tree%ROWTYPE;
+    user_object    actor.usr%ROWTYPE;
+    item_object    asset.copy%ROWTYPE;
+    cn_object    asset.call_number%ROWTYPE;
+    rec_descriptor    metabib.rec_descriptor%ROWTYPE;
+    current_mp    config.circ_matrix_matchpoint%ROWTYPE;
+    matchpoint    config.circ_matrix_matchpoint%ROWTYPE;
+BEGIN
+    SELECT INTO user_object * FROM actor.usr WHERE id = match_user;
+    SELECT INTO item_object * FROM asset.copy WHERE id = match_item;
+    SELECT INTO cn_object * FROM asset.call_number WHERE id = item_object.call_number;
+    SELECT INTO rec_descriptor r.* FROM metabib.rec_descriptor r JOIN asset.call_number c USING (record) WHERE c.id = item_object.call_number;
+    SELECT INTO current_group * FROM permission.grp_tree WHERE id = user_object.profile;
+
+    LOOP 
+        -- for each potential matchpoint for this ou and group ...
+        FOR current_mp IN
+            SELECT  m.*
+              FROM  config.circ_matrix_matchpoint m
+                    JOIN actor.org_unit_ancestors( context_ou ) d ON (m.org_unit = d.id)
+                    LEFT JOIN actor.org_unit_proximity p ON (p.from_org = context_ou AND p.to_org = d.id)
+              WHERE m.grp = current_group.id
+                    AND m.active
+                    AND (m.copy_owning_lib IS NULL OR cn_object.owning_lib IN ( SELECT id FROM actor.org_unit_descendants(m.copy_owning_lib) ))
+                    AND (m.copy_circ_lib   IS NULL OR item_object.circ_lib IN ( SELECT id FROM actor.org_unit_descendants(m.copy_circ_lib)   ))
+              ORDER BY    CASE WHEN p.prox        IS NULL THEN 999 ELSE p.prox END,
+                    CASE WHEN m.copy_owning_lib IS NOT NULL
+                        THEN 256 / ( SELECT COALESCE(prox, 255) + 1 FROM actor.org_unit_proximity WHERE to_org = cn_object.owning_lib AND from_org = m.copy_owning_lib LIMIT 1 )
+                        ELSE 0
+                    END +
+                    CASE WHEN m.copy_circ_lib IS NOT NULL
+                        THEN 256 / ( SELECT COALESCE(prox, 255) + 1 FROM actor.org_unit_proximity WHERE to_org = item_object.circ_lib AND from_org = m.copy_circ_lib LIMIT 1 )
+                        ELSE 0
+                    END +
+                    CASE WHEN m.is_renewal = renewal        THEN 128 ELSE 0 END +
+                    CASE WHEN m.juvenile_flag    IS NOT NULL THEN 64 ELSE 0 END +
+                    CASE WHEN m.circ_modifier    IS NOT NULL THEN 32 ELSE 0 END +
+                    CASE WHEN m.marc_type        IS NOT NULL THEN 16 ELSE 0 END +
+                    CASE WHEN m.marc_form        IS NOT NULL THEN 8 ELSE 0 END +
+                    CASE WHEN m.marc_vr_format    IS NOT NULL THEN 4 ELSE 0 END +
+                    CASE WHEN m.ref_flag        IS NOT NULL THEN 2 ELSE 0 END +
+                    CASE WHEN m.usr_age_lower_bound    IS NOT NULL THEN 0.5 ELSE 0 END +
+                    CASE WHEN m.usr_age_upper_bound    IS NOT NULL THEN 0.5 ELSE 0 END DESC LOOP
+
+            IF current_mp.is_renewal IS NOT NULL THEN
+                CONTINUE WHEN current_mp.is_renewal <> renewal;
+            END IF;
+
+            IF current_mp.circ_modifier IS NOT NULL THEN
+                CONTINUE WHEN current_mp.circ_modifier <> item_object.circ_modifier OR item_object.circ_modifier IS NULL;
+            END IF;
+
+            IF current_mp.marc_type IS NOT NULL THEN
+                IF item_object.circ_as_type IS NOT NULL THEN
+                    CONTINUE WHEN current_mp.marc_type <> item_object.circ_as_type;
+                ELSE
+                    CONTINUE WHEN current_mp.marc_type <> rec_descriptor.item_type;
+                END IF;
+            END IF;
+
+            IF current_mp.marc_form IS NOT NULL THEN
+                CONTINUE WHEN current_mp.marc_form <> rec_descriptor.item_form;
+            END IF;
+
+            IF current_mp.marc_vr_format IS NOT NULL THEN
+                CONTINUE WHEN current_mp.marc_vr_format <> rec_descriptor.vr_format;
+            END IF;
+
+            IF current_mp.ref_flag IS NOT NULL THEN
+                CONTINUE WHEN current_mp.ref_flag <> item_object.ref;
+            END IF;
+
+            IF current_mp.juvenile_flag IS NOT NULL THEN
+                CONTINUE WHEN current_mp.juvenile_flag <> user_object.juvenile;
+            END IF;
+
+            IF current_mp.usr_age_lower_bound IS NOT NULL THEN
+                CONTINUE WHEN user_object.dob IS NULL OR current_mp.usr_age_lower_bound < age(user_object.dob);
+            END IF;
+
+            IF current_mp.usr_age_upper_bound IS NOT NULL THEN
+                CONTINUE WHEN user_object.dob IS NULL OR current_mp.usr_age_upper_bound > age(user_object.dob);
+            END IF;
+
+
+            -- everything was undefined or matched
+            matchpoint = current_mp;
+
+            EXIT WHEN matchpoint.id IS NOT NULL;
+        END LOOP;
+
+        EXIT WHEN current_group.parent IS NULL OR matchpoint.id IS NOT NULL;
+
+        SELECT INTO current_group * FROM permission.grp_tree WHERE id = current_group.parent;
+    END LOOP;
+
+    RETURN matchpoint;
+END;
+$func$ LANGUAGE plpgsql;
+
+COMMIT;
+

Copied: branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0400.schema.unique_authority_index.sql (from rev 17886, trunk/Open-ILS/src/sql/Pg/upgrade/0400.schema.unique_authority_index.sql)
===================================================================
--- branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0400.schema.unique_authority_index.sql	                        (rev 0)
+++ branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0400.schema.unique_authority_index.sql	2010-10-18 13:46:56 UTC (rev 18371)
@@ -0,0 +1,96 @@
+BEGIN;
+
+INSERT INTO config.upgrade_log (version) VALUES ('0400'); -- dbs
+
+CREATE OR REPLACE FUNCTION authority.normalize_heading( TEXT ) RETURNS TEXT AS $func$
+    use strict;
+    use warnings;
+    use MARC::Record;
+    use MARC::File::XML (BinaryEncoding => 'UTF8');
+
+    my $xml = shift();
+    my $r = MARC::Record->new_from_xml( $xml );
+    return undef unless ($r);
+
+    # From http://www.loc.gov/standards/sourcelist/subject.html
+    my $thes_code_map = {
+        a => 'lcsh',
+        b => 'lcshac',
+        c => 'mesh',
+        d => 'nal',
+        k => 'cash',
+        n => 'notapplicable',
+        r => 'aat',
+        s => 'sears',
+        v => 'rvm',
+    };
+
+    # Default to "No attempt to code" if the leader is horribly broken
+    my $thes_char = substr($r->field('008')->data(), 11, 1) || '|';
+
+    my $thes_code = 'UNDEFINED';
+
+    if ($thes_char eq 'z') {
+        # Grab the 040 $f per http://www.loc.gov/marc/authority/ad040.html
+        $thes_code = $r->subfield('040', 'f') || 'UNDEFINED';
+    } elsif ($thes_code_map->{$thes_char}) {
+        $thes_code = $thes_code_map->{$thes_char};
+    }
+
+    my $head = $r->field('1..');
+    my $auth_txt = '';
+    foreach my $sf ($head->subfields()) {
+        $auth_txt .= $sf->[1];
+    }
+
+    
+    # Perhaps better to parameterize the spi and pass as a parameter
+    $auth_txt =~ s/'//go;
+    my $result = spi_exec_query("SELECT public.naco_normalize('$auth_txt') AS norm_text");
+    my $norm_txt = $result->{rows}[0]->{norm_text};
+
+    return $head->tag() . "_" . $thes_code . " " . $norm_txt;
+$func$ LANGUAGE 'plperlu' IMMUTABLE;
+
+COMMENT ON FUNCTION authority.normalize_heading( TEXT ) IS $$
+/**
+* Extract the authority heading, thesaurus, and NACO-normalized values
+* from an authority record. The primary purpose is to build a unique
+* index to defend against duplicated authority records from the same
+* thesaurus.
+*/
+$$;
+
+COMMIT;
+
+-- Do this outside of a transaction to avoid failure if duplicate
+-- authority heading / thesaurus / heading text entries already
+-- exist in the database:
+CREATE UNIQUE INDEX unique_by_heading_and_thesaurus
+    ON authority.record_entry (authority.normalize_heading(marc))
+    WHERE deleted IS FALSE or deleted = FALSE
+;
+
+-- If the unique index fails, uncomment the following to create
+-- a regular index that will help find the duplicates in a hurry:
+--CREATE INDEX by_heading_and_thesaurus
+--    ON authority.record_entry (authority.normalize_heading(marc))
+--    WHERE deleted IS FALSE or deleted = FALSE
+--;
+
+-- Then find the duplicates like so to get an idea of how much
+-- pain you're looking at to clean things up:
+--SELECT id, authority.normalize_heading(marc)
+--    FROM authority.record_entry
+--    WHERE authority.normalize_heading(marc) IN (
+--        SELECT authority.normalize_heading(marc)
+--        FROM authority.record_entry
+--        GROUP BY authority.normalize_heading(marc)
+--        HAVING COUNT(*) > 1
+--    )
+--;
+
+-- Once you have removed the duplicates and the CREATE UNIQUE INDEX
+-- statement succeeds, drop the temporary index to avoid unnecessary
+-- duplication:
+-- DROP INDEX authority.by_heading_and_thesaurus;

Copied: branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0401.schema.authority_record_entry_drop_arn.sql (from rev 17886, trunk/Open-ILS/src/sql/Pg/upgrade/0401.schema.authority_record_entry_drop_arn.sql)
===================================================================
--- branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0401.schema.authority_record_entry_drop_arn.sql	                        (rev 0)
+++ branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0401.schema.authority_record_entry_drop_arn.sql	2010-10-18 13:46:56 UTC (rev 18371)
@@ -0,0 +1,9 @@
+BEGIN;
+
+INSERT INTO config.upgrade_log (version) VALUES ('0401'); -- dbs
+
+DROP INDEX authority.authority_record_unique_tcn;
+ALTER TABLE authority.record_entry DROP COLUMN arn_value;
+ALTER TABLE authority.record_entry DROP COLUMN arn_source;
+
+COMMIT;

Copied: branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0402.schema.unique_authority_index_revisited.sql (from rev 17886, trunk/Open-ILS/src/sql/Pg/upgrade/0402.schema.unique_authority_index_revisited.sql)
===================================================================
--- branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0402.schema.unique_authority_index_revisited.sql	                        (rev 0)
+++ branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0402.schema.unique_authority_index_revisited.sql	2010-10-18 13:46:56 UTC (rev 18371)
@@ -0,0 +1,91 @@
+BEGIN;
+
+-- Make the authority heading normalization routine more defensive
+-- Also drop back to a plain index for 2.0, we will get more restrictive over time
+
+INSERT INTO config.upgrade_log (version) VALUES ('0402'); -- dbs
+
+CREATE OR REPLACE FUNCTION authority.normalize_heading( TEXT ) RETURNS TEXT AS $func$
+    use strict;
+    use warnings;
+
+    use utf8;
+    use MARC::Record;
+    use MARC::File::XML (BinaryEncoding => 'UTF8');
+    use UUID::Tiny ':std';
+
+    my $xml = shift() or return undef;
+
+    my $r;
+
+    # Prevent errors in XML parsing from blowing out ungracefully
+    eval {
+        $r = MARC::Record->new_from_xml( $xml );
+        1;
+    } or do {
+       return 'BAD_MARCXML_' . create_uuid_as_string(UUID_MD5, $xml);
+    };
+
+    if (!$r) {
+       return 'BAD_MARCXML_' . create_uuid_as_string(UUID_MD5, $xml);
+    }
+
+    # From http://www.loc.gov/standards/sourcelist/subject.html
+    my $thes_code_map = {
+        a => 'lcsh',
+        b => 'lcshac',
+        c => 'mesh',
+        d => 'nal',
+        k => 'cash',
+        n => 'notapplicable',
+        r => 'aat',
+        s => 'sears',
+        v => 'rvm',
+    };
+
+    # Default to "No attempt to code" if the leader is horribly broken
+    my $fixed_field = $r->field('008');
+    my $thes_char = '|';
+    if ($fixed_field) { 
+        $thes_char = substr($fixed_field->data(), 11, 1) || '|';
+    }
+
+    my $thes_code = 'UNDEFINED';
+
+    if ($thes_char eq 'z') {
+        # Grab the 040 $f per http://www.loc.gov/marc/authority/ad040.html
+        $thes_code = $r->subfield('040', 'f') || 'UNDEFINED';
+    } elsif ($thes_code_map->{$thes_char}) {
+        $thes_code = $thes_code_map->{$thes_char};
+    }
+
+    my $auth_txt = '';
+    my $head = $r->field('1..');
+    if ($head) {
+        # Concatenate all of these subfields together, prefixed by their code
+        # to prevent collisions along the lines of "Fiction, North Carolina"
+        foreach my $sf ($head->subfields()) {
+            $auth_txt .= '‡' . $sf->[0] . ' ' . $sf->[1];
+        }
+    }
+    
+    # Perhaps better to parameterize the spi and pass as a parameter
+    $auth_txt =~ s/'//go;
+
+    if ($auth_txt) {
+        my $result = spi_exec_query("SELECT public.naco_normalize('$auth_txt') AS norm_text");
+        my $norm_txt = $result->{rows}[0]->{norm_text};
+        return $head->tag() . "_" . $thes_code . " " . $norm_txt;
+    }
+
+    return 'NOHEADING_' . $thes_code . ' ' . create_uuid_as_string(UUID_MD5, $xml);
+$func$ LANGUAGE 'plperlu' IMMUTABLE;
+
+DROP INDEX authority.unique_by_heading_and_thesaurus;
+
+CREATE INDEX by_heading_and_thesaurus
+    ON authority.record_entry (authority.normalize_heading(marc))
+    WHERE deleted IS FALSE or deleted = FALSE
+;
+
+COMMIT;

Copied: branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0403.schema.serials-tweaks.sql (from rev 17886, trunk/Open-ILS/src/sql/Pg/upgrade/0403.schema.serials-tweaks.sql)
===================================================================
--- branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0403.schema.serials-tweaks.sql	                        (rev 0)
+++ branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0403.schema.serials-tweaks.sql	2010-10-18 13:46:56 UTC (rev 18371)
@@ -0,0 +1,35 @@
+-- serials schema tweaks
+
+BEGIN;
+
+INSERT INTO config.upgrade_log (version) VALUES ('0403'); -- dbwells via miker
+
+------- caption_and_pattern changes
+ALTER TABLE serial.caption_and_pattern
+ADD COLUMN start_date	TIMESTAMP WITH TIME ZONE DEFAULT NOW();
+
+ALTER TABLE serial.caption_and_pattern
+ADD COLUMN end_date	TIMESTAMP WITH TIME ZONE;
+
+
+------- *_summary changes
+ALTER TABLE serial.basic_summary
+ADD COLUMN show_generated	BOOL	NOT NULL DEFAULT TRUE;
+
+ALTER TABLE serial.supplement_summary
+ADD COLUMN show_generated	BOOL	NOT NULL DEFAULT TRUE;
+
+ALTER TABLE serial.index_summary
+ADD COLUMN show_generated	BOOL	NOT NULL DEFAULT TRUE;
+
+
+------- distribution changes
+ALTER TABLE serial.distribution
+
+ADD COLUMN summary_method	TEXT	CONSTRAINT summary_method_check CHECK (
+					summary_method IS NULL
+					OR summary_method IN ( 'add_to_sre',
+					'merge_with_sre', 'use_sre_only',
+					'use_sdist_only'));
+
+COMMIT;

Copied: branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0404.schema.acq-provider-contact-null-null.sql (from rev 17886, trunk/Open-ILS/src/sql/Pg/upgrade/0404.schema.acq-provider-contact-null-null.sql)
===================================================================
--- branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0404.schema.acq-provider-contact-null-null.sql	                        (rev 0)
+++ branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0404.schema.acq-provider-contact-null-null.sql	2010-10-18 13:46:56 UTC (rev 18371)
@@ -0,0 +1,11 @@
+BEGIN;
+
+-- Make this column NOT NULL.  This was the intent all along,
+-- thwarted by a typo (NULL NULL instead of NOT NULL).
+
+INSERT INTO config.upgrade_log (version) VALUES ('0404'); -- Scott McKellar
+
+ALTER TABLE acq.provider_contact
+	ALTER COLUMN name SET NOT NULL;
+
+COMMIT;

Copied: branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0405.schema.acq-hold-copy-map-drop-fkey.sql (from rev 17886, trunk/Open-ILS/src/sql/Pg/upgrade/0405.schema.acq-hold-copy-map-drop-fkey.sql)
===================================================================
--- branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0405.schema.acq-hold-copy-map-drop-fkey.sql	                        (rev 0)
+++ branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0405.schema.acq-hold-copy-map-drop-fkey.sql	2010-10-18 13:46:56 UTC (rev 18371)
@@ -0,0 +1,12 @@
+-- Drop a foreign key.  It is commented out in 090.schema.action.sql
+-- but was never dropped via an upgrade script.
+
+-- No transaction, in case the fkey has already been dropped by
+-- other means.
+
+INSERT INTO config.upgrade_log (version) VALUES ('0405'); -- Scott McKellar
+
+\qecho If the following ALTER TABLE fails because the constraint
+\qecho being dropped doesn't exist, that's okay.  Ignore the failure.
+
+ALTER TABLE action.hold_copy_map DROP CONSTRAINT hold_copy_map_target_copy_fkey;

Copied: branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0406.schema.hold-matrix.user-not-requestor.sql (from rev 17886, trunk/Open-ILS/src/sql/Pg/upgrade/0406.schema.hold-matrix.user-not-requestor.sql)
===================================================================
--- branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0406.schema.hold-matrix.user-not-requestor.sql	                        (rev 0)
+++ branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0406.schema.hold-matrix.user-not-requestor.sql	2010-10-18 13:46:56 UTC (rev 18371)
@@ -0,0 +1,135 @@
+BEGIN;
+
+INSERT INTO config.upgrade_log (version) VALUES ('0406'); -- miker
+
+INSERT INTO config.global_flag (name, label, enabled)
+    VALUES (
+        'circ.holds.usr_not_requestor',
+        oils_i18n_gettext(
+            'circ.holds.usr_not_requestor',
+            'Holds: When testing hold matrix matchpoints, use the profile group of the receiving user instead of that of the requestor (affects staff-placed holds)',
+            'cgf',
+            'label'
+        ),
+        TRUE
+    );
+
+CREATE OR REPLACE FUNCTION action.find_hold_matrix_matchpoint( pickup_ou INT, request_ou INT, match_item BIGINT, match_user INT, match_requestor INT ) RETURNS INT AS $func$
+DECLARE
+    current_requestor_group    permission.grp_tree%ROWTYPE;
+    root_ou            actor.org_unit%ROWTYPE;
+    requestor_object    actor.usr%ROWTYPE;
+    user_object        actor.usr%ROWTYPE;
+    item_object        asset.copy%ROWTYPE;
+    item_cn_object        asset.call_number%ROWTYPE;
+    rec_descriptor        metabib.rec_descriptor%ROWTYPE;
+    current_mp_weight    FLOAT;
+    matchpoint_weight    FLOAT;
+    tmp_weight        FLOAT;
+    current_mp        config.hold_matrix_matchpoint%ROWTYPE;
+    matchpoint        config.hold_matrix_matchpoint%ROWTYPE;
+BEGIN
+    SELECT INTO root_ou * FROM actor.org_unit WHERE parent_ou IS NULL;
+    SELECT INTO user_object * FROM actor.usr WHERE id = match_user;
+    SELECT INTO requestor_object * FROM actor.usr WHERE id = match_requestor;
+    SELECT INTO item_object * FROM asset.copy WHERE id = match_item;
+    SELECT INTO item_cn_object * FROM asset.call_number WHERE id = item_object.call_number;
+    SELECT INTO rec_descriptor r.* FROM metabib.rec_descriptor r WHERE r.record = item_cn_object.record;
+
+    PERFORM * FROM config.internal_flag WHERE name = 'circ.holds.usr_not_requestor' AND enabled;
+
+    IF NOT FOUND THEN
+        SELECT INTO current_requestor_group * FROM permission.grp_tree WHERE id = requestor_object.profile;
+    ELSE
+        SELECT INTO current_requestor_group * FROM permission.grp_tree WHERE id = user_object.profile;
+    END IF;
+
+    LOOP 
+        -- for each potential matchpoint for this ou and group ...
+        FOR current_mp IN
+            SELECT    m.*
+              FROM    config.hold_matrix_matchpoint m
+              WHERE    m.requestor_grp = current_requestor_group.id AND m.active
+              ORDER BY    CASE WHEN m.circ_modifier    IS NOT NULL THEN 16 ELSE 0 END +
+                    CASE WHEN m.juvenile_flag    IS NOT NULL THEN 16 ELSE 0 END +
+                    CASE WHEN m.marc_type        IS NOT NULL THEN 8 ELSE 0 END +
+                    CASE WHEN m.marc_form        IS NOT NULL THEN 4 ELSE 0 END +
+                    CASE WHEN m.marc_vr_format    IS NOT NULL THEN 2 ELSE 0 END +
+                    CASE WHEN m.ref_flag        IS NOT NULL THEN 1 ELSE 0 END DESC LOOP
+
+            current_mp_weight := 5.0;
+
+            IF current_mp.circ_modifier IS NOT NULL THEN
+                CONTINUE WHEN current_mp.circ_modifier <> item_object.circ_modifier OR item_object.circ_modifier IS NULL;
+            END IF;
+
+            IF current_mp.marc_type IS NOT NULL THEN
+                IF item_object.circ_as_type IS NOT NULL THEN
+                    CONTINUE WHEN current_mp.marc_type <> item_object.circ_as_type;
+                ELSE
+                    CONTINUE WHEN current_mp.marc_type <> rec_descriptor.item_type;
+                END IF;
+            END IF;
+
+            IF current_mp.marc_form IS NOT NULL THEN
+                CONTINUE WHEN current_mp.marc_form <> rec_descriptor.item_form;
+            END IF;
+
+            IF current_mp.marc_vr_format IS NOT NULL THEN
+                CONTINUE WHEN current_mp.marc_vr_format <> rec_descriptor.vr_format;
+            END IF;
+
+            IF current_mp.juvenile_flag IS NOT NULL THEN
+                CONTINUE WHEN current_mp.juvenile_flag <> user_object.juvenile;
+            END IF;
+
+            IF current_mp.ref_flag IS NOT NULL THEN
+                CONTINUE WHEN current_mp.ref_flag <> item_object.ref;
+            END IF;
+
+
+            -- caclulate the rule match weight
+            IF current_mp.item_owning_ou IS NOT NULL AND current_mp.item_owning_ou <> root_ou.id THEN
+                SELECT INTO tmp_weight 1.0 / (actor.org_unit_proximity(current_mp.item_owning_ou, item_cn_object.owning_lib)::FLOAT + 1.0)::FLOAT;
+                current_mp_weight := current_mp_weight - tmp_weight;
+            END IF; 
+
+            IF current_mp.item_circ_ou IS NOT NULL AND current_mp.item_circ_ou <> root_ou.id THEN
+                SELECT INTO tmp_weight 1.0 / (actor.org_unit_proximity(current_mp.item_circ_ou, item_object.circ_lib)::FLOAT + 1.0)::FLOAT;
+                current_mp_weight := current_mp_weight - tmp_weight;
+            END IF; 
+
+            IF current_mp.pickup_ou IS NOT NULL AND current_mp.pickup_ou <> root_ou.id THEN
+                SELECT INTO tmp_weight 1.0 / (actor.org_unit_proximity(current_mp.pickup_ou, pickup_ou)::FLOAT + 1.0)::FLOAT;
+                current_mp_weight := current_mp_weight - tmp_weight;
+            END IF; 
+
+            IF current_mp.request_ou IS NOT NULL AND current_mp.request_ou <> root_ou.id THEN
+                SELECT INTO tmp_weight 1.0 / (actor.org_unit_proximity(current_mp.request_ou, request_ou)::FLOAT + 1.0)::FLOAT;
+                current_mp_weight := current_mp_weight - tmp_weight;
+            END IF; 
+
+            IF current_mp.user_home_ou IS NOT NULL AND current_mp.user_home_ou <> root_ou.id THEN
+                SELECT INTO tmp_weight 1.0 / (actor.org_unit_proximity(current_mp.user_home_ou, user_object.home_ou)::FLOAT + 1.0)::FLOAT;
+                current_mp_weight := current_mp_weight - tmp_weight;
+            END IF; 
+
+            -- set the matchpoint if we found the best one
+            IF matchpoint_weight IS NULL OR matchpoint_weight > current_mp_weight THEN
+                matchpoint = current_mp;
+                matchpoint_weight = current_mp_weight;
+            END IF;
+
+        END LOOP;
+
+        EXIT WHEN current_requestor_group.parent IS NULL OR matchpoint.id IS NOT NULL;
+
+        SELECT INTO current_requestor_group * FROM permission.grp_tree WHERE id = current_requestor_group.parent;
+    END LOOP;
+
+    RETURN matchpoint.id;
+END;
+$func$ LANGUAGE plpgsql;
+
+COMMIT;
+

Copied: branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0407.data.serial-perm.sql (from rev 17886, trunk/Open-ILS/src/sql/Pg/upgrade/0407.data.serial-perm.sql)
===================================================================
--- branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0407.data.serial-perm.sql	                        (rev 0)
+++ branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0407.data.serial-perm.sql	2010-10-18 13:46:56 UTC (rev 18371)
@@ -0,0 +1,12 @@
+BEGIN;
+
+INSERT INTO config.upgrade_log (version) VALUES ('0407'); -- senator
+
+INSERT INTO permission.perm_list (id, code, description) VALUES
+    (397, 'ADMIN_SERIAL_CAPTION_PATTERN', oils_i18n_gettext(397, 'Create/update/delete serial caption and pattern objects', 'ppl', 'description')),
+    (398, 'ADMIN_SERIAL_SUBSCRIPTION', oils_i18n_gettext(398, 'Create/update/delete serial subscription objects', 'ppl', 'description')),
+    (399, 'ADMIN_SERIAL_DISTRIBUTION', oils_i18n_gettext(399, 'Create/update/delete serial distribution objects', 'ppl', 'description')),
+    (400, 'ADMIN_SERIAL_STREAM', oils_i18n_gettext(400, 'Create/update/delete serial stream objects', 'ppl', 'description'));
+
+COMMIT;
+

Copied: branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0408.schema.update_maintain_901.sql (from rev 17886, trunk/Open-ILS/src/sql/Pg/upgrade/0408.schema.update_maintain_901.sql)
===================================================================
--- branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0408.schema.update_maintain_901.sql	                        (rev 0)
+++ branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0408.schema.update_maintain_901.sql	2010-10-18 13:46:56 UTC (rev 18371)
@@ -0,0 +1,57 @@
+BEGIN;
+
+INSERT INTO config.upgrade_log (version) VALUES ('0408'); -- gmc
+
+CREATE OR REPLACE FUNCTION maintain_901 () RETURNS TRIGGER AS $func$
+BEGIN
+    -- Remove any existing 901 fields before we insert the authoritative one
+    NEW.marc := REGEXP_REPLACE(NEW.marc, E'<datafield\s*[^<>]*?\s*tag="901".+?</datafield>', '', 'g');
+    IF TG_TABLE_SCHEMA = 'biblio' THEN
+        NEW.marc := REGEXP_REPLACE(
+            NEW.marc,
+            E'(</(?:[^:]*?:)?record>)',
+            E'<datafield tag="901" ind1=" " ind2=" ">' ||
+                '<subfield code="a">' || NEW.tcn_value || E'</subfield>' ||
+                '<subfield code="b">' || NEW.tcn_source || E'</subfield>' ||
+                '<subfield code="c">' || NEW.id || E'</subfield>' ||
+                '<subfield code="t">' || TG_TABLE_SCHEMA || E'</subfield>' ||
+                CASE WHEN NEW.owner IS NOT NULL THEN '<subfield code="o">' || NEW.owner || E'</subfield>' ELSE '' END ||
+                CASE WHEN NEW.share_depth IS NOT NULL THEN '<subfield code="d">' || NEW.share_depth || E'</subfield>' ELSE '' END ||
+             E'</datafield>\\1'
+        );
+    ELSIF TG_TABLE_SCHEMA = 'authority' THEN
+        NEW.marc := REGEXP_REPLACE(
+            NEW.marc,
+            E'(</(?:[^:]*?:)?record>)',
+            E'<datafield tag="901" ind1=" " ind2=" ">' ||
+                '<subfield code="c">' || NEW.id || E'</subfield>' ||
+                '<subfield code="t">' || TG_TABLE_SCHEMA || E'</subfield>' ||
+             E'</datafield>\\1'
+        );
+    ELSIF TG_TABLE_SCHEMA = 'serial' THEN
+        NEW.marc := REGEXP_REPLACE(
+            NEW.marc,
+            E'(</(?:[^:]*?:)?record>)',
+            E'<datafield tag="901" ind1=" " ind2=" ">' ||
+                '<subfield code="c">' || NEW.id || E'</subfield>' ||
+                '<subfield code="t">' || TG_TABLE_SCHEMA || E'</subfield>' ||
+                '<subfield code="o">' || NEW.owning_lib || E'</subfield>' ||
+                CASE WHEN NEW.record IS NOT NULL THEN '<subfield code="r">' || NEW.record || E'</subfield>' ELSE '' END ||
+             E'</datafield>\\1'
+        );
+    ELSE
+        NEW.marc := REGEXP_REPLACE(
+            NEW.marc,
+            E'(</(?:[^:]*?:)?record>)',
+            E'<datafield tag="901" ind1=" " ind2=" ">' ||
+                '<subfield code="c">' || NEW.id || E'</subfield>' ||
+                '<subfield code="t">' || TG_TABLE_SCHEMA || E'</subfield>' ||
+             E'</datafield>\\1'
+        );
+    END IF;
+
+    RETURN NEW;
+END;
+$func$ LANGUAGE PLPGSQL;
+
+COMMIT;

Copied: branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0409.data.receive-serial-perm.sql (from rev 17886, trunk/Open-ILS/src/sql/Pg/upgrade/0409.data.receive-serial-perm.sql)
===================================================================
--- branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0409.data.receive-serial-perm.sql	                        (rev 0)
+++ branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0409.data.receive-serial-perm.sql	2010-10-18 13:46:56 UTC (rev 18371)
@@ -0,0 +1,8 @@
+BEGIN;
+
+INSERT INTO config.upgrade_log (version) VALUES ('0409'); -- senator
+
+INSERT INTO permission.perm_list (id, code, description) VALUES
+    (401, 'RECEIVE_SERIAL', oils_i18n_gettext(401, 'Receive serial items', 'ppl', 'description'));
+
+COMMIT;

Copied: branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0410.schema.allow_parallel_reingest.sql (from rev 17886, trunk/Open-ILS/src/sql/Pg/upgrade/0410.schema.allow_parallel_reingest.sql)
===================================================================
--- branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0410.schema.allow_parallel_reingest.sql	                        (rev 0)
+++ branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0410.schema.allow_parallel_reingest.sql	2010-10-18 13:46:56 UTC (rev 18371)
@@ -0,0 +1,74 @@
+BEGIN;
+
+INSERT INTO config.upgrade_log (version) VALUES ('0410'); -- gmc
+
+INSERT INTO config.internal_flag (name) VALUES ('ingest.metarecord_mapping.skip_on_update');
+
+-- AFTER UPDATE OR INSERT trigger for biblio.record_entry
+CREATE OR REPLACE FUNCTION biblio.indexing_ingest_or_delete () RETURNS TRIGGER AS $func$
+BEGIN
+
+    IF NEW.deleted IS TRUE THEN -- If this bib is deleted
+        DELETE FROM metabib.metarecord_source_map WHERE source = NEW.id; -- Rid ourselves of the search-estimate-killing linkage
+        DELETE FROM authority.bib_linking WHERE bib = NEW.id; -- Avoid updating fields in bibs that are no longer visible
+        RETURN NEW; -- and we're done
+    END IF;
+
+    IF TG_OP = 'UPDATE' THEN -- re-ingest?
+        PERFORM * FROM config.internal_flag WHERE name = 'ingest.reingest.force_on_same_marc' AND enabled;
+
+        IF NOT FOUND AND OLD.marc = NEW.marc THEN -- don't do anything if the MARC didn't change
+            RETURN NEW;
+        END IF;
+    END IF;
+
+    -- Record authority linking
+    PERFORM * FROM config.internal_flag WHERE name = 'ingest.disable_authority_linking' AND enabled;
+    IF NOT FOUND THEN
+        PERFORM biblio.map_authority_linking( NEW.id, NEW.marc );
+    END IF;
+
+    -- Flatten and insert the mfr data
+    PERFORM * FROM config.internal_flag WHERE name = 'ingest.disable_metabib_full_rec' AND enabled;
+    IF NOT FOUND THEN
+        PERFORM metabib.reingest_metabib_full_rec(NEW.id);
+        PERFORM * FROM config.internal_flag WHERE name = 'ingest.disable_metabib_rec_descriptor' AND enabled;
+        IF NOT FOUND THEN
+            PERFORM metabib.reingest_metabib_rec_descriptor(NEW.id);
+        END IF;
+    END IF;
+
+    -- Gather and insert the field entry data
+    PERFORM metabib.reingest_metabib_field_entries(NEW.id);
+
+    -- Located URI magic
+    IF TG_OP = 'INSERT' THEN
+        PERFORM * FROM config.internal_flag WHERE name = 'ingest.disable_located_uri' AND enabled;
+        IF NOT FOUND THEN
+            PERFORM biblio.extract_located_uris( NEW.id, NEW.marc, NEW.editor );
+        END IF;
+    ELSE
+        PERFORM * FROM config.internal_flag WHERE name = 'ingest.disable_located_uri' AND enabled;
+        IF NOT FOUND THEN
+            PERFORM biblio.extract_located_uris( NEW.id, NEW.marc, NEW.editor );
+        END IF;
+    END IF;
+
+    -- (re)map metarecord-bib linking
+    IF TG_OP = 'INSERT' THEN -- if not deleted and performing an insert, check for the flag
+        PERFORM * FROM config.internal_flag WHERE name = 'ingest.metarecord_mapping.skip_on_insert' AND enabled;
+        IF NOT FOUND THEN
+            PERFORM metabib.remap_metarecord_for_bib( NEW.id, NEW.fingerprint );
+        END IF;
+    ELSE -- we're doing an update, and we're not deleted, remap
+        PERFORM * FROM config.internal_flag WHERE name = 'ingest.metarecord_mapping.skip_on_update' AND enabled;
+        IF NOT FOUND THEN
+            PERFORM metabib.remap_metarecord_for_bib( NEW.id, NEW.fingerprint );
+        END IF;
+    END IF;
+
+    RETURN NEW;
+END;
+$func$ LANGUAGE PLPGSQL;
+
+COMMIT;

Copied: branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0411.schema.assume_inserts_only_flag.sql (from rev 17886, trunk/Open-ILS/src/sql/Pg/upgrade/0411.schema.assume_inserts_only_flag.sql)
===================================================================
--- branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0411.schema.assume_inserts_only_flag.sql	                        (rev 0)
+++ branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0411.schema.assume_inserts_only_flag.sql	2010-10-18 13:46:56 UTC (rev 18371)
@@ -0,0 +1,86 @@
+BEGIN;
+
+INSERT INTO config.upgrade_log (version) VALUES ('0411'); -- gmc
+
+INSERT INTO config.internal_flag (name) VALUES ('ingest.assume_inserts_only');
+
+CREATE OR REPLACE FUNCTION metabib.reingest_metabib_rec_descriptor( bib_id BIGINT ) RETURNS VOID AS $func$
+BEGIN
+    PERFORM * FROM config.internal_flag WHERE name = 'ingest.assume_inserts_only' AND enabled;
+    IF NOT FOUND THEN
+        DELETE FROM metabib.rec_descriptor WHERE record = bib_id;
+    END IF;
+    INSERT INTO metabib.rec_descriptor (record, item_type, item_form, bib_level, control_type, enc_level, audience, lit_form, type_mat, cat_form, pub_status, item_lang, vr_format, date1, date2)
+        SELECT  bib_id,
+                biblio.marc21_extract_fixed_field( bib_id, 'Type' ),
+                biblio.marc21_extract_fixed_field( bib_id, 'Form' ),
+                biblio.marc21_extract_fixed_field( bib_id, 'BLvl' ),
+                biblio.marc21_extract_fixed_field( bib_id, 'Ctrl' ),
+                biblio.marc21_extract_fixed_field( bib_id, 'ELvl' ),
+                biblio.marc21_extract_fixed_field( bib_id, 'Audn' ),
+                biblio.marc21_extract_fixed_field( bib_id, 'LitF' ),
+                biblio.marc21_extract_fixed_field( bib_id, 'TMat' ),
+                biblio.marc21_extract_fixed_field( bib_id, 'Desc' ),
+                biblio.marc21_extract_fixed_field( bib_id, 'DtSt' ),
+                biblio.marc21_extract_fixed_field( bib_id, 'Lang' ),
+                (   SELECT  v.value
+                      FROM  biblio.marc21_physical_characteristics( bib_id) p
+                            JOIN config.marc21_physical_characteristic_subfield_map s ON (s.id = p.subfield)
+                            JOIN config.marc21_physical_characteristic_value_map v ON (v.id = p.value)
+                      WHERE p.ptype = 'v' AND s.subfield = 'e'    ),
+                biblio.marc21_extract_fixed_field( bib_id, 'Date1'),
+                biblio.marc21_extract_fixed_field( bib_id, 'Date2');
+
+    RETURN;
+END;
+$func$ LANGUAGE PLPGSQL;
+
+CREATE OR REPLACE FUNCTION metabib.reingest_metabib_full_rec( bib_id BIGINT ) RETURNS VOID AS $func$
+BEGIN
+    PERFORM * FROM config.internal_flag WHERE name = 'ingest.assume_inserts_only' AND enabled;
+    IF NOT FOUND THEN
+        DELETE FROM metabib.real_full_rec WHERE record = bib_id;
+    END IF;
+    INSERT INTO metabib.real_full_rec (record, tag, ind1, ind2, subfield, value)
+        SELECT record, tag, ind1, ind2, subfield, value FROM biblio.flatten_marc( bib_id );
+
+    RETURN;
+END;
+$func$ LANGUAGE PLPGSQL;
+
+CREATE OR REPLACE FUNCTION metabib.reingest_metabib_field_entries( bib_id BIGINT ) RETURNS VOID AS $func$
+DECLARE
+    fclass          RECORD;
+    ind_data        metabib.field_entry_template%ROWTYPE;
+BEGIN
+    PERFORM * FROM config.internal_flag WHERE name = 'ingest.assume_inserts_only' AND enabled;
+    IF NOT FOUND THEN
+        FOR fclass IN SELECT * FROM config.metabib_class LOOP
+            -- RAISE NOTICE 'Emptying out %', fclass.name;
+            EXECUTE $$DELETE FROM metabib.$$ || fclass.name || $$_field_entry WHERE source = $$ || bib_id;
+        END LOOP;
+        DELETE FROM metabib.facet_entry WHERE source = bib_id;
+    END IF;
+
+    FOR ind_data IN SELECT * FROM biblio.extract_metabib_field_entry( bib_id ) LOOP
+        IF ind_data.field < 0 THEN
+            ind_data.field = -1 * ind_data.field;
+            INSERT INTO metabib.facet_entry (field, source, value)
+                VALUES (ind_data.field, ind_data.source, ind_data.value);
+        ELSE
+            EXECUTE $$
+                INSERT INTO metabib.$$ || ind_data.field_class || $$_field_entry (field, source, value)
+                    VALUES ($$ ||
+                        quote_literal(ind_data.field) || $$, $$ ||
+                        quote_literal(ind_data.source) || $$, $$ ||
+                        quote_literal(ind_data.value) ||
+                    $$);$$;
+        END IF;
+
+    END LOOP;
+
+    RETURN;
+END;
+$func$ LANGUAGE PLPGSQL;
+
+COMMIT;

Copied: branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0412.data.trigger.validator.HoldIsCancelled.sql (from rev 17886, trunk/Open-ILS/src/sql/Pg/upgrade/0412.data.trigger.validator.HoldIsCancelled.sql)
===================================================================
--- branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0412.data.trigger.validator.HoldIsCancelled.sql	                        (rev 0)
+++ branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0412.data.trigger.validator.HoldIsCancelled.sql	2010-10-18 13:46:56 UTC (rev 18371)
@@ -0,0 +1,16 @@
+BEGIN;
+
+INSERT INTO config.upgrade_log (version) VALUES ('0412'); -- phasefx
+
+INSERT INTO action_trigger.validator (module, description) VALUES (
+    'HoldIsCancelled',
+    oils_i18n_gettext(
+        'HoldIsCancelled',
+        'Check whether a hold request is cancelled.',
+        'atval',
+        'description'
+    )
+);
+
+COMMIT;
+

Copied: branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0413.schema.upgrade-auditor-tables.sql (from rev 17886, trunk/Open-ILS/src/sql/Pg/upgrade/0413.schema.upgrade-auditor-tables.sql)
===================================================================
--- branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0413.schema.upgrade-auditor-tables.sql	                        (rev 0)
+++ branches/serials-integration/Open-ILS/src/sql/Pg/upgrade/0413.schema.upgrade-auditor-tables.sql	2010-10-18 13:46:56 UTC (rev 18371)
@@ -0,0 +1,61 @@
+-- Resolve some discrepancies in the auditor schema between a fresh
+-- install and an upgraded database.
+
+BEGIN;
+
+INSERT INTO config.upgrade_log (version) VALUES ('0413'); -- Scott McKellar
+
+DROP VIEW auditor.actor_org_unit_lifecycle;
+
+SELECT auditor.create_auditor_lifecycle( 'actor', 'org_unit' );
+
+ALTER TABLE auditor.actor_usr_history
+	ALTER COLUMN claims_never_checked_out_count DROP DEFAULT;
+
+DROP VIEW auditor.actor_usr_lifecycle;
+
+SELECT auditor.create_auditor_lifecycle( 'actor', 'usr' );
+
+DROP VIEW auditor.asset_call_number_lifecycle;
+
+SELECT auditor.create_auditor_lifecycle( 'asset', 'call_number' );
+
+DROP VIEW auditor.asset_copy_lifecycle;
+
+SELECT auditor.create_auditor_lifecycle( 'asset', 'copy' );
+
+DROP VIEW auditor.biblio_record_entry_lifecycle;
+
+SELECT auditor.create_auditor_lifecycle( 'biblio', 'record_entry' );
+
+COMMIT;
+
+-- Outside of transaction; failure is okay if the 
+-- index already exists
+
+\qecho Creating some indexes outside of a transaction.  If a CREATE
+\qecho fails because the index already exists, ignore the failure.
+
+CREATE INDEX aud_actor_usr_address_hist_id_idx
+	ON auditor.actor_usr_address_history ( id );
+
+CREATE INDEX aud_actor_usr_hist_id_idx
+    ON auditor.actor_usr_history ( id );
+
+CREATE INDEX aud_asset_cn_hist_creator_idx
+	ON auditor.asset_call_number_history ( creator );
+
+CREATE INDEX aud_asset_cn_hist_editor_idx
+	ON auditor.asset_call_number_history ( editor );
+
+CREATE INDEX aud_asset_cp_hist_creator_idx
+	ON auditor.asset_copy_history ( creator );
+
+CREATE INDEX aud_asset_cp_hist_editor_idx
+	ON auditor.asset_copy_history ( editor );
+
+CREATE INDEX aud_bib_rec_entry_hist_creator_idx
+	ON auditor.biblio_record_entry_history ( creator );
+
+CREATE INDEX aud_bib_rec_entry_hist_editor_idx
+	ON auditor.biblio_record_entry_history ( editor );


Property changes on: branches/serials-integration/Open-ILS/src/support-scripts/clear_expired_circ_history.srfsh
___________________________________________________________________
Name: svn:executable
   + *

Modified: branches/serials-integration/Open-ILS/src/support-scripts/edi_fetcher.pl
===================================================================
--- branches/serials-integration/Open-ILS/src/support-scripts/edi_fetcher.pl	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/src/support-scripts/edi_fetcher.pl	2010-10-18 13:46:56 UTC (rev 18371)
@@ -21,44 +21,164 @@
 use vars qw/$debug/;
 
 use OpenILS::Application::Acq::EDI;
-use OpenILS::Utils::CStoreEditor;   # needs init() after IDL is loaded (by Cronscript session)
 use OpenILS::Utils::Cronscript;
+use File::Spec;
 
-INIT {
-    $debug = 1;
-}
+my $defaults = {
+    "account=i"  => 0,
+    "provider=i" => 0,
+    "inactive"   => 0,
+    "test"       => 0,
+};
 
-OpenILS::Utils::Cronscript->new()->session('open-ils.acq') or die "No session created";
-OpenILS::Utils::CStoreEditor::init();
+my $core  = OpenILS::Utils::Cronscript->new($defaults);
+my $opts  = $core->MyGetOptions() or die "Getting options failed!";
+my $e     = $core->editor();
+my $debug = $opts->{debug};
 
-sub editor {
-    my $ed = OpenILS::Utils::CStoreEditor->new(@_) or die "Failed to get new CStoreEditor";
-    return $ed;
+if ($debug) {
+    print join "\n", "OPTIONS:", map {sprintf "%16s: %s", $_, $opts->{$_}} sort keys %$opts;
+    print "\n\n";
 }
 
+sub main_search {
+    my $select = {'+acqpro' => {active => {"in"=>['t','f']}} }; # either way
+    my %args = @_ ? @_ : ();
+    foreach (keys %args) {
+        $select->{$_} = $args{$_};
+    }
+    return $e->search_acq_edi_account([
+        $select,
+        {
+            'join' => 'acqpro',
+            flesh => 1,
+            flesh_fields => {acqedi => ['provider']},
+        }
+    ]);
+}
 
-my $e = editor();
-my $set = $e->retrieve_all_acq_edi_account();
+my $set = main_search() or die "No EDI accounts found in database (table: acq.edi_account)";
+
 my $total_accts = scalar(@$set);
 
 ($total_accts) or die "No EDI accounts found in database (table: acq.edi_account)";
 
-print "EDI Accounts Total : ", scalar(@$set), "\n";
+print "EDI Accounts Total : $total_accts\n";
+my $active = [ grep {$_->provider->active eq 't'} @$set ];
+print "EDI Accounts Active: ", scalar(@$active), "\n";
 
-my $subset = $e->search_acq_edi_account([
-    {'+acqpro' => {active => 't'}},
-    {
-        'join' => 'acqpro',
-        flesh => 1,
-        flesh_fields => {acqedi => ['provider']},
+my $subset;
+if ($opts->{inactive} or $opts->{provider} or $opts->{account}) {
+    print "Including inactive accounts\n";
+    $subset = [@$set];
+} else {
+    $subset = $active;
+}
+
+my ($acct, $pro);
+if ($opts->{provider}) {
+    print "Limiting by provider: " . $opts->{provider} . "\n";
+    $pro  = $e->retrieve_acq_provider($opts->{provider}) or die "provider '" . $opts->{provider} . "' not found";
+    printf "Provider %s found (edi_default %s)\n", $pro->id, $pro->edi_default;
+    $subset = main_search( 'id' => $pro->edi_default );
+    # $subset = [ grep {$_->provider->id == $opts->{provider}} @$subset ];
+    foreach (@$subset) {
+        $_->provider($pro);     # force provider match (short of LEFT JOINing the main_search query and dealing w/ multiple combos)
     }
-]);
+    scalar(@$subset) or die "provider '" . $opts->{provider} . "' edi_default invalid (failed to match acq.edi_account.id)";
+    if ($opts->{account} and $opts->{account} != $pro->edi_default) {
+        die sprintf "ERROR: --provider=%s and --account=%s specify rows that exist, but are not paired by acq.provider.edi_default", $opts->{provider}, $opts->{account};
+    }
+    $acct = $subset->[0]; 
+} 
+if ($opts->{account}) {
+    print "Limiting by account: " . $opts->{account} . "\n";
+    $subset = [ grep {$opts->{account}  == $_->id} @$subset ];
+    scalar(@$subset) or die "No acq.provider.edi_default matches option  --account=" . $opts->{account} . " ";
+    scalar(@$subset) > 1 and warn "account '" . $opts->{account} . "' has multiple matches.  Ignoring all but the first.";
+    $acct = $subset->[0]; 
+}
+scalar(@$subset) or die "No acq.provider rows match options " .
+    ($opts->{account}  ? ("--account="  . $opts->{account} ) : '') .
+    ($opts->{provider} ? ("--provider=" . $opts->{provider}) : '') ;
 
-print "EDI Accounts Active: ", scalar(@$subset), "\n";
+print "Limiting to " . scalar(@$subset) . " account(s)\n"; 
+foreach (@$subset) {
+    printf "Provider %s - %s, edi_account %s - %s: %s%s\n",
+        $_->provider->id, $_->provider->name, $_->id, $_->label, $_->host, ($_->in_dir ? ('/' . $_->in_dir) : '') ;
+}
 
-my $res = OpenILS::Application::Acq::EDI->retrieve_core();
+if (@ARGV) {
+    $opts->{provider} or $opts->{account}
+        or die "ERROR: --account=[ID] or --provider=[ID] option required for local data ingest, with valid edi_account or provider id";
+    print "READING FROM ", scalar(@ARGV), " LOCAL SOURCE(s) ONLY.  NO REMOTE SERVER(s) WILL BE USED\n"; 
+    printf "File will be attributed to edi_account %s - %s: %s\n", $acct->id, $acct->label, $acct->host;
+    my @files = @ARGV; # copy original @ARGV
+    foreach (@files) {
+        @ARGV = ($_);  # We'll use the diamond op, so we can pull from STDIN too
+        my $content = join '', <> or next;
+        $opts->{test} and next;
+        my $in = OpenILS::Application::Acq::EDI->process_retrieval(
+            $content,
+            "localhost:" . File::Spec->rel2abs($_),
+            OpenILS::Application::Acq::EDI->remote_account($acct),
+            $acct,
+            $e
+        );
+    }
+    exit;
+}
+# else no args
+
+my $res = OpenILS::Application::Acq::EDI->retrieve_core($subset,undef,undef,$opts->{test});
 print "Files retrieved: ", scalar(@$res), "\n";
 $debug and print "retrieve_core returns ", scalar(@$res),  " ids: " . join(', ', @$res), "\n";
 
-$debug and print Dumper($set);
+# $Data::Dumper::Indent = 1;
+$debug and print map {Dumper($_) . "\n"} @$subset;
 print "\ndone\n";
+
+__END__
+
+=pod
+
+=head1 NAME
+
+edi_fetcher.pl - A script for retrieving and processing EDI files from remote accounts.
+
+=head1 DESCRIPTION
+
+This script is expected to be run via crontab, for the purpose of retrieving vendor EDI files.
+
+Note: Depending on your vendors' and your own network environments, you may want to set/export
+the environmental variable FTP_PASSIVE like:
+
+    export FTP_PASSIVE=1
+    # or
+    FTP_PASSIVE=1 Open-ILS/src/support-scripts/edi_fetcher.pl
+
+=head1 OPTIONS
+
+    --account=[id]  Target one account, whether or not it is inactive.
+    --inactive      Includes inactive provider accounts (default OFF, forced ON if --account specified)
+
+=head1 ARGUMENTS
+
+edi_fetcher can also read from files specified as arguments on the command line, or from STDIN, or both.
+In such cases, the filename is not used to check whether the file has been loaded or not.  
+
+=head1 TODO
+
+More docs here.
+
+=head1 SEE ALSO
+
+    OpenILS::Utils::Cronscript
+    edi_pusher.pl
+
+=head1 AUTHOR
+
+Joe Atzberger <jatzberger at esilibrary.com>
+
+=cut
+

Modified: branches/serials-integration/Open-ILS/src/support-scripts/edi_pusher.pl
===================================================================
--- branches/serials-integration/Open-ILS/src/support-scripts/edi_pusher.pl	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/src/support-scripts/edi_pusher.pl	2010-10-18 13:46:56 UTC (rev 18371)
@@ -112,7 +112,7 @@
 
     $remaining -= scalar(@$events);
 
-    print "Event definition ", $def->id, " has ", scalar(@$events), " event(s)\n";
+    print "Event definition ", $def->id, " has ", scalar(@$events), " (completed) event(s)\n";
     foreach (@$events) {
 
         my $event = $e->retrieve_action_trigger_event([

Modified: branches/serials-integration/Open-ILS/src/support-scripts/eg_db_config.pl
===================================================================
--- branches/serials-integration/Open-ILS/src/support-scripts/eg_db_config.pl	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/src/support-scripts/eg_db_config.pl	2010-10-18 13:46:56 UTC (rev 18371)
@@ -27,7 +27,6 @@
 my ($dbhost, $dbport, $dbname, $dbuser, $dbpw, $help);
 my $config_file = '';
 my $build_db_sh = '';
-my $bootstrap_file = '';
 my $offline_file = '';
 my $prefix = '';
 my $sysconfdir = '';
@@ -77,24 +76,6 @@
 		die "ERROR: Failed to update the configuration file '$config_file'\n";
 }
 
-# write out the DB bootstrapping config
-sub create_db_bootstrap {
-	my ($setup, $settings) = @_;
-
-	open(FH, '>', $setup) or die "Could not write database setup to $setup\n";
-
-	print "Writing database bootstrapping configuration to $setup\n";
-
-	printf FH "\$main::config{dsn} = 'dbi:Pg:host=%s;dbname=%s;port=%d';\n",
-		$settings->{host}, $settings->{db}, $settings->{port};
-
-	printf FH "\$main::config{usr} = '%s';\n", $settings->{user};
-	printf FH "\$main::config{pw} = '%s';\n", $settings->{pw};
-	
-	print FH "\$main::config{index} = 'config.cgi';\n";
-	close(FH);
-}
-
 # write out the offline config
 sub create_offline_config {
 	my ($setup, $settings) = @_;
@@ -149,17 +130,14 @@
 	chdir($script_dir);
 }
 
-my $bootstrap;
 my $offline;
 my $cschema;
 my $uconfig;
 my %settings;
 
 GetOptions("create-schema" => \$cschema, 
-		"create-bootstrap" => \$bootstrap,
 		"create-offline" => \$offline,
 		"update-config" => \$uconfig,
-		"bootstrap-file=s" => \$bootstrap_file,
 		"config-file=s" => \$config_file,
 		"build-db-file=s" => \$build_db_sh,
 		"service=s" => \@services,
@@ -194,10 +172,6 @@
 	$build_db_sh = File::Spec->catfile($script_dir, '../sql/Pg/build-db.sh');
 }
 
-if (!$bootstrap_file) {
-	$bootstrap_file = File::Spec->catfile($sysconfdir, 'live-db-setup.pl');
-}
-
 if (!$offline_file) {
 	$offline_file = File::Spec->catfile($sysconfdir, 'offline-config.pl');
 }
@@ -211,10 +185,9 @@
 get_settings(\%settings);
 
 if ($cschema) { create_schema(\%settings); }
-if ($bootstrap) { create_db_bootstrap($bootstrap_file, \%settings); }
 if ($offline) { create_offline_config($offline_file, \%settings); }
 
-if ((!$cschema && !$uconfig && !$bootstrap && !$offline) || $help) {
+if ((!$cschema && !$uconfig && !$offline) || $help) {
 	print <<HERE;
 
 SYNOPSIS
@@ -230,10 +203,6 @@
     --config-file
         specifies the opensrf.xml file. Defaults to /openils/conf/opensrf.xml
 
-    --bootstrap-file
-        specifies the database bootstrap file required by the CGI setup
-        interface. Defaults to /openils/conf/live-db-setup.pl
-
     --build-db-file
         specifies the script that creates the database schema. Defaults to
         Open-ILS/src/sql/pg/build-db.sh
@@ -247,9 +216,6 @@
         Configures Evergreen database settings in the file specified by
         --build-db-file.  
 
-    --create-bootstrap
-        Creates the database bootstrap file required by the CGI setup interface
-
     --create-offline
         Creates the database setting file required by the offline data uploader
 
@@ -287,7 +253,7 @@
    script with a complete set of commands:
 
    perl Open-ILS/src/support-scripts/eg_db_config.pl --update-config \
-       --service all --create-schema --create-bootstrap --create-offline \
+       --service all --create-schema --create-offline \
        --user evergreen --password evergreen --hostname localhost --port 5432 \
        --database evergreen 
 

Modified: branches/serials-integration/Open-ILS/src/support-scripts/settings-tester.pl
===================================================================
--- branches/serials-integration/Open-ILS/src/support-scripts/settings-tester.pl	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/src/support-scripts/settings-tester.pl	2010-10-18 13:46:56 UTC (rev 18371)
@@ -212,7 +212,7 @@
 
 # Check for oils_web.xml, required for acquisitions and many administration
 # interfaces as of Evergreen 1.6
-if (!-t '/openils/conf/oils_web.xml') {
+if (!-T '/openils/conf/oils_web.xml') {
 	my $de = "* WARNING: As of Evergreen 1.6, /openils/conf/oils_web.xml " .
 		"is a required configuration file. Copying " .
 		"/openils/conf/oils_web.xml.example should resolve this " .

Deleted: branches/serials-integration/Open-ILS/src/support-scripts/test-scripts/edi_object.pl
===================================================================
--- branches/serials-integration/Open-ILS/src/support-scripts/test-scripts/edi_object.pl	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/src/support-scripts/test-scripts/edi_object.pl	2010-10-18 13:46:56 UTC (rev 18371)
@@ -1,2985 +0,0 @@
-#!/usr/bin/perl
-#
-
-use strict; use warnings;
-
-use Data::Dumper;
-
-use OpenILS::Application::Acq::EDI;
-use OpenILS::Utils::Cronscript;
-use Business::EDI::Object;
-use Business::EDI::Segment::RFF;
-use vars qw/%code_hash/;
-
-require Business::EDI::DataElement;
-
-my $core = OpenILS::Utils::Cronscript->new();
-my $editor = $core->editor;
-
-my $slurp = join '', <DATA>;
-
-my ($aref, $whole) = OpenILS::Application::Acq::EDI->process_jedi($slurp);
-
-$Data::Dumper::Indent = 1;
-my $i = 0;
-foreach (@$aref) {
-    print "Building object from chunk ", ++$i, "\n";
-    my $obj = Business::EDI::Object->new($_);
-    print Dumper($obj);
-}
-
-print "\ndone\n";
-
-__DATA__
-{
-"trailer": ["UNZ", {
-    "0020": "2045",
-    "0036": 1
-}],
-"body": [{
-    "ORDRSP": [["UNH", {
-        "S009": {
-            "0052": "D",
-            "0054": "96A",
-            "0065": "ORDRSP",
-            "0051": "UN"
-        },
-        "0062": "723"
-    }], ["BGM", {
-        "4343": "AC",
-        "1225": "29",
-        "C002": {
-            "1001": "231"
-        },
-        "1004": "582822"
-    }], ["DTM", {
-        "C507": {
-            "2379": "102",
-            "2380": "20070618",
-            "2005": "137"
-        }
-    }], ["RFF", {
-        "C506": {
-            "1153": "ON",
-            "1154": "E07158FIC"
-        }
-    }], ["NAD", {
-        "C082": {
-            "3039": "8888888",
-            "3055": "31B"
-        },
-        "3035": "BY"
-    }], ["NAD", {
-        "C082": {
-            "3039": "1556150",
-            "3055": "31B"
-        },
-        "3035": "SU"
-    }], ["NAD", {
-        "C082": {
-            "3039": "8888888",
-            "3055": "91"
-        },
-        "3035": "BY"
-    }], ["CUX", {
-        "C504": [{
-            "6345": "USD",
-            "6347": "2",
-            "6343": "9"
-        }]
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["LACY, AL THINGS NOT SEEN"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 4,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 4,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "85"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "01",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 10.99
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4639/1"
-            }
-        }]],
-        "C212": {
-            "7140": "9781576734131",
-            "7143": "EN"
-        },
-        "1082": 1,
-        "1229": "5"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["LACY, AL FINAL JUSTICE"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 1,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 1,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "85"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "01",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 14.99
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4639/2"
-            }
-        }]],
-        "C212": {
-            "7140": "9781590529966",
-            "7143": "EN"
-        },
-        "1082": 2,
-        "1229": "5"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["MALAMUD, B NATURAL"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 5,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 5,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "85"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "01",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 14
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4639/3"
-            }
-        }]],
-        "C212": {
-            "7140": "9780374502003",
-            "7143": "EN"
-        },
-        "1082": 3,
-        "1229": "5"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["SCOTT, PAU RAJ QUARTET THE JEWEL IN"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 2,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 2,
-                "6063": "83"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "03",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 32.5
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4639/4"
-            }
-        }]],
-        "C212": {
-            "7140": "9780307263964",
-            "7143": "EN"
-        },
-        "1082": 4,
-        "1229": "24"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["JAMES, P.  SHROUD FOR A NIGHTINGALE"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 4,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 4,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "85"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "01",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 14
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4639/6"
-            }
-        }]],
-        "C212": {
-            "7140": "9780743219600",
-            "7143": "EN"
-        },
-        "1082": 5,
-        "1229": "5"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["LAHAYE, TI TRIBULATION FORCE THE CO"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 3,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 3,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "85"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "01",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 14.99
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4639/7"
-            }
-        }]],
-        "C212": {
-            "7140": "9780842329217",
-            "7143": "EN"
-        },
-        "1082": 6,
-        "1229": "5"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["ZANE AFTERBURN A NOVEL"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 4,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 4,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "85"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "01",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 15
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4639/8"
-            }
-        }]],
-        "C212": {
-            "7140": "9780743470988",
-            "7143": "EN"
-        },
-        "1082": 7,
-        "1229": "5"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["CABOT, MEG BOY NEXT DOOR"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 4,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 4,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "85"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "01",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 13.95
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4639/9"
-            }
-        }]],
-        "C212": {
-            "7140": "9780060096199",
-            "7143": "EN"
-        },
-        "1082": 8,
-        "1229": "5"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["VONNEGUT,  BREAKFAST OF CHAMPIONS"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 5,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 5,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "85"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "01",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 14
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4639/10"
-            }
-        }]],
-        "C212": {
-            "7140": "9780385334204",
-            "7143": "EN"
-        },
-        "1082": 9,
-        "1229": "5"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["DOSTOYEVSK BROTHERS KARAMAZOV"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 3,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 3,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "85"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "01",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 9.95
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4639/11"
-            }
-        }]],
-        "C212": {
-            "7140": "9781593083526",
-            "7143": "EN"
-        },
-        "1082": 10,
-        "1229": "5"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["KINGSBURY, FORGIVEN"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 6,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 6,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "85"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "01",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 13.99
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4639/12"
-            }
-        }]],
-        "C212": {
-            "7140": "9780842387446",
-            "7143": "EN"
-        },
-        "1082": 11,
-        "1229": "5"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["BERLINSKI, FIELDWORK"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 3,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 3,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "85"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "01",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 24
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4639/13"
-            }
-        }]],
-        "C212": {
-            "7140": "9780374299163",
-            "7143": "EN"
-        },
-        "1082": 12,
-        "1229": "5"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["GREGORY, P MERIDON A NOVEL"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 4,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 4,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "85"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "01",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 16
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4639/14"
-            }
-        }]],
-        "C212": {
-            "7140": "9780743249317",
-            "7143": "EN"
-        },
-        "1082": 13,
-        "1229": "5"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["MCCALL SMI MORALITY FOR BEAUTIFUL G"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 5,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 5,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "85"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "01",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 12.95
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4639/15"
-            }
-        }]],
-        "C212": {
-            "7140": "9781400031368",
-            "7143": "EN"
-        },
-        "1082": 14,
-        "1229": "5"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["CLEAGE, PE WHAT LOOKS LIKE CRAZY ON"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 3,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 3,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "85"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "01",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 13.95
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4639/16"
-            }
-        }]],
-        "C212": {
-            "7140": "9780380794874",
-            "7143": "EN"
-        },
-        "1082": 15,
-        "1229": "5"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["GREGORY, P WIDEACRE"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 4,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 4,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "85"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "01",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 16
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4639/17"
-            }
-        }]],
-        "C212": {
-            "7140": "9780743249294",
-            "7143": "EN"
-        },
-        "1082": 16,
-        "1229": "5"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["FERBER, ED SO BIG"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 3,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 3,
-                "6063": "83"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "07",
-                "3055": "28",
-                "1131": "7B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 13
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4639/18"
-            }
-        }]],
-        "C212": {
-            "7140": "9780060956691",
-            "7143": "EN"
-        },
-        "1082": 17,
-        "1229": "24"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["GREGORY, P OTHER BOLEYN GIRL"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 4,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 4,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "85"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "01",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 16
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4639/19"
-            }
-        }]],
-        "C212": {
-            "7140": "9780743227445",
-            "7143": "EN"
-        },
-        "1082": 18,
-        "1229": "5"
-    }], ["UNS", {
-        "0081": "S"
-    }], ["CNT", {
-        "C270": {
-            "6069": "2",
-            "6066": 18
-        }
-    }], ["UNT", {
-        "0074": 155,
-        "0062": "723"
-    }]]
-},
-{
-    "ORDRSP": [["UNH", {
-        "S009": {
-            "0052": "D",
-            "0054": "96A",
-            "0065": "ORDRSP",
-            "0051": "UN"
-        },
-        "0062": "724"
-    }], ["BGM", {
-        "4343": "AC",
-        "1225": "29",
-        "C002": {
-            "1001": "231"
-        },
-        "1004": "582828"
-    }], ["DTM", {
-        "C507": {
-            "2379": "102",
-            "2380": "20070618",
-            "2005": "137"
-        }
-    }], ["RFF", {
-        "C506": {
-            "1153": "ON",
-            "1154": "E07159ANF"
-        }
-    }], ["NAD", {
-        "C082": {
-            "3039": "8888888",
-            "3055": "31B"
-        },
-        "3035": "BY"
-    }], ["NAD", {
-        "C082": {
-            "3039": "1556150",
-            "3055": "31B"
-        },
-        "3035": "SU"
-    }], ["NAD", {
-        "C082": {
-            "3039": "8888888",
-            "3055": "91"
-        },
-        "3035": "BY"
-    }], ["CUX", {
-        "C504": [{
-            "6345": "USD",
-            "6347": "2",
-            "6343": "9"
-        }]
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["HOLM, BILL WINDOWS OF BRIMNES"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 3,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 3,
-                "6063": "83"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "03",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 22
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4640/1"
-            }
-        }]],
-        "C212": {
-            "7140": "9781571313027",
-            "7143": "EN"
-        },
-        "1082": 1,
-        "1229": "24"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["REPA, BARB YOUR RIGHTS IN THE WORKP"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 4,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 4,
-                "6063": "83"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "03",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 29.99
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4640/2"
-            }
-        }]],
-        "C212": {
-            "7140": "9781413306439",
-            "7143": "EN"
-        },
-        "1082": 2,
-        "1229": "24"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["GUERIN, LI ESSENTIAL GUIDE TO WORKP"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 2,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 2,
-                "6063": "83"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "03",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 39.99
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4640/3"
-            }
-        }]],
-        "C212": {
-            "7140": "9781413306910",
-            "7143": "EN"
-        },
-        "1082": 3,
-        "1229": "24"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["CLIFFORD,  ESTATE PLANNING BASICS"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 5,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 5,
-                "6063": "83"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "03",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 21.99
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4640/4"
-            }
-        }]],
-        "C212": {
-            "7140": "9781413307023",
-            "7143": "EN"
-        },
-        "1082": 4,
-        "1229": "24"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["FRIEDMAN,  BABY CARE BOOK"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 8,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 8,
-                "6063": "83"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "03",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 29.95
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4640/5"
-            }
-        }]],
-        "C212": {
-            "7140": "9780778801603",
-            "7143": "EN"
-        },
-        "1082": 5,
-        "1229": "24"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["KING, RUSS ATLAS OF HUMAN MIGRATION"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 3,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 3,
-                "6063": "83"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "03",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 40
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4640/6"
-            }
-        }]],
-        "C212": {
-            "7140": "9781554072873",
-            "7143": "EN"
-        },
-        "1082": 6,
-        "1229": "24"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["ASH, RUSSE FIREFLYS WORLD OF FACTS"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 6,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 6,
-                "6063": "83"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "03",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 29.95
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4640/7"
-            }
-        }]],
-        "C212": {
-            "7140": "9781554073139",
-            "7143": "EN"
-        },
-        "1082": 7,
-        "1229": "24"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["WARNER, RA 101 LAW FORMS FOR PERSON"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 6,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 6,
-                "6063": "83"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "03",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 29.99
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4640/8"
-            }
-        }]],
-        "C212": {
-            "7140": "9781413307122",
-            "7143": "EN"
-        },
-        "1082": 8,
-        "1229": "24"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["BRAY, ILON NOLOS ESSENTIAL GUIDE TO"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 10,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 10,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "85"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "01",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 24.99
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4640/9"
-            }
-        }]],
-        "C212": {
-            "7140": "9781413306286",
-            "7143": "EN"
-        },
-        "1082": 9,
-        "1229": "5"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["WESTWOOD,  HOW TO WRITE A MARKETING"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 3,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 1,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 2,
-                "6063": "83"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "99",
-                "3055": "28",
-                "1131": "7B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 17.95
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4640/10"
-            }
-        }]],
-        "C212": {
-            "7140": "9780749445546",
-            "7143": "EN"
-        },
-        "1082": 10,
-        "1229": "24"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["ROANE, SUS HOW TO WORK A ROOM YOUR "]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 8,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 8,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "85"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "01",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 14.95
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4640/11"
-            }
-        }]],
-        "C212": {
-            "7140": "9780061238673",
-            "7143": "EN"
-        },
-        "1082": 11,
-        "1229": "5"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["GERMAIN, D REACHING PAST THE WIRE A"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 4,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 4,
-                "6063": "83"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "03",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 24.95
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4640/12"
-            }
-        }]],
-        "C212": {
-            "7140": "9780873516068",
-            "7143": "EN"
-        },
-        "1082": 12,
-        "1229": "24"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["KLING, KEV DOG SAYS HOW"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 3,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 3,
-                "6063": "83"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "03",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 22.95
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4640/13"
-            }
-        }]],
-        "C212": {
-            "7140": "9780873515993",
-            "7143": "EN"
-        },
-        "1082": 13,
-        "1229": "24"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["SHORT, SUS BUNDT CAKE BLISS DELICIO"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 5,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 5,
-                "6063": "83"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "03",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 16.95
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4640/14"
-            }
-        }]],
-        "C212": {
-            "7140": "9780873515856",
-            "7143": "EN"
-        },
-        "1082": 14,
-        "1229": "24"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["BRADY, TIM GOPHER GOLD LEGENDARY FI"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 2,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 2,
-                "6063": "83"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "03",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 24.95
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4640/15"
-            }
-        }]],
-        "C212": {
-            "7140": "9780873516013",
-            "7143": "EN"
-        },
-        "1082": 15,
-        "1229": "24"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["ROBERTS, K MINNESOTA 150 THE PEOPLE"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 8,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 8,
-                "6063": "83"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "03",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 19.95
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4640/16"
-            }
-        }]],
-        "C212": {
-            "7140": "9780873515948",
-            "7143": "EN"
-        },
-        "1082": 16,
-        "1229": "24"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["MAK, GEERT IN EUROPE A JOURNEY THRO"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 2,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 2,
-                "6063": "83"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "03",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 35
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4640/17"
-            }
-        }]],
-        "C212": {
-            "7140": "9780375424953",
-            "7143": "EN"
-        },
-        "1082": 17,
-        "1229": "24"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["DONAHUE, P PARENTING WITHOUT FEAR O"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 5,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 5,
-                "6063": "83"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "03",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 14.95
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4640/18"
-            }
-        }]],
-        "C212": {
-            "7140": "9780312358914",
-            "7143": "EN"
-        },
-        "1082": 18,
-        "1229": "24"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["MURRAY, LI BABYCENTERS ESSENTIAL GU"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 8,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 8,
-                "6063": "83"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "03",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 15.95
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4640/19"
-            }
-        }]],
-        "C212": {
-            "7140": "9781594864117",
-            "7143": "EN"
-        },
-        "1082": 19,
-        "1229": "24"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["LAPINE, MI SNEAKY CHEF SIMPLE STRAT"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 6,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 6,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "85"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "01",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 17.95
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4640/20"
-            }
-        }]],
-        "C212": {
-            "7140": "9780762430758",
-            "7143": "EN"
-        },
-        "1082": 20,
-        "1229": "5"
-    }], ["UNS", {
-        "0081": "S"
-    }], ["CNT", {
-        "C270": {
-            "6069": "2",
-            "6066": 20
-        }
-    }], ["UNT", {
-        "0074": 171,
-        "0062": "724"
-    }]]
-},
-{
-    "ORDRSP": [["UNH", {
-        "S009": {
-            "0052": "D",
-            "0054": "96A",
-            "0065": "ORDRSP",
-            "0051": "UN"
-        },
-        "0062": "725"
-    }], ["BGM", {
-        "4343": "AC",
-        "1225": "29",
-        "C002": {
-            "1001": "231"
-        },
-        "1004": "582830"
-    }], ["DTM", {
-        "C507": {
-            "2379": "102",
-            "2380": "20070618",
-            "2005": "137"
-        }
-    }], ["RFF", {
-        "C506": {
-            "1153": "ON",
-            "1154": "E07160FIC"
-        }
-    }], ["NAD", {
-        "C082": {
-            "3039": "8888888",
-            "3055": "31B"
-        },
-        "3035": "BY"
-    }], ["NAD", {
-        "C082": {
-            "3039": "1556150",
-            "3055": "31B"
-        },
-        "3035": "SU"
-    }], ["NAD", {
-        "C082": {
-            "3039": "8888888",
-            "3055": "91"
-        },
-        "3035": "BY"
-    }], ["CUX", {
-        "C504": [{
-            "6345": "USD",
-            "6347": "2",
-            "6343": "9"
-        }]
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["SHAW, REBE COUNTRY LOVERS"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 5,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 5,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "85"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "01",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 12.95
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4641/1"
-            }
-        }]],
-        "C212": {
-            "7140": "9781400098224",
-            "7143": "EN"
-        },
-        "1082": 1,
-        "1229": "5"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["BLAKE, TON TEMPT ME TONIGHT"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 4,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 4,
-                "6063": "83"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "07",
-                "3055": "28",
-                "1131": "7B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 13.95
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4641/2"
-            }
-        }]],
-        "C212": {
-            "7140": "9780061136092",
-            "7143": "EN"
-        },
-        "1082": 2,
-        "1229": "24"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["MONING, KA BLOODFEVER"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 6,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 6,
-                "6063": "83"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "03",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 22
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4641/3"
-            }
-        }]],
-        "C212": {
-            "7140": "9780385339162",
-            "7143": "EN"
-        },
-        "1082": 3,
-        "1229": "24"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["MCKENNA, S EDGE OF MIDNIGHT"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 8,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 8,
-                "6063": "83"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "03",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 14
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4641/4"
-            }
-        }]],
-        "C212": {
-            "7140": "9780758211859",
-            "7143": "EN"
-        },
-        "1082": 4,
-        "1229": "24"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["BALZO, SAN GROUNDS FOR MURDER"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 8,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 8,
-                "6063": "83"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "03",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 27.95
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4641/5"
-            }
-        }]],
-        "C212": {
-            "7140": "9780727865496",
-            "7143": "EN"
-        },
-        "1082": 5,
-        "1229": "24"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["PALMER, DI HARD TO HANDLE"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 8,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 8,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "85"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "01",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 13.95
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4641/6"
-            }
-        }]],
-        "C212": {
-            "7140": "9780373772612",
-            "7143": "EN"
-        },
-        "1082": 6,
-        "1229": "5"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["JONES, LLO MR PIP"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 3,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 3,
-                "6063": "83"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "03",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 20
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4641/7"
-            }
-        }]],
-        "C212": {
-            "7140": "9780385341066",
-            "7143": "EN"
-        },
-        "1082": 7,
-        "1229": "24"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["JILES, PAU STORMY WEATHER"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 8,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 8,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "85"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "01",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 24.95
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4641/8"
-            }
-        }]],
-        "C212": {
-            "7140": "9780060537326",
-            "7143": "EN"
-        },
-        "1082": 8,
-        "1229": "5"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["DELILLO, D FALLING MAN A NOVEL"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 4,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 4,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "85"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "01",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 26
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4641/9"
-            }
-        }]],
-        "C212": {
-            "7140": "9781416546023",
-            "7143": "EN"
-        },
-        "1082": 9,
-        "1229": "5"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["MORRISON,  SWEETER THAN HONEY"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 3,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 3,
-                "6063": "83"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "03",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 24
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4641/10"
-            }
-        }]],
-        "C212": {
-            "7140": "9780758215116",
-            "7143": "EN"
-        },
-        "1082": 10,
-        "1229": "24"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["SMITH, SHE FOX"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 2,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 2,
-                "6063": "83"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "03",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 25.95
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4641/11"
-            }
-        }]],
-        "C212": {
-            "7140": "9780756404215",
-            "7143": "EN"
-        },
-        "1082": 11,
-        "1229": "24"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["GROSSMAN,  SOON I WILL BE INVINCIBL"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 2,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 2,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "85"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "01",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 22.95
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4641/12"
-            }
-        }]],
-        "C212": {
-            "7140": "9780375424861",
-            "7143": "EN"
-        },
-        "1082": 12,
-        "1229": "5"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["LEWYCKA, M SHORT HISTORY OF TRACTOR"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 3,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 3,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "85"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "01",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 14
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4641/13"
-            }
-        }]],
-        "C212": {
-            "7140": "9780143036746",
-            "7143": "EN"
-        },
-        "1082": 13,
-        "1229": "5"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["BANNISTER, FLAWED"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 4,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 4,
-                "6063": "83"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "03",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 24.95
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4641/14"
-            }
-        }]],
-        "C212": {
-            "7140": "9780312375669",
-            "7143": "EN"
-        },
-        "1082": 14,
-        "1229": "24"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["ALEXANDER, REMEMBERED"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 8,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 8,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "85"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "01",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 13.99
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4641/15"
-            }
-        }]],
-        "C212": {
-            "7140": "9780764201103",
-            "7143": "EN"
-        },
-        "1082": 15,
-        "1229": "5"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["TANIGUCHI, OCEAN IN THE CLOSET"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 2,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 2,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "85"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "01",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 14.95
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4641/16"
-            }
-        }]],
-        "C212": {
-            "7140": "9781566891943",
-            "7143": "EN"
-        },
-        "1082": 16,
-        "1229": "5"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["HENKE, ROX SECRET OF US"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 5,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 5,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "85"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "01",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 13.99
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4641/17"
-            }
-        }]],
-        "C212": {
-            "7140": "9780736917018",
-            "7143": "EN"
-        },
-        "1082": 17,
-        "1229": "5"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["HERMAN, KA EVER PRESENT DANGER"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 5,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 5,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "85"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "01",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 12.99
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4641/18"
-            }
-        }]],
-        "C212": {
-            "7140": "9781590529218",
-            "7143": "EN"
-        },
-        "1082": 18,
-        "1229": "5"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["CHAPMAN, G IT HAPPENS EVERY SPRING"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 5,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 5,
-                "6063": "83"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "07",
-                "3055": "28",
-                "1131": "7B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 12.99
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4641/19"
-            }
-        }]],
-        "C212": {
-            "7140": "9781414311654",
-            "7143": "EN"
-        },
-        "1082": 19,
-        "1229": "24"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["JACKSON, N YADA YADA PRAYER GROUP G"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 8,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 8,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "85"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "01",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 13.99
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4641/20"
-            }
-        }]],
-        "C212": {
-            "7140": "9781591453628",
-            "7143": "EN"
-        },
-        "1082": 20,
-        "1229": "5"
-    }], ["UNS", {
-        "0081": "S"
-    }], ["CNT", {
-        "C270": {
-            "6069": "2",
-            "6066": 20
-        }
-    }], ["UNT", {
-        "0074": 171,
-        "0062": "725"
-    }]]
-}],
-"recipient": "8888888",
-"sender": "1556150",
-"header": ["UNB", {
-    "S003": {
-        "0007": "31B",
-        "0010": "8888888"
-    },
-    "0020": "2045",
-    "S004": {
-        "0019": 1556,
-        "0017": 70618
-    },
-    "S001": {
-        "0001": "UNOC",
-        "0002": 3
-    },
-    "S002": {
-        "0007": "31B",
-        "0004": "1556150"
-    }
-}],
-"sender_qual": "31B",
-"UNA": {
-    "seg_term": "'",
-    "decimal_sign": ".",
-    "esc_char": "?",
-    "de_sep": "+",
-    "ce_sep": ":",
-    "rep_sep": " "
-},
-"recipient_qual": "31B"
-}

Modified: branches/serials-integration/Open-ILS/src/support-scripts/test-scripts/ftp_ls.pl
===================================================================
--- branches/serials-integration/Open-ILS/src/support-scripts/test-scripts/ftp_ls.pl	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/src/support-scripts/test-scripts/ftp_ls.pl	2010-10-18 13:46:56 UTC (rev 18371)
@@ -57,7 +57,7 @@
 }
 close TEMP;
 
-my $dir = '/home/some_user/out';
+my $dir = '/home/' . $config{remote_user} . '/out';
 $delay and print "Sleeping $delay seconds\n" and sleep $delay;
 
 my $glob6 = $dir . '/*Q*';

Deleted: branches/serials-integration/Open-ILS/src/support-scripts/test-scripts/ordrsp_parse.pl
===================================================================
--- branches/serials-integration/Open-ILS/src/support-scripts/test-scripts/ordrsp_parse.pl	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/src/support-scripts/test-scripts/ordrsp_parse.pl	2010-10-18 13:46:56 UTC (rev 18371)
@@ -1,3058 +0,0 @@
-#!/usr/bin/perl
-#
-
-use strict; use warnings;
-
-use Data::Dumper;
-
-use OpenILS::Utils::Cronscript;
-use OpenILS::Application::Acq::EDI;
-use Business::EDI::DataElement;
-use Business::EDI::Segment::RFF;
-use vars qw/%code_hash/;
-
-require Business::EDI::DataElement;
-
-my $verbose = @ARGV ? shift : 0;
-
-my $core = OpenILS::Utils::Cronscript->new();
-my $editor = $core->editor;
-
-my $slurp = join '', <DATA>;
-
-my ($aref, $whole) = OpenILS::Application::Acq::EDI->process_jedi($slurp);
-
-$Data::Dumper::Indent = 1;
-# print Dumper($aref);
-my @innards = @$aref;
-my @rffs;
-
-# `print Dumper(\@innards);
-
-=pod
-    ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["LACY, AL THINGS NOT SEEN"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 4,
-                "6063": "21"
-            }
-        }], ...
-            ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4639/1"
-            }
-        }], ... ]}]
-
-=cut
-
-my @qtys = ();
-foreach (@innards) {
-    
-#   my $count = scalar(@{$_->{SG26}});
-   my $count = scalar(@$_);
-   print STDERR "->{SG26} has $count pieces: ";
-   for (my $i = 0; $i < $count; $i++) {
-        my $label = $_->[$i]->[0];
-        my $body  = $_->[$i]->[1];
-        print STDERR "$label ";
-        $label eq 'QTY' and push @qtys, $body;
-        $label eq 'RFF' and push @rffs, $body;
-    }
-    print STDERR "\n";
-    # foreach my $qty (@{$_->{SG26}->[0]}) {
-}
-
-printf "%4d LINs found\n", scalar(@innards);
-printf "%4d QTYs found\n", scalar(@qtys);
-printf "%4d RFFs found (inside LINs)\n", scalar(@rffs);
-
-sub example_dump {
-    my $example = shift or return;
-    print "\nexample QTY: ", Dumper($example);
-    foreach (keys %{$example->{C186}}) {
-        # no warnings 'uninitialized';
-        my $x = Business::EDI::DataElement->new($_);
-        print $x->label, " ($_) : ", $example->{C186}->{$_}, "\n";
-    }
-}
-
-# example_dump($qtys[-1]);
-
-# We want: RFF > C506 > 1154 where 1153 = LI
-foreach my $rff (@rffs) {
-    my $obj = Business::EDI::Segment::RFF->new($rff);
-    $verbose and print Dumper ($obj);
-    foreach my $subrff (keys %$rff) {
-        $subrff eq 'C506' or next;
-        my $i = 0;
-        foreach (sort keys %{$rff->{$subrff}}) {
-            my $x = Business::EDI::DataElement->new($_, $rff->{$subrff}->{$_});
-            $x or warn "Unknown DataElement code $_";
-            print "$_ ", $x->label, " ", $x->value, " ";
-            $i++ == 0 and print "==> ";
-        }
-        print "\n";
-    }
-}
-print "\ndone\n";
-
-__DATA__
-{
-"trailer": ["UNZ", {
-    "0020": "2045",
-    "0036": 1
-}],
-"body": [{
-    "ORDRSP": [["UNH", {
-        "S009": {
-            "0052": "D",
-            "0054": "96A",
-            "0065": "ORDRSP",
-            "0051": "UN"
-        },
-        "0062": "723"
-    }], ["BGM", {
-        "4343": "AC",
-        "1225": "29",
-        "C002": {
-            "1001": "231"
-        },
-        "1004": "582822"
-    }], ["DTM", {
-        "C507": {
-            "2379": "102",
-            "2380": "20070618",
-            "2005": "137"
-        }
-    }], ["RFF", {
-        "C506": {
-            "1153": "ON",
-            "1154": "E07158FIC"
-        }
-    }], ["NAD", {
-        "C082": {
-            "3039": "8888888",
-            "3055": "31B"
-        },
-        "3035": "BY"
-    }], ["NAD", {
-        "C082": {
-            "3039": "1556150",
-            "3055": "31B"
-        },
-        "3035": "SU"
-    }], ["NAD", {
-        "C082": {
-            "3039": "8888888",
-            "3055": "91"
-        },
-        "3035": "BY"
-    }], ["CUX", {
-        "C504": [{
-            "6345": "USD",
-            "6347": "2",
-            "6343": "9"
-        }]
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["LACY, AL THINGS NOT SEEN"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 4,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 4,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "85"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "01",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 10.99
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4639/1"
-            }
-        }]],
-        "C212": {
-            "7140": "9781576734131",
-            "7143": "EN"
-        },
-        "1082": 1,
-        "1229": "5"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["LACY, AL FINAL JUSTICE"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 1,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 1,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "85"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "01",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 14.99
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4639/2"
-            }
-        }]],
-        "C212": {
-            "7140": "9781590529966",
-            "7143": "EN"
-        },
-        "1082": 2,
-        "1229": "5"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["MALAMUD, B NATURAL"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 5,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 5,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "85"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "01",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 14
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4639/3"
-            }
-        }]],
-        "C212": {
-            "7140": "9780374502003",
-            "7143": "EN"
-        },
-        "1082": 3,
-        "1229": "5"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["SCOTT, PAU RAJ QUARTET THE JEWEL IN"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 2,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 2,
-                "6063": "83"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "03",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 32.5
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4639/4"
-            }
-        }]],
-        "C212": {
-            "7140": "9780307263964",
-            "7143": "EN"
-        },
-        "1082": 4,
-        "1229": "24"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["JAMES, P.  SHROUD FOR A NIGHTINGALE"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 4,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 4,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "85"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "01",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 14
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4639/6"
-            }
-        }]],
-        "C212": {
-            "7140": "9780743219600",
-            "7143": "EN"
-        },
-        "1082": 5,
-        "1229": "5"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["LAHAYE, TI TRIBULATION FORCE THE CO"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 3,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 3,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "85"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "01",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 14.99
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4639/7"
-            }
-        }]],
-        "C212": {
-            "7140": "9780842329217",
-            "7143": "EN"
-        },
-        "1082": 6,
-        "1229": "5"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["ZANE AFTERBURN A NOVEL"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 4,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 4,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "85"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "01",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 15
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4639/8"
-            }
-        }]],
-        "C212": {
-            "7140": "9780743470988",
-            "7143": "EN"
-        },
-        "1082": 7,
-        "1229": "5"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["CABOT, MEG BOY NEXT DOOR"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 4,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 4,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "85"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "01",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 13.95
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4639/9"
-            }
-        }]],
-        "C212": {
-            "7140": "9780060096199",
-            "7143": "EN"
-        },
-        "1082": 8,
-        "1229": "5"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["VONNEGUT,  BREAKFAST OF CHAMPIONS"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 5,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 5,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "85"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "01",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 14
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4639/10"
-            }
-        }]],
-        "C212": {
-            "7140": "9780385334204",
-            "7143": "EN"
-        },
-        "1082": 9,
-        "1229": "5"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["DOSTOYEVSK BROTHERS KARAMAZOV"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 3,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 3,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "85"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "01",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 9.95
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4639/11"
-            }
-        }]],
-        "C212": {
-            "7140": "9781593083526",
-            "7143": "EN"
-        },
-        "1082": 10,
-        "1229": "5"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["KINGSBURY, FORGIVEN"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 6,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 6,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "85"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "01",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 13.99
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4639/12"
-            }
-        }]],
-        "C212": {
-            "7140": "9780842387446",
-            "7143": "EN"
-        },
-        "1082": 11,
-        "1229": "5"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["BERLINSKI, FIELDWORK"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 3,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 3,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "85"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "01",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 24
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4639/13"
-            }
-        }]],
-        "C212": {
-            "7140": "9780374299163",
-            "7143": "EN"
-        },
-        "1082": 12,
-        "1229": "5"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["GREGORY, P MERIDON A NOVEL"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 4,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 4,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "85"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "01",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 16
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4639/14"
-            }
-        }]],
-        "C212": {
-            "7140": "9780743249317",
-            "7143": "EN"
-        },
-        "1082": 13,
-        "1229": "5"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["MCCALL SMI MORALITY FOR BEAUTIFUL G"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 5,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 5,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "85"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "01",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 12.95
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4639/15"
-            }
-        }]],
-        "C212": {
-            "7140": "9781400031368",
-            "7143": "EN"
-        },
-        "1082": 14,
-        "1229": "5"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["CLEAGE, PE WHAT LOOKS LIKE CRAZY ON"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 3,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 3,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "85"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "01",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 13.95
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4639/16"
-            }
-        }]],
-        "C212": {
-            "7140": "9780380794874",
-            "7143": "EN"
-        },
-        "1082": 15,
-        "1229": "5"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["GREGORY, P WIDEACRE"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 4,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 4,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "85"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "01",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 16
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4639/17"
-            }
-        }]],
-        "C212": {
-            "7140": "9780743249294",
-            "7143": "EN"
-        },
-        "1082": 16,
-        "1229": "5"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["FERBER, ED SO BIG"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 3,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 3,
-                "6063": "83"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "07",
-                "3055": "28",
-                "1131": "7B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 13
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4639/18"
-            }
-        }]],
-        "C212": {
-            "7140": "9780060956691",
-            "7143": "EN"
-        },
-        "1082": 17,
-        "1229": "24"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["GREGORY, P OTHER BOLEYN GIRL"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 4,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 4,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "85"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "01",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 16
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4639/19"
-            }
-        }]],
-        "C212": {
-            "7140": "9780743227445",
-            "7143": "EN"
-        },
-        "1082": 18,
-        "1229": "5"
-    }], ["UNS", {
-        "0081": "S"
-    }], ["CNT", {
-        "C270": {
-            "6069": "2",
-            "6066": 18
-        }
-    }], ["UNT", {
-        "0074": 155,
-        "0062": "723"
-    }]]
-},
-{
-    "ORDRSP": [["UNH", {
-        "S009": {
-            "0052": "D",
-            "0054": "96A",
-            "0065": "ORDRSP",
-            "0051": "UN"
-        },
-        "0062": "724"
-    }], ["BGM", {
-        "4343": "AC",
-        "1225": "29",
-        "C002": {
-            "1001": "231"
-        },
-        "1004": "582828"
-    }], ["DTM", {
-        "C507": {
-            "2379": "102",
-            "2380": "20070618",
-            "2005": "137"
-        }
-    }], ["RFF", {
-        "C506": {
-            "1153": "ON",
-            "1154": "E07159ANF"
-        }
-    }], ["NAD", {
-        "C082": {
-            "3039": "8888888",
-            "3055": "31B"
-        },
-        "3035": "BY"
-    }], ["NAD", {
-        "C082": {
-            "3039": "1556150",
-            "3055": "31B"
-        },
-        "3035": "SU"
-    }], ["NAD", {
-        "C082": {
-            "3039": "8888888",
-            "3055": "91"
-        },
-        "3035": "BY"
-    }], ["CUX", {
-        "C504": [{
-            "6345": "USD",
-            "6347": "2",
-            "6343": "9"
-        }]
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["HOLM, BILL WINDOWS OF BRIMNES"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 3,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 3,
-                "6063": "83"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "03",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 22
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4640/1"
-            }
-        }]],
-        "C212": {
-            "7140": "9781571313027",
-            "7143": "EN"
-        },
-        "1082": 1,
-        "1229": "24"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["REPA, BARB YOUR RIGHTS IN THE WORKP"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 4,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 4,
-                "6063": "83"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "03",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 29.99
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4640/2"
-            }
-        }]],
-        "C212": {
-            "7140": "9781413306439",
-            "7143": "EN"
-        },
-        "1082": 2,
-        "1229": "24"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["GUERIN, LI ESSENTIAL GUIDE TO WORKP"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 2,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 2,
-                "6063": "83"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "03",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 39.99
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4640/3"
-            }
-        }]],
-        "C212": {
-            "7140": "9781413306910",
-            "7143": "EN"
-        },
-        "1082": 3,
-        "1229": "24"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["CLIFFORD,  ESTATE PLANNING BASICS"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 5,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 5,
-                "6063": "83"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "03",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 21.99
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4640/4"
-            }
-        }]],
-        "C212": {
-            "7140": "9781413307023",
-            "7143": "EN"
-        },
-        "1082": 4,
-        "1229": "24"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["FRIEDMAN,  BABY CARE BOOK"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 8,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 8,
-                "6063": "83"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "03",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 29.95
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4640/5"
-            }
-        }]],
-        "C212": {
-            "7140": "9780778801603",
-            "7143": "EN"
-        },
-        "1082": 5,
-        "1229": "24"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["KING, RUSS ATLAS OF HUMAN MIGRATION"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 3,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 3,
-                "6063": "83"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "03",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 40
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4640/6"
-            }
-        }]],
-        "C212": {
-            "7140": "9781554072873",
-            "7143": "EN"
-        },
-        "1082": 6,
-        "1229": "24"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["ASH, RUSSE FIREFLYS WORLD OF FACTS"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 6,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 6,
-                "6063": "83"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "03",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 29.95
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4640/7"
-            }
-        }]],
-        "C212": {
-            "7140": "9781554073139",
-            "7143": "EN"
-        },
-        "1082": 7,
-        "1229": "24"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["WARNER, RA 101 LAW FORMS FOR PERSON"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 6,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 6,
-                "6063": "83"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "03",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 29.99
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4640/8"
-            }
-        }]],
-        "C212": {
-            "7140": "9781413307122",
-            "7143": "EN"
-        },
-        "1082": 8,
-        "1229": "24"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["BRAY, ILON NOLOS ESSENTIAL GUIDE TO"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 10,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 10,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "85"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "01",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 24.99
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4640/9"
-            }
-        }]],
-        "C212": {
-            "7140": "9781413306286",
-            "7143": "EN"
-        },
-        "1082": 9,
-        "1229": "5"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["WESTWOOD,  HOW TO WRITE A MARKETING"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 3,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 1,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 2,
-                "6063": "83"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "99",
-                "3055": "28",
-                "1131": "7B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 17.95
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4640/10"
-            }
-        }]],
-        "C212": {
-            "7140": "9780749445546",
-            "7143": "EN"
-        },
-        "1082": 10,
-        "1229": "24"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["ROANE, SUS HOW TO WORK A ROOM YOUR "]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 8,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 8,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "85"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "01",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 14.95
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4640/11"
-            }
-        }]],
-        "C212": {
-            "7140": "9780061238673",
-            "7143": "EN"
-        },
-        "1082": 11,
-        "1229": "5"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["GERMAIN, D REACHING PAST THE WIRE A"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 4,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 4,
-                "6063": "83"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "03",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 24.95
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4640/12"
-            }
-        }]],
-        "C212": {
-            "7140": "9780873516068",
-            "7143": "EN"
-        },
-        "1082": 12,
-        "1229": "24"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["KLING, KEV DOG SAYS HOW"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 3,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 3,
-                "6063": "83"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "03",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 22.95
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4640/13"
-            }
-        }]],
-        "C212": {
-            "7140": "9780873515993",
-            "7143": "EN"
-        },
-        "1082": 13,
-        "1229": "24"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["SHORT, SUS BUNDT CAKE BLISS DELICIO"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 5,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 5,
-                "6063": "83"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "03",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 16.95
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4640/14"
-            }
-        }]],
-        "C212": {
-            "7140": "9780873515856",
-            "7143": "EN"
-        },
-        "1082": 14,
-        "1229": "24"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["BRADY, TIM GOPHER GOLD LEGENDARY FI"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 2,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 2,
-                "6063": "83"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "03",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 24.95
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4640/15"
-            }
-        }]],
-        "C212": {
-            "7140": "9780873516013",
-            "7143": "EN"
-        },
-        "1082": 15,
-        "1229": "24"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["ROBERTS, K MINNESOTA 150 THE PEOPLE"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 8,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 8,
-                "6063": "83"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "03",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 19.95
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4640/16"
-            }
-        }]],
-        "C212": {
-            "7140": "9780873515948",
-            "7143": "EN"
-        },
-        "1082": 16,
-        "1229": "24"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["MAK, GEERT IN EUROPE A JOURNEY THRO"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 2,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 2,
-                "6063": "83"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "03",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 35
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4640/17"
-            }
-        }]],
-        "C212": {
-            "7140": "9780375424953",
-            "7143": "EN"
-        },
-        "1082": 17,
-        "1229": "24"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["DONAHUE, P PARENTING WITHOUT FEAR O"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 5,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 5,
-                "6063": "83"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "03",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 14.95
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4640/18"
-            }
-        }]],
-        "C212": {
-            "7140": "9780312358914",
-            "7143": "EN"
-        },
-        "1082": 18,
-        "1229": "24"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["MURRAY, LI BABYCENTERS ESSENTIAL GU"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 8,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 8,
-                "6063": "83"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "03",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 15.95
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4640/19"
-            }
-        }]],
-        "C212": {
-            "7140": "9781594864117",
-            "7143": "EN"
-        },
-        "1082": 19,
-        "1229": "24"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["LAPINE, MI SNEAKY CHEF SIMPLE STRAT"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 6,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 6,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "85"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "01",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 17.95
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4640/20"
-            }
-        }]],
-        "C212": {
-            "7140": "9780762430758",
-            "7143": "EN"
-        },
-        "1082": 20,
-        "1229": "5"
-    }], ["UNS", {
-        "0081": "S"
-    }], ["CNT", {
-        "C270": {
-            "6069": "2",
-            "6066": 20
-        }
-    }], ["UNT", {
-        "0074": 171,
-        "0062": "724"
-    }]]
-},
-{
-    "ORDRSP": [["UNH", {
-        "S009": {
-            "0052": "D",
-            "0054": "96A",
-            "0065": "ORDRSP",
-            "0051": "UN"
-        },
-        "0062": "725"
-    }], ["BGM", {
-        "4343": "AC",
-        "1225": "29",
-        "C002": {
-            "1001": "231"
-        },
-        "1004": "582830"
-    }], ["DTM", {
-        "C507": {
-            "2379": "102",
-            "2380": "20070618",
-            "2005": "137"
-        }
-    }], ["RFF", {
-        "C506": {
-            "1153": "ON",
-            "1154": "E07160FIC"
-        }
-    }], ["NAD", {
-        "C082": {
-            "3039": "8888888",
-            "3055": "31B"
-        },
-        "3035": "BY"
-    }], ["NAD", {
-        "C082": {
-            "3039": "1556150",
-            "3055": "31B"
-        },
-        "3035": "SU"
-    }], ["NAD", {
-        "C082": {
-            "3039": "8888888",
-            "3055": "91"
-        },
-        "3035": "BY"
-    }], ["CUX", {
-        "C504": [{
-            "6345": "USD",
-            "6347": "2",
-            "6343": "9"
-        }]
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["SHAW, REBE COUNTRY LOVERS"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 5,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 5,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "85"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "01",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 12.95
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4641/1"
-            }
-        }]],
-        "C212": {
-            "7140": "9781400098224",
-            "7143": "EN"
-        },
-        "1082": 1,
-        "1229": "5"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["BLAKE, TON TEMPT ME TONIGHT"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 4,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 4,
-                "6063": "83"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "07",
-                "3055": "28",
-                "1131": "7B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 13.95
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4641/2"
-            }
-        }]],
-        "C212": {
-            "7140": "9780061136092",
-            "7143": "EN"
-        },
-        "1082": 2,
-        "1229": "24"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["MONING, KA BLOODFEVER"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 6,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 6,
-                "6063": "83"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "03",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 22
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4641/3"
-            }
-        }]],
-        "C212": {
-            "7140": "9780385339162",
-            "7143": "EN"
-        },
-        "1082": 3,
-        "1229": "24"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["MCKENNA, S EDGE OF MIDNIGHT"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 8,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 8,
-                "6063": "83"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "03",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 14
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4641/4"
-            }
-        }]],
-        "C212": {
-            "7140": "9780758211859",
-            "7143": "EN"
-        },
-        "1082": 4,
-        "1229": "24"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["BALZO, SAN GROUNDS FOR MURDER"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 8,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 8,
-                "6063": "83"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "03",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 27.95
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4641/5"
-            }
-        }]],
-        "C212": {
-            "7140": "9780727865496",
-            "7143": "EN"
-        },
-        "1082": 5,
-        "1229": "24"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["PALMER, DI HARD TO HANDLE"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 8,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 8,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "85"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "01",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 13.95
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4641/6"
-            }
-        }]],
-        "C212": {
-            "7140": "9780373772612",
-            "7143": "EN"
-        },
-        "1082": 6,
-        "1229": "5"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["JONES, LLO MR PIP"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 3,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 3,
-                "6063": "83"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "03",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 20
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4641/7"
-            }
-        }]],
-        "C212": {
-            "7140": "9780385341066",
-            "7143": "EN"
-        },
-        "1082": 7,
-        "1229": "24"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["JILES, PAU STORMY WEATHER"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 8,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 8,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "85"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "01",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 24.95
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4641/8"
-            }
-        }]],
-        "C212": {
-            "7140": "9780060537326",
-            "7143": "EN"
-        },
-        "1082": 8,
-        "1229": "5"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["DELILLO, D FALLING MAN A NOVEL"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 4,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 4,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "85"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "01",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 26
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4641/9"
-            }
-        }]],
-        "C212": {
-            "7140": "9781416546023",
-            "7143": "EN"
-        },
-        "1082": 9,
-        "1229": "5"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["MORRISON,  SWEETER THAN HONEY"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 3,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 3,
-                "6063": "83"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "03",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 24
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4641/10"
-            }
-        }]],
-        "C212": {
-            "7140": "9780758215116",
-            "7143": "EN"
-        },
-        "1082": 10,
-        "1229": "24"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["SMITH, SHE FOX"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 2,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 2,
-                "6063": "83"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "03",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 25.95
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4641/11"
-            }
-        }]],
-        "C212": {
-            "7140": "9780756404215",
-            "7143": "EN"
-        },
-        "1082": 11,
-        "1229": "24"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["GROSSMAN,  SOON I WILL BE INVINCIBL"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 2,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 2,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "85"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "01",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 22.95
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4641/12"
-            }
-        }]],
-        "C212": {
-            "7140": "9780375424861",
-            "7143": "EN"
-        },
-        "1082": 12,
-        "1229": "5"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["LEWYCKA, M SHORT HISTORY OF TRACTOR"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 3,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 3,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "85"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "01",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 14
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4641/13"
-            }
-        }]],
-        "C212": {
-            "7140": "9780143036746",
-            "7143": "EN"
-        },
-        "1082": 13,
-        "1229": "5"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["BANNISTER, FLAWED"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 4,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 4,
-                "6063": "83"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "03",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 24.95
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4641/14"
-            }
-        }]],
-        "C212": {
-            "7140": "9780312375669",
-            "7143": "EN"
-        },
-        "1082": 14,
-        "1229": "24"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["ALEXANDER, REMEMBERED"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 8,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 8,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "85"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "01",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 13.99
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4641/15"
-            }
-        }]],
-        "C212": {
-            "7140": "9780764201103",
-            "7143": "EN"
-        },
-        "1082": 15,
-        "1229": "5"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["TANIGUCHI, OCEAN IN THE CLOSET"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 2,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 2,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "85"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "01",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 14.95
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4641/16"
-            }
-        }]],
-        "C212": {
-            "7140": "9781566891943",
-            "7143": "EN"
-        },
-        "1082": 16,
-        "1229": "5"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["HENKE, ROX SECRET OF US"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 5,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 5,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "85"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "01",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 13.99
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4641/17"
-            }
-        }]],
-        "C212": {
-            "7140": "9780736917018",
-            "7143": "EN"
-        },
-        "1082": 17,
-        "1229": "5"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["HERMAN, KA EVER PRESENT DANGER"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 5,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 5,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "85"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "01",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 12.99
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4641/18"
-            }
-        }]],
-        "C212": {
-            "7140": "9781590529218",
-            "7143": "EN"
-        },
-        "1082": 18,
-        "1229": "5"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["CHAPMAN, G IT HAPPENS EVERY SPRING"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 5,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 5,
-                "6063": "83"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "07",
-                "3055": "28",
-                "1131": "7B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 12.99
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4641/19"
-            }
-        }]],
-        "C212": {
-            "7140": "9781414311654",
-            "7143": "EN"
-        },
-        "1082": 19,
-        "1229": "24"
-    }], ["LIN", {
-        "SG26": [["IMD", {
-            "C273": {
-                "7008": ["JACKSON, N YADA YADA PRAYER GROUP G"]
-            },
-            "7077": "F",
-            "7081": "BST"
-        }], ["QTY", {
-            "C186": {
-                "6060": 8,
-                "6063": "21"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 8,
-                "6063": "12"
-            }
-        }], ["QTY", {
-            "C186": {
-                "6060": 0,
-                "6063": "85"
-            }
-        }], ["FTX", {
-            "C107": {
-                "4441": "01",
-                "3055": "28",
-                "1131": "8B"
-            },
-            "4451": "LIN"
-        }], ["PRI", {
-            "C509": {
-                "5387": "SRP",
-                "5125": "AAB",
-                "5118": 13.99
-            }
-        }], ["RFF", {
-            "C506": {
-                "1153": "LI",
-                "1154": "4641/20"
-            }
-        }]],
-        "C212": {
-            "7140": "9781591453628",
-            "7143": "EN"
-        },
-        "1082": 20,
-        "1229": "5"
-    }], ["UNS", {
-        "0081": "S"
-    }], ["CNT", {
-        "C270": {
-            "6069": "2",
-            "6066": 20
-        }
-    }], ["UNT", {
-        "0074": 171,
-        "0062": "725"
-    }]]
-}],
-"recipient": "8888888",
-"sender": "1556150",
-"header": ["UNB", {
-    "S003": {
-        "0007": "31B",
-        "0010": "8888888"
-    },
-    "0020": "2045",
-    "S004": {
-        "0019": 1556,
-        "0017": 70618
-    },
-    "S001": {
-        "0001": "UNOC",
-        "0002": 3
-    },
-    "S002": {
-        "0007": "31B",
-        "0004": "1556150"
-    }
-}],
-"sender_qual": "31B",
-"UNA": {
-    "seg_term": "'",
-    "decimal_sign": ".",
-    "esc_char": "?",
-    "de_sep": "+",
-    "ce_sep": ":",
-    "rep_sep": " "
-},
-"recipient_qual": "31B"
-}

Copied: branches/serials-integration/Open-ILS/tests/datasets/edi_scratch (from rev 17886, trunk/Open-ILS/tests/datasets/edi_scratch)


Property changes on: branches/serials-integration/Open-ILS/tests/datasets/edi_scratch
___________________________________________________________________
Name: svn:mergeinfo
   + /trunk/edi_scratch:10932,10935

Copied: branches/serials-integration/Open-ILS/updates (from rev 17886, trunk/Open-ILS/updates)

Modified: branches/serials-integration/Open-ILS/web/Makefile.am
===================================================================
--- branches/serials-integration/Open-ILS/web/Makefile.am	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/Makefile.am	2010-10-18 13:46:56 UTC (rev 18371)
@@ -11,7 +11,7 @@
 reportsdir = $(DESTDIR)$(WEBDIR)/reports/
 
 if BUILDILSWEB
-OILSWEB_INST = webcore-install offline-install cgi-bootstrap
+OILSWEB_INST = webcore-install offline-install
 
 #webcore-install
 
@@ -32,7 +32,7 @@
 	     $(OPENSRF_LIBS)/javascript/opensrf_xmpp.js
 endif
 
-install-exec-local: webcore-install offline-install cgi-bootstrap
+install-exec-local: webcore-install offline-install
 
 uninstall-hook:
 	rm -R $(opacextrasdir)
@@ -68,15 +68,6 @@
 	cp $(TMP)/offline.pl $(DESTDIR)$(CGIDIR)/offline/
 	chmod +x $(DESTDIR)$(CGIDIR)/offline/offline.pl
 
-cgi-bootstrap:
-	@echo "Installing cgi's to $(DESTDIR)$(CGIDIR)"
-	$(MKDIR_P) $(TMP)/cgi-bin
-	$(MKDIR_P) $(DESTDIR)$(CGIDIR)
-	for i in @top_srcdir@/Open-ILS/src/cgi-bin/*cgi; do xxx=`basename $$i`; perl -pe "s{##CONFIG##}{@sysconfdir@}" < $$i > $(TMP)/cgi-bin/$$xxx; done
-	cp $(TMP)/cgi-bin/*cgi $(DESTDIR)$(CGIDIR)
-	cp -r @top_srcdir@/Open-ILS/src/cgi-bin/support $(DESTDIR)$(CGIDIR)
-	chmod 755 $(DESTDIR)$(CGIDIR)/*cgi
-
 install-data-local:
 	$(MKDIR_P) $(DESTDIR)$(WEBDIR)/opac/common/js
 	for i in $(OPACJS); do \

Copied: branches/serials-integration/Open-ILS/web/css/skin/default/register.css (from rev 17886, trunk/Open-ILS/web/css/skin/default/register.css)
===================================================================
--- branches/serials-integration/Open-ILS/web/css/skin/default/register.css	                        (rev 0)
+++ branches/serials-integration/Open-ILS/web/css/skin/default/register.css	2010-10-18 13:46:56 UTC (rev 18371)
@@ -0,0 +1,83 @@
+ at import url("register_custom.css");
+
+/* XXX Move me into the CSS tree XXX */
+
+#uedit-tbody tr td {
+    padding: 5px;
+    text-align: left;
+}
+
+
+#uedit-save-div {
+    position: fixed;
+    top:40px;
+    right:30px;
+    width:300px;
+    border:2px solid #d9e8f9;
+    -moz-border-radius: 10px;
+    font-weight: bold;
+    padding: 12px;
+    text-align:center;
+    vertical-align:middle;
+}
+
+#uedit-help-div {
+    position: fixed;
+    top:124px;
+    right:30px;
+    width:300px;
+    border:2px dashed #d9e8f9;
+    -moz-border-radius: 10px;
+    font-weight: bold;
+    padding: 20px;
+}
+
+#uedit-dupe-div {
+    position: fixed;
+    top:124px;
+    right:30px;
+    width:300px;
+    border:2px dashed #d9e8f9;
+    -moz-border-radius: 10px;
+    font-weight: bold;
+    padding: 20px;
+}
+
+.uedit-help {
+    width: 25px;
+    border:1px solid #e0e0e0;
+    text-align:center;
+    vertical-align:middle;
+}
+.divider td {
+    min-height:10px;
+    background-color: #e0e0e0;
+}
+
+.divider span { padding: 0px 5px 0px 5px; }
+
+.newaddr-row td {
+    text-align: right;
+    border-top:1px dashed #d9e8f9;
+}
+.newaddr-row td:last-child {
+    border-right:1px dashed #d9e8f9;
+}
+
+.pending-addr-row td { border:1px solid #aaa; }
+
+.uedit-addr-del-button {margin-left: 10px; color:red;}
+
+.dijitTextBoxFocused, .dijitFocused { border:1px dashed #3e3e3e; color: #303030; font-weight:bold;}
+
+.hide-non-required tr:not([required]) {
+    visibility:hidden;
+    display:none;
+}
+
+#require-toggle {
+    margin-top:10px;
+    margin-bottom:-5px;
+}
+
+

Copied: branches/serials-integration/Open-ILS/web/css/skin/default/serial.css (from rev 17886, trunk/Open-ILS/web/css/skin/default/serial.css)
===================================================================
--- branches/serials-integration/Open-ILS/web/css/skin/default/serial.css	                        (rev 0)
+++ branches/serials-integration/Open-ILS/web/css/skin/default/serial.css	2010-10-18 13:46:56 UTC (rev 18371)
@@ -0,0 +1,27 @@
+.oils-serial-header { margin-bottom: 20px; }
+.oils-serial-tab-container { height: 600px; }
+.lesser { margin-top: 2px !important }
+.lesser div:first-child { font-size: 110% !important; }
+.lesser div:last-child { margin-right: 16px; }
+#scap_editor th {
+    font-weight: bold;
+    background-color: #ccc;
+    padding: 2px 8px;
+}
+#scap_editor td { padding: 2px 8px; }
+#scap_editor tr[changed="true"] td { background-color: #fc9; }
+#scap_editor [name="remover"] button { color: red; font-weight: bold; }
+#scap_editor tfoot td { text-align: center; padding-top: 24px; }
+#scap_editor td[name] { text-align: center; }
+.serial-dialog-table tr > * { padding-bottom: 1em; }
+.serial-dialog-table th { text-align: left; padding-right: 1em; }
+.serial-dialog-table tr:last-child td { text-align: center; }
+.serial-additional-controls {
+    text-align: right;
+    margin-right: 16px;
+    padding: 8px 0;
+}
+.serial-holding-code { border: 0 !important; margin: 0;}
+.serial-holding-code tr { border: 0 !important; margin: 0 !important; }
+.serial-holding-code td { border: 0 !important; padding: 3px; margin: 0 !important; }
+.serial-holding-code td[colspan="2"] { text-align:center; }

Modified: branches/serials-integration/Open-ILS/web/css/skin/default.css
===================================================================
--- branches/serials-integration/Open-ILS/web/css/skin/default.css	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/css/skin/default.css	2010-10-18 13:46:56 UTC (rev 18371)
@@ -1,6 +1,7 @@
 /* import the default css for the install applications */
 @import "default/acq.css";
 @import "default/admin.css";
+ at import "default/serial.css";
 /* import the dojo CSS */
 @import "/js/dojo/dojo/resources/dojo.css";
 @import "/js/dojo/dijit/themes/tundra/tundra.css";

Copied: branches/serials-integration/Open-ILS/web/images/dimple.png (from rev 17886, trunk/Open-ILS/web/images/dimple.png)
===================================================================
--- branches/serials-integration/Open-ILS/web/images/dimple.png	                        (rev 0)
+++ branches/serials-integration/Open-ILS/web/images/dimple.png	2010-10-18 13:46:56 UTC (rev 18371)
@@ -0,0 +1,5 @@
+‰PNG
+
+   
+IHDR         b­MÛ   tEXtSoftware Adobe ImageReadyqÉe<   =IDAT×c```° â:(¶`N2Ü@Ìvqqñ rÔ@ÌÞ¶m[PCCƒ%ƒØÿÿÿ×â(Ö …5
+Bmª    IEND®B`‚
\ No newline at end of file

Copied: branches/serials-integration/Open-ILS/web/images/licenses.txt (from rev 17886, trunk/Open-ILS/web/images/licenses.txt)
===================================================================
--- branches/serials-integration/Open-ILS/web/images/licenses.txt	                        (rev 0)
+++ branches/serials-integration/Open-ILS/web/images/licenses.txt	2010-10-18 13:46:56 UTC (rev 18371)
@@ -0,0 +1,3 @@
+dimple.png derived from:
+http://mxr.mozilla.org/mozilla-central/source/toolkit/themes/pinstripe/global/splitter/dimple.png
+Mozilla Public License/GPL/GLPL

Modified: branches/serials-integration/Open-ILS/web/js/dojo/MARC/Field.js
===================================================================
--- branches/serials-integration/Open-ILS/web/js/dojo/MARC/Field.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/js/dojo/MARC/Field.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -47,7 +47,7 @@
         },
 
         addSubfields : function () {
-            for (var i in arguments) {
+            for (var i = 0; i < arguments.length; i++) {
                 var code = arguments[i];
                 var value = arguments[++i];
                 this.subfields.push( [ code, value ] );

Modified: branches/serials-integration/Open-ILS/web/js/dojo/MARC/Record.js
===================================================================
--- branches/serials-integration/Open-ILS/web/js/dojo/MARC/Record.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/js/dojo/MARC/Record.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -68,11 +68,11 @@
 
         insertOrderedFields : function () {
             var me = this;
-            for ( var i in arguments ) { // arguments is special, and for..in is correct
+            for (var i = 0; i < arguments.length; i++) {
                 var f = arguments[i];
                 var done = false;
                 for (var j = 0; j < this.fields.length; j++) {
-                    if (f.tag > this.fields[j].tag) {
+                    if (f.tag < this.fields[j].tag) {
                         this.insertFieldsBefore(this.fields[j], f);
                         done = true;
                         break;
@@ -83,12 +83,13 @@
         },
 
         insertFieldsBefore : function (target) {
-            arguments.splice(0,1);
+            var args = Array.prototype.slice.call(arguments);
+            args.splice(0,1);
             var me = this;
             for (var j = 0; j < this.fields.length; j++) {
                 if (target === this.fields[j]) {
                     j--;
-                    dojo.forEach( arguments, function (f) {
+                    dojo.forEach( args, function (f) {
                         me.fields.splice(j++,0,f);
                     });
                     break;
@@ -97,11 +98,12 @@
         },
 
         insertFieldsAfter : function (target) {
-            arguments.splice(0,1);
+            var args = Array.prototype.slice.call(arguments);
+            args.splice(0,1);
             var me = this;
             for (var j = 0; j < this.fields.length; j++) {
                 if (target === this.fields[j]) {
-                    dojo.forEach( arguments, function (f) {
+                    dojo.forEach( args, function (f) {
                         me.fields.splice(j++,0,f);
                     });
                     break;

Modified: branches/serials-integration/Open-ILS/web/js/dojo/fieldmapper/Fieldmapper.js
===================================================================
--- branches/serials-integration/Open-ILS/web/js/dojo/fieldmapper/Fieldmapper.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/js/dojo/fieldmapper/Fieldmapper.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -53,7 +53,7 @@
 					obj.a[i] = thing.clone();
 				} else {
 
-					if(instanceOf(thing, Array)) {
+					if(dojo.isArray(thing)) {
 						obj.a[i] = new Array();
 
 						for( var j in thing ) {

Modified: branches/serials-integration/Open-ILS/web/js/dojo/fieldmapper/IDL.js
===================================================================
--- branches/serials-integration/Open-ILS/web/js/dojo/fieldmapper/IDL.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/js/dojo/fieldmapper/IDL.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -197,7 +197,7 @@
     fieldmapper.IDL.loaded = false;
 
     JSON2js.fallbackObjectifier = function (arg, key_name, val_name) {
-        console.log("Firing IDL loader for " + key_name);
+        console.log("Firing IDL loader for " + arg[key_name]);
         fieldmapper.IDL.load([arg[key_name]]);
         return decodeJS(arg);
     }

Modified: branches/serials-integration/Open-ILS/web/js/dojo/fieldmapper/dojoData.js
===================================================================
--- branches/serials-integration/Open-ILS/web/js/dojo/fieldmapper/dojoData.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/js/dojo/fieldmapper/dojoData.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -92,15 +92,18 @@
 		return data;
 	}
 
-	for (var i in fmclasses) fieldmapper[i].prototype.fromStoreItem = _fromStoreItem;
-	for (var i in fmclasses) fieldmapper[i].toStoreData = _toStoreData;
-	for (var i in fmclasses) fieldmapper[i].toStoreItem = _toStoreItem;
-	for (var i in fmclasses) fieldmapper[i].prototype.toStoreItem = function ( args ) { return _toStoreItem(this, args) };
-	for (var i in fmclasses) fieldmapper[i].initStoreData = _initStoreData;
+	for (var i in fmclasses) {
+		fieldmapper[i].prototype.fromStoreItem = _fromStoreItem;
+		fieldmapper[i].prototype.fromStoreItem = _fromStoreItem;
+		fieldmapper[i].toStoreData = _toStoreData;
+		fieldmapper[i].toStoreItem = _toStoreItem;
+		fieldmapper[i].prototype.toStoreItem = function ( args ) { return _toStoreItem(this, args) };
+		fieldmapper[i].initStoreData = _initStoreData;
+	}
 
-	fieldmapper.aou.prototype._ignore_fields = ['children'];
-	fieldmapper.aout.prototype._ignore_fields = ['children'];
-	fieldmapper.pgt.prototype._ignore_fields = ['children'];
+	if (fieldmapper.aou) fieldmapper.aou.prototype._ignore_fields = ['children'];
+	if (fieldmapper.aout) fieldmapper.aout.prototype._ignore_fields = ['children'];
+	if (fieldmapper.pgt) fieldmapper.pgt.prototype._ignore_fields = ['children'];
 
 	fieldmapper.aou.toStoreData = function (list, label) {
 		if (!label) label = 'shortname';

Modified: branches/serials-integration/Open-ILS/web/js/dojo/openils/BibTemplate.js
===================================================================
--- branches/serials-integration/Open-ILS/web/js/dojo/openils/BibTemplate.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/js/dojo/openils/BibTemplate.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -28,11 +28,13 @@
             this.subObjectLimit = kwargs.subObjectLimit;
             this.subObjectOffset = kwargs.subObjectOffset;
             this.tagURI = kwargs.tagURI;
+            this.xml = kwargs.xml;
             this.record = kwargs.record;
             this.org_unit = kwargs.org_unit || '-';
             this.depth = kwargs.depth;
             this.sync = kwargs.sync == true;
             this.locale = kwargs.locale || OpenSRF.locale || 'en-US';
+            this.nodelay = kwargs.delay == false;
 
             this.mode = 'biblio-record_entry';
             this.default_datatype = 'marcxml-uris';
@@ -41,6 +43,8 @@
                 this.mode = 'metabib-metarecord';
                 this.default_datatype = 'mods';
             }
+
+            if (this.nodelay) this.render();
         },
 
         subsetNL : function (old_nl, start, end) {
@@ -76,7 +80,7 @@
                 } else if (s.getAttribute('type').indexOf('+') > -1)  {
                     current_datatype = s.getAttribute('type').split('+').reverse()[0];
                 }
-        
+
                 if (!slots[current_datatype]) slots[current_datatype] = [];
                 slots[current_datatype].push(s);
 
@@ -86,95 +90,126 @@
 
                 (function (args) {
                     var BT = args.renderer;
+                    var process_record = function (bib) {
+                        dojo.forEach(args.slot_list, function (slot) {
+                            var debug = slot.getAttribute('debug') == 'true';
 
-                    var uri = '';
-                    if (BT.tagURI) {
-                        uri = BT.tagURI;
-                    } else {
-                        uri = 'tag:evergreen-opac:' + BT.mode + '/' + BT.record;
-                        if (BT.subObjectLimit) {
-                            uri += '[' + BT.subObjectLimit;
-                            if (BT.subObjectOffset)
-                                uri += ',' + BT.subObjectOffset;
-                            uri += ']';
-                        }
-                        uri += '/' + BT.org_unit;
-                        if (BT.depth || BT.depth == '0') uri += '/' + BT.depth;
-                    }
+                            try {
+                                var joiner = slot.getAttribute('join') || ' ';
+                                var item_limit = parseInt(slot.getAttribute('limit'));
+                                var item_offset = parseInt(slot.getAttribute('offset')) || 0;
 
-                    dojo.xhrGet({
-                        url: '/opac/extras/unapi?id=' + uri + '&format=' + args.dtype + '&locale=' + BT.locale,
-                        handleAs: 'xml',
-                        sync: BT.sync,
-                        preventCache: true,
-                        load: function (bib) {
+                                var pre_render_callbacks = dojo.query( '*[type=opac/call-back+pre-render]', slot );
+                                var post_render_callbacks = dojo.query( '*[type=opac/call-back+post-render]', slot );
+                                var pre_query_callbacks = dojo.query( '*[type=opac/call-back+pre-query]', slot );
+                                var post_query_callbacks = dojo.query( '*[type=opac/call-back+post-query]', slot );
 
-                            dojo.forEach(args.slot_list, function (slot) {
-                                var debug = slot.getAttribute('debug') == 'true';
+                                // Do pre-query stuff
+                                dojo.forEach(pre_query_callbacks, function (cb) {
+                                    try { (new Function( 'BT', 'slotXML', 'slot', unescape(cb.innerHTML) ))(BT,bib,slot) } catch (e) {/*meh*/}
+                                });
 
-                                try {
-                                    var joiner = slot.getAttribute('join') || ' ';
-                                    var item_limit = parseInt(slot.getAttribute('limit'));
-                                    var item_offset = parseInt(slot.getAttribute('offset')) || 0;
+                                var item_list = dojo.query(
+                                    slot.getAttribute('query'),
+                                    bib
+                                );
 
-                                    var item_list = dojo.query(
-                                        slot.getAttribute('query'),
-                                        bib
-                                    );
+                                if (item_limit) {
+                                    if (debug) alert('BibTemplate debug -- item list limit/offset requested: ' + item_limit + '/' + item_offset);
+                                    if (item_list.length) item_list = BT.subsetNL(item_list, item_offset, item_offset + item_limit);
+                                }
 
-                                    if (item_limit) {
-                                        if (debug) alert('BibTemplate debug -- item list limit/offset requested: ' + item_limit + '/' + item_offset);
-                                        if (item_list.length) item_list = BT.subsetNL(item_list, item_offset, item_offset + item_limit);
-                                        if (!item_list.length) return;
-                                    }
+                                // Do post-query stuff, only if there's an item list!
+                                dojo.forEach(post_query_callbacks, function (cb) {
+                                    try { (new Function( 'item_list', 'BT', 'slotXML', 'slot', unescape(cb.innerHTML) ))(item_list,BT,bib,slot) } catch (e) {/*meh*/}
+                                });
 
-                                    var templated = slot.getAttribute('templated') == 'true';
-                                    if (debug) alert('BibTemplate debug -- slot ' + (templated ? 'is' : 'is not') + ' templated');
-                                    if (templated) {
-                                        if (debug) alert('BibTemplate debug -- slot template innerHTML:\n' + slot.innerHTML);
-                                        var template_values = {};
-                                        var template_value_count = 0;
+                                if (!item_list.length) return;
 
-                                        dojo.query(
-                                            '*[type=opac/template-value]',
-                                            slot
-                                        ).orphan().forEach(function(x) {
-                                            var name = x.getAttribute('name');
-                                            var value = (new Function( 'item_list', 'BT', 'slotXML', 'slot', unescape(x.innerHTML) ))(item_list,BT,bib,slot);
-                                            if (name && (value || value == '')) {
-                                                template_values[name] = value;
-                                                template_value_count++;
-                                            }
-                                        });
+                                // Do pre-render stuff
+                                dojo.forEach(pre_render_callbacks, function (cb) {
+                                    try { (new Function( 'item_list', 'BT', 'slotXML', 'slot', unescape(cb.innerHTML) ))(item_list,BT,bib,slot) } catch (e) {/*meh*/}
+                                });
 
-                                        if (debug) alert('BibTemplate debug -- template values:\n' + dojo.toJson( template_values ));
-                                        if (template_value_count > 0) slot.innerHTML = dojo.string.substitute( unescape(slot.innerHTML), template_values );
-                                    }
+                                var templated = slot.getAttribute('templated') == 'true';
+                                if (debug) alert('BibTemplate debug -- slot ' + (templated ? 'is' : 'is not') + ' templated');
+                                if (templated) {
+                                    if (debug) alert('BibTemplate debug -- slot template innerHTML:\n' + slot.innerHTML);
+                                    var template_values = {};
+                                    var template_value_count = 0;
 
-                                    var handler_node = dojo.query( '*[type=opac/slot-format]', slot )[0];
-                                    if (handler_node) slot_handler = new Function('item_list', 'BT', 'slotXML', 'slot', 'item', dojox.xml.parser.textContent(handler_node) || handler_node.innerHTML);
-                                    else slot_handler = new Function('item_list', 'BT', 'slotXML', 'slot', 'item','return dojox.xml.parser.textContent(item) || item.innerHTML;');
-
-                                    if (item_list.length) {
-                                        var content = dojo.map(item_list, dojo.partial(slot_handler,item_list,BT,bib,slot)).join(joiner);
-                                        if (templated) {
-                                            if (handler_node) handler_node.parentNode.replaceChild( dojo.doc.createTextNode( content ), handler_node );
-                                        } else {
-                                            slot.innerHTML = content;
+                                    dojo.query(
+                                        '*[type=opac/template-value]',
+                                        slot
+                                    ).orphan().forEach(function(x) {
+                                        var name = x.getAttribute('name');
+                                        var value = (new Function( 'item_list', 'BT', 'slotXML', 'slot', unescape(x.innerHTML) ))(item_list,BT,bib,slot);
+                                        if (name && (value || value == '')) {
+                                            template_values[name] = value;
+                                            template_value_count++;
                                         }
-                                    }
+                                    });
 
-                                    delete(slot_handler);
-                                } catch (e) {
-                                    if (debug) {
-                                        alert('BibTemplate Error: ' + e + '\n' + dojo.toJson(e));
-                                        throw(e);
+                                    if (debug) alert('BibTemplate debug -- template values:\n' + dojo.toJson( template_values ));
+                                    if (template_value_count > 0) slot.innerHTML = dojo.string.substitute( unescape(slot.innerHTML), template_values );
+                                }
+
+                                var handler_node = dojo.query( '*[type=opac/slot-format]', slot )[0];
+                                if (handler_node) slot_handler = new Function('item_list', 'BT', 'slotXML', 'slot', 'item', dojox.xml.parser.textContent(handler_node) || handler_node.innerHTML);
+                                else slot_handler = new Function('item_list', 'BT', 'slotXML', 'slot', 'item','return dojox.xml.parser.textContent(item) || item.innerHTML;');
+
+                                if (item_list.length) {
+                                    var content = dojo.map(item_list, dojo.partial(slot_handler,item_list,BT,bib,slot)).join(joiner);
+                                    if (templated) {
+                                        if (handler_node) handler_node.parentNode.replaceChild( dojo.doc.createTextNode( content ), handler_node );
+                                    } else {
+                                        slot.innerHTML = content;
                                     }
                                 }
-                            });
-                       }
-                    });
 
+                                delete(slot_handler);
+
+                                // Do post-render stuff
+                                dojo.forEach(post_render_callbacks, function (cb) {
+                                    try { (new Function( 'item_list', 'BT', 'slotXML', 'slot', unescape(cb.innerHTML) ))(item_list,BT,bib,slot) } catch (e) {/*meh*/}
+                                });
+
+                            } catch (e) {
+                                if (debug) {
+                                    alert('BibTemplate Error: ' + e + '\n' + dojo.toJson(e));
+                                    throw(e);
+                                }
+                            }
+                        });
+                    };
+
+                    if (BT.xml) {
+                        process_record(BT.xml);
+                    } else {
+                        var uri = '';
+                        if (BT.tagURI) {
+                            uri = BT.tagURI;
+                        } else {
+                            uri = 'tag:evergreen-opac:' + BT.mode + '/' + BT.record;
+                            if (BT.subObjectLimit) {
+                                uri += '[' + BT.subObjectLimit;
+                                if (BT.subObjectOffset)
+                                    uri += ',' + BT.subObjectOffset;
+                                uri += ']';
+                            }
+                            uri += '/' + BT.org_unit;
+                            if (BT.depth || BT.depth == '0') uri += '/' + BT.depth;
+                        }
+
+                        dojo.xhrGet({
+                            url: '/opac/extras/unapi?id=' + uri + '&format=' + args.dtype + '&locale=' + BT.locale,
+                            handleAs: 'xml',
+                            sync: BT.sync,
+                            preventCache: true,
+                            load: process_record
+                        });
+                    }
+
                 })({ slot_list : slots[datatype].reverse(), dtype : datatype, renderer : this });
             
             }
@@ -184,4 +219,49 @@
         }
     });
 
+    dojo._hasResource["openils.FeedTemplate"] = true;
+    dojo.provide("openils.FeedTemplate");
+    dojo.declare('openils.FeedTemplate', null, {
+
+        constructor : function(kwargs) {
+            this.place = kwargs.place;
+            this.root = kwargs.root;
+            this.xml = kwargs.xml;
+            this.feed_uri = kwargs.uri;
+            this.item_query = kwargs.query;
+            this.sync = kwargs.sync == true;
+            this.nodelay = kwargs.delay == false;
+            this.reverseSort = kwargs.reverseSort == true;
+            this.relativePosition = 'last';
+            if (this.reverseSort) this.relativePosition = 'first';
+
+            if (this.nodelay) this.render();
+        },
+
+        render : function () {
+            var me = this;
+            var process_feed = function (xmldoc) {
+                dojo.query( me.item_query, xmldoc ).forEach(
+                    function (item) {
+                        var template = me.root.cloneNode(true);
+                        dojo.place( template, place, me.relativePosition );
+                        new openils.BibTemplate({ delay : false, xml : item, root : template });
+                    }
+                );
+            };
+
+            if (this.xml) {
+                process_feed(this.xml);
+            } else {
+                dojo.xhrGet({
+                    url: this.feed_uri,
+                    handleAs: 'xml',
+                    sync: this.sync,
+                    preventCache: true,
+                    load: process_feed
+                });
+            }
+
+        }
+    });
 }

Modified: branches/serials-integration/Open-ILS/web/js/dojo/openils/I18N.js
===================================================================
--- branches/serials-integration/Open-ILS/web/js/dojo/openils/I18N.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/js/dojo/openils/I18N.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -25,7 +25,7 @@
 
     dojo.declare('openils.I18N', null, {});
 
-	openils.I18N.BaseLocales = fieldmapper.standardRequest( [ 'open-ils.fielder', 'open-ils.fielder.i18n_l.atomic'], [ { query : { code : { '!=' :  null }  } } ] );
+	openils.I18N.BaseLocales = fieldmapper.standardRequest( [ 'open-ils.fielder', 'open-ils.fielder.i18n_l.atomic'], [ { cache : 1, query : { code : { '!=' :  null }  } } ] );
 	openils.I18N.localeStore = new dojo.data.ItemFileWriteStore( { data : {identifier : 'locale', label : 'label', items : [] } } );
 	openils.I18N.BaseLocales = openils.I18N.BaseLocales.sort(
         function(a, b) {

Modified: branches/serials-integration/Open-ILS/web/js/dojo/openils/PermaCrud.js
===================================================================
--- branches/serials-integration/Open-ILS/web/js/dojo/openils/PermaCrud.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/js/dojo/openils/PermaCrud.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -366,7 +366,9 @@
                 if (obj.ischanged()) method = 'update';
                 if (obj.isnew())     method = 'create';
                 if (obj.isdeleted()) method = 'delete';
-                if (!method) throw 'No action detected';
+                if (!method) {
+                    return _auto_CUD_recursive(obj_list, pos+1, final_complete, final_error);
+                }
 
                 var req_hash = {
                     method : 'open-ils.pcrud.' + method + '.' + obj.classname,
@@ -393,16 +395,15 @@
                             oncomplete : function (r) {
                                 var res = r.recv();
                                 if ( res && res.content() ) {
-                                    _auto_CUD_recursive( list, 0 );
+                                    if (r._final_complete) 
+                                        req._final_complete(req, _return_list);
+                                    _pcrud.disconnect();
                                 } else {
                                     _pcrud.disconnect();
                                     throw 'Transaction commit error';
                                 }
                             },
                         }).send();
-
-                        if (r._final_complete) r._final_complete(r);
-                        _pcrud.disconnect();
                     };
 
                     req.onerror = function (r) {

Modified: branches/serials-integration/Open-ILS/web/js/dojo/openils/User.js
===================================================================
--- branches/serials-integration/Open-ILS/web/js/dojo/openils/User.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/js/dojo/openils/User.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -24,6 +24,7 @@
     dojo.require('fieldmapper.Fieldmapper');
     dojo.require('fieldmapper.OrgUtils');
     dojo.require('openils.Util');
+    dojo.require('dojo.cookie');
     dojo.requireLocalization("openils.User", "User");
 
     dojo.declare('openils.User', null, {
@@ -51,6 +52,7 @@
             this.authcookie = kwargs.authcookie || openils.User.authcookie;
             this.permOrgStoreCache = {}; /* permName => permOrgUnitStore map */
 
+            if (this.authcookie) this.authtoken = dojo.cookie(this.authcookie);
             if (this.id && this.authtoken) this.user = this.getById( this.id );
             else if (this.authtoken) this.getBySession();
             else if (kwargs.login) this.login();
@@ -148,7 +150,6 @@
 					if (!openils.User.authtime) openils.User.authtime = _u.authtime;
                     _u.getBySession(onComplete);
                     if(_u.authcookie) {
-                        dojo.require('dojo.cookie');
                         dojo.cookie(_u.authcookie, _u.authtoken, {path:'/'});
                     }
                 }
@@ -192,7 +193,6 @@
             if (!openils.User.authtime) openils.User.authtime = _u.authtime;
 
             if(_u.authcookie) {
-                dojo.require('dojo.cookie');
                 dojo.cookie(_u.authcookie, _u.authtoken, {path:'/'});
             }
 

Modified: branches/serials-integration/Open-ILS/web/js/dojo/openils/Util.js
===================================================================
--- branches/serials-integration/Open-ILS/web/js/dojo/openils/Util.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/js/dojo/openils/Util.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -28,6 +28,16 @@
     dojo.declare('openils.Util', null, {});
 
 
+    openils.Util.timeStampRegexp =
+        /^(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}[\+-]\d{2})(\d{2})$/;
+
+    openils.Util.timeStampAsDateObj = function(s) {
+        if (s.constructor.name == "Date") return s;
+        return dojo.date.stamp.fromISOString(
+            s.replace(openils.Util.timeStampRegexp, "$1:$2")
+        );
+    }
+
     /**
      * Returns a locale-appropriate representation of a timestamp when the
      * timestamp (first argument) is actually a string as provided by
@@ -39,12 +49,7 @@
         if (typeof(opts) == "undefined") opts = {};
 
         return dojo.date.locale.format(
-            dojo.date.stamp.fromISOString(
-                s.replace(
-                    /^(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}[\+-]\d{2})(\d{2})$/,
-                    "$1:$2"
-                )
-            ), opts
+            openils.Util.timeStampAsDateObj(s), opts
         );
     };
 
@@ -319,6 +324,16 @@
         return openils.Util.objectProperties(o);
     }
 
+    openils.Util.uniqueObjects = function(list, field) {
+        var sorted = openils.Util.objectSort(list, field);
+        var results = [];
+        for (var i = 0; i < sorted.length; i++) {
+            if (!i || (sorted[i][field]() != sorted[i-1][field]()))
+                results.push(sorted[i]);
+        }
+        return results;
+    };
+
     /**
      * Highlight instances of each pattern in the given DOM node
      * Inspired by the jquery plugin
@@ -361,5 +376,36 @@
         dojo.forEach(patterns, function(pat) { _hilightNode(node, pat); });
     };
 
+
+    /**
+     * Takes a chunk of HTML, inserts it into a new window, prints the window, 
+     * then closes the windw.  To provide ample printer queueing time, automatically
+     * wait a short time before closing the window after calling .print().  The amount
+     * of time to wait is based on the size of the data to be printed.
+     * @param html The HTML string
+     * @param callback Optional post-printing callback
+     */
+    openils.Util.printHtmlString = function(html, callback) {
+
+        var win = window.open('', 'Print Window', 'resizable,width=800,height=600,scrollbars=1'); 
+
+        // force the new window to the background
+        win.blur(); 
+        window.focus(); 
+
+        win.document.body.innerHTML = html;
+        win.print();
+
+        setTimeout(
+            function() { 
+                win.close();
+                if(callback)
+                    callback();
+            },
+            // 1k == 1 second pause, max 10 seconds
+            Math.min(html.length, 10000)
+        );
+    };
+
 }
 

Modified: branches/serials-integration/Open-ILS/web/js/dojo/openils/XUL.js
===================================================================
--- branches/serials-integration/Open-ILS/web/js/dojo/openils/XUL.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/js/dojo/openils/XUL.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -33,6 +33,27 @@
         xulG.new_tab(path, tabInfo, options);
     }
 
+    openils.XUL.newTabEasy = function(url, tab_name, extra_content_params) {
+        var content_params = {
+            "session": openils.User.authtoken,
+            "authtime": openils.User.authtime
+        };
+
+        ["url_prefix", "new_tab", "set_tab", "close_tab", "new_patron_tab",
+            "set_patron_tab", "volume_item_creator", "get_new_session",
+            "holdings_maintenance_tab", "set_tab_name", "open_chrome_window",
+            "url_prefix", "network_meter", "page_meter", "set_statusbar",
+            "set_help_context"
+        ].forEach(function(k) { content_params[k] = xulG[k]; });
+
+        if (extra_content_params)
+            dojo.mixin(content_params, extra_content_params);
+
+        xulG.new_tab(
+            xulG.url_prefix(url), {"tab_name": tab_name}, content_params
+        );
+    };
+
     /**
      * @return bool True if a new session was successfully created, false otherwise.
      */

Modified: branches/serials-integration/Open-ILS/web/js/dojo/openils/acq/Lineitem.js
===================================================================
--- branches/serials-integration/Open-ILS/web/js/dojo/openils/acq/Lineitem.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/js/dojo/openils/acq/Lineitem.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -144,6 +144,9 @@
                 var orderDate = '';
                 var liLink = '';
 
+                if(pl.name() == '') // special pl
+                    pl = null;
+
                 if(po) {
                     liLink = oilsBasePath + '/acq/po/view/' + po.id() + '/' + lineitem.id();
                     if(po.order_date()) {
@@ -175,7 +178,9 @@
                         lineitem.order_summary().encumbrance_amount() || '0.00',
                         lineitem.order_summary().paid_amount() || '0.00',
                         orderDate,
-                        liLink
+                        liLink,
+                        (po) ? 'foo' : '', // forces class='hiddenfoo' i.e. not hidden
+                        (pl) ? 'foo' : '', // ditto
                     ]
                 );
 

Modified: branches/serials-integration/Open-ILS/web/js/dojo/openils/acq/nls/acq.js
===================================================================
--- branches/serials-integration/Open-ILS/web/js/dojo/openils/acq/nls/acq.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/js/dojo/openils/acq/nls/acq.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -49,6 +49,7 @@
     "FUND_LIST_ROLLOVER_SUMMARY_ROLLOVER_AMOUNT" : "<b>$${1}</b> unspent money rolled over to fiscal year ${0} for the selected locations",
     "FUND_XFER_SAME_SOURCE_AND_DEST" : "Cannot transfer. The source and destination funds are the same.",
     "FUND_XFER_CONFIRM" : "Are you sure you're ready to commit this transfer?",
+    "PO_ACTIVATED_ON" : "Activated ${0}",
     "PO_CHECKING" : "[One moment...]",
     "PO_COULD_ACTIVATE" : "Yes.",
     "PO_WARNING_NO_BLOCK_ACTIVATION" : "Yes; fund ${0} (${1}) would be encumbered beyond its warning level.",
@@ -59,7 +60,7 @@
     "INVOICE_ITEM_DETAILS" : "${0} <br/> ${1} <br/> ${2}. <br/> Estimated Price: $${3}. <br/> Lineitem ID: ${4} <br/> PO: ${5} <br/> Order Date: ${6}",
     "INVOICE_CONFIRM_ITEM_DELETE" : "Remove this $${0} '${1}' charge from the invoice?",
     "INVOICE_CONFIRM_ENTRY_DETACH" : "Remove $${0} charge for item '${1}, ${2} [${3}] from the invoice?",
-    "LINEITEM_SUMMARY" : "<div class='acq-lineitem-summary'><a href='${19}'>${0}</a>, by ${1} (${2})</div>\n<div class='acq-lineitem-summary-extra'>\n${3} Ordered, ${4} Received, ${7} Invoiced, ${8} Claimed, ${9} Cancelled</div>\n<div class='acq-lineitem-summary-extra'>Estimated $${6}, Encumbered $${16}, Paid $${17}</div>\n<div class='acq-lineitem-summary-extra'>\n<a style='padding-right: 10px;' href='${11}/acq/po/view/${12}'>PO #${13} ${18}</a>\n<a style='padding-right: 10px;' href='${11}/acq/picklist/view/${14}'>${15}</a></div>",
+    "LINEITEM_SUMMARY" : "<div class='acq-lineitem-summary'><a href='${19}'>${0}</a>, by ${1} (${2})</div>\n<div class='acq-lineitem-summary-extra'>\n${3} Ordered, ${4} Received, ${7} Invoiced, ${8} Claimed, ${9} Cancelled</div>\n<div class='acq-lineitem-summary-extra'>Estimated $${6}, Encumbered $${16}, Paid $${17}</div>\n<div class='acq-lineitem-summary-extra'>\n# ${10} <a style='padding-right: 10px;' class='hidden${20}'  href='${11}/acq/po/view/${12}'>&#x2318; ${13} ${18}</a>\n<a style='padding-right: 10px;' class='hidden${21}' href='${11}/acq/picklist/view/${14}'>&#x2756; ${15}</a></div>",
     "INVOICE_CONFIRM_PRORATE" : "Prorate charges?\n\nAny subsequent changes to the invoice that would affect prorated amounts should be resolved manually.",
     "INVOICE_EXTRA_COPIES" : "You are attempting to invoice <b>${0}</b> more copies than originally ordered.  <br/><br/>To add these items to the original order, select a fund and choose 'Add New Items' below.  <br/>After saving the invoice, you may finish editing and importing the new copies from the lineitem details page.",
     "INVOICE_ITEM_PO_DETAILS" : "<b>${0}</b><br/><a href='${1}/acq/po/view/${2}'>PO #${3} ${4}</a><br/>Total Estimated Cost: $${5}",

Modified: branches/serials-integration/Open-ILS/web/js/dojo/openils/actor/nls/register.js
===================================================================
--- branches/serials-integration/Open-ILS/web/js/dojo/openils/actor/nls/register.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/js/dojo/openils/actor/nls/register.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -1,4 +1,6 @@
 {
+    "DELETE_ADDRESS" : "Delete address ${0}?",
+    "NEED_ADDRESS" : "An address is required during registration.",
     "DUPE_PATRON_NAME" : "Found ${0} patron(s) with the same name",
     "DUPE_PATRON_EMAIL" : "Found ${0} patron(s) with the same email address",
     "DUPE_PATRON_IDENT" : "Found ${0} patron(s) with the same identification",

Modified: branches/serials-integration/Open-ILS/web/js/dojo/openils/conify/nls/conify.js
===================================================================
--- branches/serials-integration/Open-ILS/web/js/dojo/openils/conify/nls/conify.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/js/dojo/openils/conify/nls/conify.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -85,6 +85,8 @@
     "SURVEY_QUESTION": "Question:",
     "SURVEY_ID": "Survey ID # ${0}",
     "SURVEY_FOOT_LABEL": "Questions & Answers",
-    "EVENT_DEF_LABEL" : "${0}: ${1}"
+    "EVENT_DEF_LABEL" : "${0}: ${1}",
+    "ACQ_DISTRIB_FORMULA_NAME_PROMPT" : "Enter new formula name",
+    "ACQ_DISTRIB_FORMULA_NAME_CLONE" : "${0} (Clone)"
 }
 

Modified: branches/serials-integration/Open-ILS/web/js/dojo/openils/opac/nls/opac.js
===================================================================
--- branches/serials-integration/Open-ILS/web/js/dojo/openils/opac/nls/opac.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/js/dojo/openils/opac/nls/opac.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -14,6 +14,7 @@
 	"CREATE_MFHD": "Add MFHD Record",
 	"CREATED_MFHD_RECORD": "Created MFHD record for ${0}",
 	"DELETE_MFHD": "Delete Record",
+	"DELETE_MFHD_CONFIRM": "Are you sure you want to delete this serial record?",
 	"DELETED_MFHD_RECORD": "Deleted MFHD record ${0}",
 	"EDIT_MFHD_RECORD": "Edit Record",
 	"EDIT_MFHD_MENU": "Edit Holdings",

Modified: branches/serials-integration/Open-ILS/web/js/dojo/openils/widget/AutoFieldWidget.js
===================================================================
--- branches/serials-integration/Open-ILS/web/js/dojo/openils/widget/AutoFieldWidget.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/js/dojo/openils/widget/AutoFieldWidget.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -44,6 +44,8 @@
          *  dataLoader : Bypass the default PermaCrud linked data fetcher and use this function instead.
          *      Function arguments are (link class name, search filter, callback)
          *      The fetched objects should be passed to the callback as an array
+         *  disableQuery : dojo.data query passed to FilteringTreeSelect-based widgets to disable
+         *      (but leave visible) certain options.  
          */
         constructor : function(args) {
             for(var k in args)
@@ -54,10 +56,17 @@
             }
             this.dijitArgs['scrollOnFocus'] = false;
 
+
             // find the field description in the IDL if not provided
             if(this.fmObject) 
                 this.fmClass = this.fmObject.classname;
             this.fmIDL = fieldmapper.IDL.fmclasses[this.fmClass];
+
+            if(this.fmClass && !this.fmIDL) {
+                fieldmapper.IDL.load([this.fmClass]);
+                this.fmIDL = fieldmapper.IDL.fmclasses[this.fmClass];
+            }
+
             this.suppressLinkedFields = args.suppressLinkedFields || [];
 
             if(this.selfReference) {
@@ -149,10 +158,9 @@
                     }
                 case 'timestamp':
                     if (!value) return '';
-                    dojo.require('dojo.date.locale');
-                    dojo.require('dojo.date.stamp');
-                    var date = dojo.date.stamp.fromISOString(value);
-                    return dojo.date.locale.format(date, {formatLength:'short'});
+                    return openils.Util.timeStamp(
+                        value, {"formatLength": "short"}
+                    );
                 case 'org_unit':
                     if(value === null || value === undefined) return '';
                     return fieldmapper.aou.findOrgUnit(value).shortname();
@@ -175,8 +183,15 @@
                 // core widget provided for us, attach and move on
                 if(this.parentNode) // may already be in the "right" place
                     this.parentNode.appendChild(this.widget.domNode);
-                if(this.widget.attr('value') == null)
+                if (this.shove) {
+                    if (this.shove.mode == "update")
+                        this.widget.attr("value", this.widgetValue);
+                    else
+                        this.widgetValue = this.shove.create;
                     this._widgetLoaded();
+                } else if (this.widget.attr("value") == null) {
+                    this._widgetLoaded();
+                }
                 return;
             }
             
@@ -228,12 +243,11 @@
                         dojo.require('dijit.form.DateTextBox');
                         dojo.require('dojo.date.stamp');
                         this.widget = new dijit.form.DateTextBox(this.dijitArgs, this.parentNode);
-                        if(this.widgetValue != null) 
-                            this.widgetValue = dojo.date.stamp.fromISOString(
-                                // Kludge until the ML returning ISO timestamps with a colon in the timezone offset,
-                                // which dojo.date.stamp.fromISOString requires
-                                this.widgetValue.replace( /^(\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\d-\d\d)(\d\d)$/, '$1:$2') 
+                        if (this.widgetValue != null) {
+                            this.widgetValue = openils.Util.timeStampAsDateObj(
+                                this.widgetValue
                             );
+                        }
                         break;
 
                     case 'bool':
@@ -351,6 +365,8 @@
         _getLinkSelector : function() {
             var linkClass = this.idlField['class'];
             if(this.idlField.reltype != 'has_a')  return false;
+            if(!fieldmapper.IDL.fmclasses[linkClass]) // class neglected by AutoIDL
+                fieldmapper.IDL.load([linkClass]);
             if(!fieldmapper.IDL.fmclasses[linkClass].permacrud) return false;
             if(!fieldmapper.IDL.fmclasses[linkClass].permacrud.retrieve) return false;
 
@@ -560,6 +576,7 @@
         _buildPermGrpSelector : function() {
             dojo.require('openils.widget.FilteringTreeSelect');
             this.widget = new openils.widget.FilteringTreeSelect(this.dijitArgs, this.parentNode);
+            this.widget.disableQuery = this.disableQuery;
             this.widget.searchAttr = 'name';
 
             if(this.cache.permGrpTree) {

Modified: branches/serials-integration/Open-ILS/web/js/dojo/openils/widget/AutoGrid.js
===================================================================
--- branches/serials-integration/Open-ILS/web/js/dojo/openils/widget/AutoGrid.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/js/dojo/openils/widget/AutoGrid.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -20,6 +20,7 @@
             editStyle : 'dialog',
             editReadOnly : false,
             suppressFields : null,
+            suppressEditFields : null,
             hideSelector : false,
             selectorWidth : '1.5',
             showColumnPicker : false,
@@ -86,14 +87,10 @@
                         style : 'padding-right:6px;',
                         href : 'javascript:void(0);', 
                         onclick : function() { 
-                            self.resetStore();
                             self.cachedQueryOpts.offset = self.displayOffset -= self.displayLimit;
                             if(self.displayOffset < 0)
                                 self.cachedQueryOpts.offset = self.displayOffset = 0;
-                            if(self.dataLoader)
-                                self.dataLoader()
-                            else
-                                self.loadAll(self.cachedQueryOpts, self.cachedQuerySearch);
+                            self.refresh();
                         }
                     });
 
@@ -102,12 +99,8 @@
                         style : 'padding-right:6px;',
                         href : 'javascript:void(0);', 
                         onclick : function() { 
-                            self.resetStore();
                             self.cachedQueryOpts.offset = self.displayOffset += self.displayLimit;
-                            if(self.dataLoader)
-                                self.dataLoader()
-                            else
-                                self.loadAll(self.cachedQueryOpts, self.cachedQuerySearch);
+                            self.refresh();
                         }
                     });
 
@@ -384,6 +377,7 @@
                     overrideWidgetArgs : this.overrideWidgetArgs,
                     disableWidgetTest : this.disableWidgetTest,
                     requiredFields : this.requiredFields,
+                    suppressFields : this.suppressEditFields,
                     onPostSubmit : function() {
                         for(var i in fmObject._fields) {
                             var field = fmObject._fields[i];
@@ -424,6 +418,7 @@
                     overrideWidgetArgs : this.overrideWidgetArgs,
                     disableWidgetTest : this.disableWidgetTest,
                     requiredFields : this.requiredFields,
+                    suppressFields : this.suppressEditFields,
                     onPostSubmit : function(req, cudResults) {
                         var fmObject = cudResults[0];
                         if(grid.onPostCreate)
@@ -554,6 +549,14 @@
                 this.setStore(this.buildAutoStore());
             },
 
+            refresh : function() {
+                this.resetStore();
+                if (this.dataLoader)
+                    this.dataLoader()
+                else
+                    this.loadAll(this.cachedQueryOpts, this.cachedQuerySearch);
+            },
+
             loadAll : function(opts, search) {
                 dojo.require('openils.PermaCrud');
                 if(this.loadProgressIndicator)

Modified: branches/serials-integration/Open-ILS/web/js/dojo/openils/widget/AutoWidget.js
===================================================================
--- branches/serials-integration/Open-ILS/web/js/dojo/openils/widget/AutoWidget.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/js/dojo/openils/widget/AutoWidget.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -20,6 +20,10 @@
             if(this.fmObject)
                 this.fmClass = this.fmObject.classname;
             this.fmIDL = fieldmapper.IDL.fmclasses[this.fmClass];
+            if(!this.fmIDL) {
+                fieldmapper.IDL.load([this.fmClass]);
+                this.fmIDL = fieldmapper.IDL.fmclasses[this.fmClass];
+            }
             this.buildSortedFieldList();
         },
 

Modified: branches/serials-integration/Open-ILS/web/js/dojo/openils/widget/EditPane.js
===================================================================
--- branches/serials-integration/Open-ILS/web/js/dojo/openils/widget/EditPane.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/js/dojo/openils/widget/EditPane.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -125,6 +125,15 @@
                         this.overrideWidgetArgs[field.name] // per-field overrides
                     );
 
+                    if (this.overrideWidgets[field.name]) {
+                        if (this.overrideWidgets[field.name].shove) {
+                            args.shove = dojo.mixin(
+                                {"mode": this.mode},
+                                this.overrideWidgets[field.name].shove
+                            );
+                        }
+                    }
+
                     if(args.readOnly) {
                         dojo.addClass(nameTd, 'openils-widget-editpane-ro-name-cell');
                         dojo.addClass(valTd, 'openils-widget-editpane-ro-value-cell');

Modified: branches/serials-integration/Open-ILS/web/js/dojo/openils/widget/FacetSidebar.js
===================================================================
--- branches/serials-integration/Open-ILS/web/js/dojo/openils/widget/FacetSidebar.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/js/dojo/openils/widget/FacetSidebar.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -34,6 +34,7 @@
             classOrder : null,
             searchSubmit : '',
             facetLimit : 10,
+            maxValuesPerFacet : 100,
 
             startup : function () {
                 this.populate();
@@ -47,12 +48,28 @@
 
                 if (openils.widget.Searcher._cache.facetData) {
                     this.facetData = openils.widget.Searcher._cache.facetData;
+                    this._render_callback();
                 } else {
-                    var facetData = fieldmapper.standardRequest( [ 'open-ils.search', 'open-ils.search.facet_cache.retrieve'], this.facetCacheKey );
-                    if (!facetData) return;
-                    this.facetData = openils.widget.Searcher._cache.facetData = facetData;
+                    var limit = dojo.isIE ? this.facetLimit : this.maxValuesPerFacet;
+                    var self = this;
+                    fieldmapper.standardRequest( 
+                        [ 'open-ils.search', 'open-ils.search.facet_cache.retrieve'], 
+                        { async : true,
+                          params : [this.facetCacheKey, limit],
+                          oncomplete : function(r) {
+                              var facetData = r.recv().content();
+                              if (!facetData) return;
+                              self.facetData = openils.widget.Searcher._cache.facetData = facetData;
+                              self._render_callback();
+                          }
+                        }
+                    );
                 }
 
+            },
+
+            _render_callback : function(facetData) {
+                var facetData = this.facetData;
                 var classes = openils.widget.Searcher._cache.arr.cmc;
                 if (this.classOrder && this.classOrder.length > 0) {
                     classes = [];

Modified: branches/serials-integration/Open-ILS/web/js/dojo/openils/widget/FilteringTreeSelect.js
===================================================================
--- branches/serials-integration/Open-ILS/web/js/dojo/openils/widget/FilteringTreeSelect.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/js/dojo/openils/widget/FilteringTreeSelect.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -24,6 +24,7 @@
             parentField : 'parent',
             labelAttr : 'name',
             childField : 'children',
+            disableQuery : null,
             tree : null,
 
             startup : function() {
@@ -44,26 +45,59 @@
                     this.store = new dojo.data.ItemFileReadStore({data:storeData});
                 }
                 this.inherited(arguments);
+
+                if(this.dataList.length > 0 && this.disableQuery)  
+                    this._setDisabled();
             },
 
+            _setDisabled : function() {
+
+                // tag disabled items
+                this.store.fetch({
+                    query : this.disableQuery,
+                    onItem : function(item) { item._disabled = 'true'; }
+                });
+
+                // disallow selecting of disabled items
+                var self = this;
+                dojo.connect(this, 'onChange', 
+                    function(ident) { 
+                        if(!ident) return;
+                        self.store.fetchItemByIdentity({
+                            identity : ident,
+                            onItem : function(item) {
+                                if(item._disabled == 'true')
+                                    self.attr('value', '');
+                            }
+                        });
+                    }
+                );
+            },
+
             // Compile the tree down to a depth-first list of dojo data items
             _makeNodeList : function(node, depth) {
                 if(!depth) depth = 0;
                 var storeItem = node.toStoreItem();
                 storeItem._depth = depth++;
                 this.dataList.push(storeItem);
+
                 for(var i in node[this.childField]()) 
                     this._makeNodeList(node[this.childField]()[i], depth);
             },
 
             // For each item, find the depth at display time by searching up the tree.
             _getMenuLabelFromItem : function(item) {
+
+                var style = 'padding-left:'+ (item._depth * this.defaultPad) +'px;';
+
+                if(item._disabled == 'true') // TODO: external CSS
+                    style += 'background-color:#CCC;cursor:wait'; 
+
                 return {
                     html: true,
-                    label: '<div style="padding-left:'+ (item._depth * this.defaultPad) +'px;">' +
-                        this.store.getValue(item, this.labelAttr) + '</div>'
+                    label: '<div style="'+style+'">' + this.store.getValue(item, this.labelAttr) + '</div>'
                 }
-            }
+            },
         }
     );
 }

Copied: branches/serials-integration/Open-ILS/web/js/dojo/openils/widget/HoldingCode.js (from rev 17886, trunk/Open-ILS/web/js/dojo/openils/widget/HoldingCode.js)
===================================================================
--- branches/serials-integration/Open-ILS/web/js/dojo/openils/widget/HoldingCode.js	                        (rev 0)
+++ branches/serials-integration/Open-ILS/web/js/dojo/openils/widget/HoldingCode.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -0,0 +1,167 @@
+if (!dojo._hasResource["openils.widget.HoldingCode"]) {
+    dojo.provide("openils.widget.HoldingCode");
+    dojo.require("dijit.layout.ContentPane");
+    dojo.require("dijit.form.DropDownButton");
+    dojo.require("dijit.form.TextBox");
+    dojo.require("dijit.form.NumberTextBox");
+
+    var _needed_fields = "abcdefghijklm";
+
+    function _prepare_ttip_dialog(div, wizard) {
+        dojo.empty(div);
+
+        var selector = wizard.args.scap_selector;
+        var caption_and_pattern = new scap().fromStoreItem(selector.item);
+
+        /* we're going to look for subfields a-h and i-m now. There may already
+         * be JS libs available to make this easier, but for now I'm doing this
+         * the fastest way I know. */
+
+        var pattern_code;
+        try {
+            pattern_code = JSON2js(caption_and_pattern.pattern_code());
+        } catch (E) {
+            /* no-op */;
+        }
+
+        if (!dojo.isArray(pattern_code)) {
+            div.innerHTML =
+                "Have you selected a valid caption and pattern?";/* XXX i18n */
+            return;
+        }
+
+        var fields = [];
+        for (var i = 0; i < pattern_code.length; i += 2) {
+            var subfield = pattern_code[i];
+            var value = pattern_code[i + 1];
+
+            if (_needed_fields.indexOf(subfield) != -1)
+                fields.push({"subfield": subfield, "caption": value});
+        }
+
+        if (!fields.length) {
+            div.innerHTML = /* XXX i18n (below) */
+                "No caption subfields in seleted caption and pattern";
+            return;
+        }
+
+        _prepare_ttip_dialog_fields(div, fields, wizard);
+    }
+
+    function _prepare_ttip_dialog_fields(div, fields, wizard) {
+        /* XXX TODO Don't assume these defaults for the indicators and $8, and
+         * provide reasonable control over them. */
+        var holding_code = ["4", "1", "8", "1"];
+        var inputs = [];
+
+        wizard.wizard_button.attr("disabled", true);
+        var table = dojo.create("table", {"className": "serial-holding-code"});
+        fields.forEach(
+            function(field) {
+                var tr = dojo.create("tr", null, table);
+
+                field.caption = field.caption.replace(/^\(?([^\)]+)\)?$/, "$1");
+                if (field.subfield > "h") {
+                    field.caption = field.caption.slice(0,1).toUpperCase() +
+                        field.caption.slice(1);
+                }
+
+                dojo.create("td", {"innerHTML": field.caption}, tr);
+                var dij = field.subfield > "h" ?
+                    dijit.form.NumberTextBox : dijit.form.TextBox;
+                var input = new dij(
+                    {
+                        "name": field.subfield,
+                        "constraints": {"pattern": "####"}
+                    },
+                    dojo.create("td", null, tr)
+                );
+                input.startup();
+                inputs.push({"subfield": field.subfield, "input": input});
+            }
+        );
+
+        new dijit.form.Button(
+            {
+                "label": "Compile",
+                "onClick": function() {
+                    inputs.forEach(
+                        function(input) {
+                            var value = input.input.attr("value");
+                            if (value === null || isNaN(value)) {
+                                /* XXX i18n */
+                                alert("A valid holding code cannot be " +
+                                    "produced with any blank fields.");
+                            }
+                            holding_code.push(input.subfield);
+                            holding_code.push(value);
+                        }
+                    );
+                    wizard.code_text_box.attr("value", js2JSON(holding_code));
+                    wizard.wizard_button.attr("disabled", false);
+                    dojo.empty(div);
+                }
+            }, dojo.create(
+                "span", null, dojo.create(
+                    "td", {"colspan": 2},
+                    dojo.create("tr", null, table)
+                )
+            )
+        );
+        dojo.place(table, div, "only");
+    }
+
+    dojo.declare(
+        "openils.widget.HoldingCode", dijit.layout.ContentPane, {
+            "constructor": function(args) {
+                this.args = args || {};
+            },
+
+            "startup": function() {
+                var self = this;
+                this.inherited(arguments);
+
+                var dialog_div = dojo.create(
+                    "div", {
+                        "style": "padding:1em;margin:0;text-align:center;"
+                    }, this.domNode
+                );
+                var target_div = dojo.create("div", null, this.domNode);
+                dojo.create("br", null, this.domNode);
+
+                this.wizard_button = new dijit.form.Button(
+                    {
+                        "label": "Wizard" /* XXX i18n */,
+                        "onClick": function() {
+                            _prepare_ttip_dialog(target_div, self);
+                        }
+                    },
+                    dojo.create("span", null, dialog_div)
+                );
+
+                this.code_text_box = new dijit.form.TextBox(
+                    {}, dojo.create("div", null, this.domNode)
+                );
+                this.code_text_box.startup();
+            },
+
+            "attr": function(name, value) {
+                if (name == "value") {
+                    /* XXX can this get called before any subdijits are
+                     * built (before startup() is run)? */
+                    if (value) {
+                        this.code_text_box.attr(name, value);
+                    }
+                    return this.code_text_box.attr(name);
+                } else {
+                    return this.inherited(arguments);
+                }
+            },
+
+            "update_scap_selector": function(selector) {
+                this.args.scap_selector = selector;
+                this.attr("value", "");
+            }
+        }
+    );
+}

Modified: branches/serials-integration/Open-ILS/web/js/dojo/openils/widget/Searcher.js
===================================================================
--- branches/serials-integration/Open-ILS/web/js/dojo/openils/widget/Searcher.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/js/dojo/openils/widget/Searcher.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -274,7 +274,7 @@
 
             var fielder_result = fieldmapper.standardRequest(
                 [ 'open-ils.fielder', 'open-ils.fielder.'+c.classname+'.atomic'],
-                [ { query : q } ]
+                [ { cache : 1, query : q } ]
             );
 
             var sorted_fielder_result = fielder_result.sort( function(a,b) {

Modified: branches/serials-integration/Open-ILS/web/js/dojo/openils/widget/nls/Searcher.js
===================================================================
--- branches/serials-integration/Open-ILS/web/js/dojo/openils/widget/nls/Searcher.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/js/dojo/openils/widget/nls/Searcher.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -1,6 +1,6 @@
 {
-    and : '&&',
-    or  : '||',
+    and : 'AND',
+    or  : 'OR',
     more  : 'More...',
     less  : '...Less',
     classed_searches  : 'Classed Searches',

Modified: branches/serials-integration/Open-ILS/web/js/ui/default/acq/common/li_table.js
===================================================================
--- branches/serials-integration/Open-ILS/web/js/ui/default/acq/common/li_table.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/js/ui/default/acq/common/li_table.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -68,7 +68,6 @@
     this.realCopiesRow = this.realCopiesTbody.removeChild(dojo.byId('acq-lit-real-copies-row'));
     this._copy_fields_for_acqdf = ['owning_lib', 'location'];
     this.skipInitialEligibilityCheck = false;
-    this.invoiceLinkDialogManager = new InvoiceLinkDialogManager("li");
     this.claimDialog = new ClaimDialogManager(
         liClaimDialog, finalClaimDialog, this.claimEligibleLidByLi,
         function(li) {    /* callback that fires when claims are made */
@@ -76,11 +75,10 @@
         }
     );
 
-    dojo.connect(acqLitLiActionsSelector, 'onChange', 
-        function() { 
-            self.applySelectedLiAction(this.attr('value')) 
-            acqLitLiActionsSelector.attr('value', '_');
-        });
+    dojo.byId("acq-lit-li-actions-selector").onchange = function() { 
+        self.applySelectedLiAction(this.options[this.selectedIndex].value);
+        this.selectedIndex = 0;
+    };
 
     acqLitCreatePoSubmit.onClick = function() {
         if (self._confirmPoPrepaySituation()) {
@@ -274,11 +272,12 @@
             );
         }
 
+        nodeByName("liid", row).innerHTML += li.id();
+
         if(li.eg_bib_id()) {
             openils.Util.show(nodeByName('catalog', row), 'inline');
             nodeByName("catalog_link", row).onclick = this.generateMakeRecTab(li.eg_bib_id());
         } else {
-            // TODO: Add discovery mechanism for bib linking
             openils.Util.show(nodeByName('link_to_catalog', row), 'inline');
             nodeByName("link_to_catalog_link", row).onclick = function() { self.drawBibFinder(li) };
         }
@@ -500,6 +499,10 @@
                 nodeByName("action_none", row).selected = true;
             };
             actLinkInvoice.onclick = function() {
+                if (!self.invoiceLinkDialogManager) {
+                    self.invoiceLinkDialogManager =
+                        new InvoiceLinkDialogManager("li");
+                }
                 self.invoiceLinkDialogManager.target = li;
                 acqLitLinkInvoiceDialog.show();
                 nodeByName("action_none", row).selected = true;
@@ -732,7 +735,8 @@
 
         fieldmapper.standardRequest(
             ['open-ils.acq', 'open-ils.acq.lineitem.price.set'],
-            {   async : true,
+            {   async : false, // redundant w/ timeout
+                timeout : 10,
                 params : [this.authtoken, li.id(), price],
                 oncomplete : function(r) {
                     openils.Util.readResponse(r);
@@ -1441,6 +1445,7 @@
                     parentNode : dojo.query('[name='+field+']', row)[0],
                     orgLimitPerms : ['CREATE_PICKLIST', 'CREATE_PURCHASE_ORDER'],
                     readOnly : readOnly,
+                    orgDefaultsToWs : true
                 });
 
                 widget.build(
@@ -2076,8 +2081,7 @@
                     progressDialog.hide();
                     var evt = openils.Util.readResponse(r);
                     if(evt && evt.template_output()) {
-                        win = window.open('','', 'resizable,width=800,height=600,scrollbars=1');
-                        win.document.body.innerHTML = evt.template_output().data();
+                        openils.Util.printHtmlString(evt.template_output().data());
                     }
                 }
             }
@@ -2309,7 +2313,7 @@
         }
         var self = this;
         win.xulG = {
-            record : {marc : li.marc()},
+            record : {marc : li.marc(), "rtype": "bre"},
             save : {
                 label: 'Save Record', // XXX I18N
                 func: function(xmlString) {

Modified: branches/serials-integration/Open-ILS/web/js/ui/default/acq/financial/view_fund.js
===================================================================
--- branches/serials-integration/Open-ILS/web/js/ui/default/acq/financial/view_fund.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/js/ui/default/acq/financial/view_fund.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -69,13 +69,13 @@
     /* XXX If we want to show allocating user with a username instead of just
      * ID#, the following pcrud search will have to be replaced with an API
      * call. */
-    fundAllocationGrid.loadAll({order_by : {acqfa :  'create_time DESC'}});
+    fundAllocationGrid.loadAll({order_by : {acqfa :  'create_time DESC'}}, {fund : fundID});
     fundAllocationGrid.isLoaded = true;
 }
 
 function loadDebitGrid() {
     if(fundDebitGrid.isLoaded) return;
-    fundDebitGrid.loadAll({order_by : {acqfdeb :  'create_time DESC'}});
+    fundDebitGrid.loadAll({order_by : {acqfdeb :  'create_time DESC'}}, {fund : fundID});
     fundDebitGrid.isLoaded = true;
 }
 

Modified: branches/serials-integration/Open-ILS/web/js/ui/default/acq/invoice/view.js
===================================================================
--- branches/serials-integration/Open-ILS/web/js/ui/default/acq/invoice/view.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/js/ui/default/acq/invoice/view.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -472,11 +472,19 @@
 
     nodeByName('detach', row).onclick = function() {
         var cost = widgetRegistry.acqie[entry.id()].cost_billed.getFormattedValue();
+        var idents = [];
+        dojo.forEach(['isbn', 'upc', 'issn'], 
+            function(ident) { 
+                var val = liMarcAttr(entry.lineitem(), ident);
+                if(val) idents.push(val); 
+            }
+        );
+
         var msg = dojo.string.substitute(
             localeStrings.INVOICE_CONFIRM_ENTRY_DETACH, [
                 cost || 0,
-                liMarcAttr(lineitem, 'title'),
-                liMarcAttr(lineitem, 'author'),
+                liMarcAttr(entry.lineitem(), 'title'),
+                liMarcAttr(entry.lineitem(), 'author'),
                 idents.join(',')
             ]
         );

Modified: branches/serials-integration/Open-ILS/web/js/ui/default/acq/po/view_po.js
===================================================================
--- branches/serials-integration/Open-ILS/web/js/ui/default/acq/po/view_po.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/js/ui/default/acq/po/view_po.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -295,9 +295,6 @@
             "/acq/invoice/view?create=1&attach_po=" + PO.id();
     };
 
-    if (!invoiceLinkDialogManager)
-        invoiceLinkDialogManager = new InvoiceLinkDialogManager("po", PO);
-
     openils.Util.show("acq-po-invoice-stuff", "table-cell");
 }
 
@@ -312,6 +309,21 @@
     dojo.byId("acq-po-view-total-enc").innerHTML = PO.amount_encumbered().toFixed(2);
     dojo.byId("acq-po-view-total-spent").innerHTML = PO.amount_spent().toFixed(2);
     dojo.byId("acq-po-view-state").innerHTML = PO.state(); // TODO i18n
+
+    if(PO.order_date()) {
+        openils.Util.show('acq-po-activated-on', 'inline');
+        dojo.byId('acq-po-activated-on').innerHTML = 
+            dojo.string.substitute(
+                localeStrings.PO_ACTIVATED_ON, [
+                    dojo.date.locale.format(
+                        dojo.date.stamp.fromISOString(PO.order_date()), 
+                        {formatLength:'short'}
+                    )
+                ]
+            );
+
+    }
+
     makePrepayWidget(
         dojo.byId("acq-po-view-prepay"),
         openils.Util.isTrue(PO.prepayment_required())
@@ -385,7 +397,11 @@
     fieldmapper.standardRequest(
         ['open-ils.acq', 'open-ils.acq.lineitem.search'],
         {   async: true,
-params: [openils.User.authtoken, {purchase_order:poId}, {flesh_attrs:true, flesh_notes:true, flesh_cancel_reason:true}],
+            params: [
+                openils.User.authtoken, 
+                {purchase_order:poId}, 
+                {flesh_attrs:true, flesh_notes:true, flesh_cancel_reason:true, clear_marc:true}
+            ],
             onresponse: function(r) {
                 zeroLi = false;
                 liTable.show('list');
@@ -429,6 +445,7 @@
     d.innerHTML = localeStrings.PO_CHECKING;
     var warnings = [];
     var stops = [];
+    var other = [];
 
     fieldmapper.standardRequest(
         ["open-ils.acq", "open-ils.acq.purchase_order.activate.dry_run"], {
@@ -444,6 +461,8 @@
                             case "ACQ_FUND_EXCEEDS_WARN_PERCENT":
                                 warnings.push(r);
                                 break;
+                            default:
+                                other.push(r);
                         }
                     }
                 }
@@ -451,11 +470,16 @@
             "oncomplete": function() {
                 /* XXX in the future, this might be tweaked to display info
                  * about more than one stop or warning event from the ML. */
-                if (!(warnings.length || stops.length)) {
+                if (!(warnings.length || stops.length || other.length)) {
                     d.innerHTML = localeStrings.PO_COULD_ACTIVATE;
                     openils.Util.show(a, "inline");
                 } else {
-                    if (stops.length) {
+                    if (other.length) {
+                        /* XXX make the textcode part a tooltip one day */
+                        d.innerHTML = localeStrings.NO + ": " +
+                            other[0].desc + " (" + other[0].textcode + ")";
+                        openils.Util.hide(a);
+                    } else if (stops.length) {
                         d.innerHTML =
                             dojo.string.substitute(
                                 localeStrings.PO_STOP_BLOCKS_ACTIVATION, [

Modified: branches/serials-integration/Open-ILS/web/js/ui/default/acq/search/invoice.js
===================================================================
--- branches/serials-integration/Open-ILS/web/js/ui/default/acq/search/invoice.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/js/ui/default/acq/search/invoice.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -1,3 +1,5 @@
+dojo.require('openils.widget.ProgressDialog');
+
 function getInvIdent(rowIndex, item) {
     if (item) {
         return {
@@ -19,9 +21,9 @@
     var inv_ids = dijit.byId("acq-unified-inv-grid").
         getSelectedItems().map(function(o) {return o.id[0];});
 
-    /* XXX this business about opening a window and populating its
-     * body should be wrapped up in a simple dijit or something.
-     * consolidate with claim_voucher.js maybe. */
+    progressDialog.show(true);
+
+    var html;
     if (inv_ids.length) {
         var win = null;
         fieldmapper.standardRequest(
@@ -30,22 +32,18 @@
                 "async": true,
                 "onresponse": function(r) {
                     if (r = openils.Util.readResponse(r)) {
-                        if (!win) {
-                            win = window.open(
-                                "", "", "resizable,width=800," +
-                                "height=600,scrollbars=1"
-                            );
-                            win.document.title = localeStrings.INVOICES;
-                            win.document.body.innerHTML =
-                                "<style type='text/css'>.acq-invoice-" +
+                        if(!html) {
+                            html = "<style type='text/css'>.acq-invoice-" +
                                 "voucher {page-break-after:always;}" +
                                 "</style>\n";
                         }
-                        win.document.body.innerHTML +=
-                            r.template_output().data();
+                        html += r.template_output().data();
                     }
                 },
-                "oncomplete": function() { win.print(); }
+                "oncomplete": function() { 
+                    progressDialog.hide();
+                    openils.Util.printHtmlString(html);
+                }
             }
         );
     }

Modified: branches/serials-integration/Open-ILS/web/js/ui/default/acq/search/unified.js
===================================================================
--- branches/serials-integration/Open-ILS/web/js/ui/default/acq/search/unified.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/js/ui/default/acq/search/unified.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -169,6 +169,13 @@
                             w.focus();
                         if (typeof(callback) == "function")
                             callback(term, widgetKey);
+
+                        // submit on enter
+                        openils.Util.registerEnterHandler(w.domNode,
+                            function() { 
+                                resultManager.go(termManager.buildSearchObject());
+                            }
+                        );
                     }
                 );
             }
@@ -801,6 +808,7 @@
                     {"state": "on-order"}
                 ]
             },
+            "half_search": true,
             "result_type": "purchase_order",
             "conjunction": "and",
             "order_by": [
@@ -826,6 +834,7 @@
                     {"receiver": openils.User.user.ws_ou()}
                 ]
             },
+            "half_search": true,
             "result_type": "invoice",
             "conjunction": "and",
             "order_by": [
@@ -869,10 +878,13 @@
 
         uriManager = new URIManager();
         if (uriManager.search_object) {
-            hideForm();
+            if (!uriManager.half_search)
+                hideForm();
             openils.Util.show("acq-unified-body");
             termManager.reflect(uriManager.search_object);
-            resultManager.search(uriManager, termManager);
+
+            if (!uriManager.half_search)
+                resultManager.search(uriManager, termManager);
         } else {
             termManager.addRow();
             openils.Util.show("acq-unified-body");

Modified: branches/serials-integration/Open-ILS/web/js/ui/default/actor/user/register.js
===================================================================
--- branches/serials-integration/Open-ILS/web/js/ui/default/actor/user/register.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/js/ui/default/actor/user/register.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -44,6 +44,7 @@
 var stageUser;
 var optInSettings;
 var allCardsTemplate;
+var uEditCloneCopyAddr; // if true, copy addrs on clone instead of link
 
 var dupeUsrname = false;
 var dupeBarcode = false;
@@ -81,12 +82,18 @@
         'global.juvenile_age_threshold',
         'patron.password.use_phone',
         'ui.patron.default_inet_access_level',
-        'circ.holds.behind_desk_pickup_supported'
+        'ui.patron.default_ident_type',
+        'ui.patron.default_country',
+        'ui.patron.registration.require_address',
+        'circ.holds.behind_desk_pickup_supported',
+        'circ.patron_edit.clone.copy_address'
     ]);
+
     for(k in orgSettings)
         if(orgSettings[k])
             orgSettings[k] = orgSettings[k].value;
 
+    uEditCloneCopyAddr = orgSettings['circ.patron_edit.clone.copy_address'];
     uEditUsePhonePw = orgSettings['patron.password.use_phone'];
     uEditFetchUserSettings(userId);
 
@@ -285,34 +292,69 @@
 function uEditCopyCloneData(patron) {
     cloneUserObj = uEditLoadUser(cloneUser);
 
-    dojo.forEach( [
+    var cloneFields = [
         'home_ou', 
         'day_phone', 
         'evening_phone', 
         'other_phone',
-        'billing_address',
-        'usrgroup',
-        'mailing_address' ], 
+        'usrgroup'
+    ];
+
+    if(!uEditCloneCopyAddr) 
+        cloneFields = cloneFields.concat(['mailing_address', 'billing_address']);
+
+    dojo.forEach(
+        cloneFields, 
         function(field) {
             patron[field](cloneUserObj[field]());
         }
     );
 
-    // don't grab all addresses().  the only ones we can link to are billing/mailing
-    if(patron.billing_address()) {
-        var t = patron.addresses();
-            if (!t) { t = []; }
-            t.push(patron.billing_address());
-            patron.addresses(t);
-    }
+    if(uEditCloneCopyAddr) {
+        var billAddr, mailAddr;
 
-    if(patron.mailing_address() && (
-            patron.addresses().length == 0 || 
-            patron.mailing_address().id() != patron.billing_address().id()) ) {
-        var t = patron.addresses();
-            if (!t) { t = []; }
-            t.push(patron.mailing_address());
-            patron.addresses(t);
+        // copy the billing and mailing addresses into new addresses
+        function cloneAddr(addr) {
+            var newAddr = addr.clone();
+            newAddr.isnew(true);
+            newAddr.id(uEditAddrVirtId--);
+            newAddr.usr(patron.id());
+            patron.addresses().push(newAddr);
+            return newAddr;
+        }
+
+        if(billAddr = cloneUserObj.billing_address()) 
+            patron.billing_address(cloneAddr(billAddr));
+
+        if(mailAddr = cloneUserObj.mailing_address()) {
+            if (billAddr && billAddr.id() == mailAddr.id()) {
+                patron.mailing_address(patron.billing_address());
+            } else {
+                patron.mailing_address(cloneAddr(mailAddr));
+            }
+        }
+
+        if(!billAddr) // if there was no billing addr, use the mailing addr
+            patron.billing_address(patron.mailing_address());
+
+    } else {
+
+        // link the billing and mailing addresses
+        if(patron.billing_address()) {
+            var t = patron.addresses();
+                if (!t) { t = []; }
+                t.push(patron.billing_address());
+                patron.addresses(t);
+        }
+
+        if(patron.mailing_address() && (
+                patron.addresses().length == 0 || 
+                patron.mailing_address().id() != patron.billing_address().id()) ) {
+            var t = patron.addresses();
+                if (!t) { t = []; }
+                t.push(patron.mailing_address());
+                patron.addresses(t);
+        }
     }
 }
 
@@ -415,6 +457,9 @@
         var stat = statCats[idx];
         var row = statCatTemplate.cloneNode(true);
         row.id = 'stat-cat-row-' + idx;
+        row.setAttribute('stat_cat_owner',stat.owner());
+        row.setAttribute('stat_cat_name',stat.name());
+        row.setAttribute('stat_cat_id',stat.id());
         tbody.appendChild(row);
         getByName(row, 'name').innerHTML = stat.name();
         var valtd = getByName(row, 'widget');
@@ -481,6 +526,8 @@
     var wclass = row.getAttribute('wclass');
     var wstyle = row.getAttribute('wstyle');
     var wconstraints = row.getAttribute('wconstraints');
+    /* use CSS to set the zindex for widgets you want to disable. */
+    var disabled = dojo.style(row, 'zIndex') == -1 ? true : false;
 
     var isPasswd2 = (fmfield == 'passwd2');
     if(isPasswd2) fmfield = 'passwd';
@@ -510,7 +557,6 @@
     wtd.appendChild(span);
 
     var fmObject = null;
-    var disabled = false;
     switch(fmcls) {
         case 'au' : fmObject = patron; break;
         case 'ac' : fmObject = patron.card(); break;
@@ -549,12 +595,7 @@
     if(value !== null)
         dijitArgs.value = value;
 
-    // fetch profile groups non-async so existing expire_date is
-    // not overwritten when the profile groups arrive and update
-    var sync = (fmfield == 'profile') ? true : false;
-
-    var widget = new openils.widget.AutoFieldWidget({
-        forceSync : sync,
+    var wargs = {
         idlField : fieldIdl,
         fmObject : fmObject,
         fmClass : fmcls,
@@ -563,8 +604,18 @@
         dijitArgs : dijitArgs,
         orgDefaultsToWs : true,
         orgLimitPerms : ['UPDATE_USER'],
-    });
+    };
 
+    if(fmfield == 'profile') {
+        // fetch profile groups non-async so existing expire_date is
+        // not overwritten when the profile groups arrive and update
+        wargs.forceSync = true;
+        wargs.disableQuery = {usergroup : 'f'};
+    } else {
+        wargs.forceSync = false;
+    }
+
+    var widget = new openils.widget.AutoFieldWidget(wargs);
     widget.build();
 
     // now put it back before we register the widget
@@ -959,6 +1010,7 @@
     patron.card(card);
     patron.cards([card]);
     patron.net_access_level(orgSettings['ui.patron.default_inet_access_level'] || 1);
+    patron.ident_type(orgSettings['ui.patron.default_ident_type']);
     patron.stat_cat_entries([]);
     patron.survey_responses([]);
     patron.addresses([]);
@@ -1016,6 +1068,7 @@
                     addr.id(w._addr);
                     addr.isnew(1);
                     addr.usr(patron.id());
+                    addr.country(orgSettings['ui.patron.default_country']);
                     var t = patron.addresses();
                         if (!t) { t = []; }
                         t.push(addr);
@@ -1164,6 +1217,10 @@
                 if(id < 0 && row.getAttribute('fmfield') == 'valid') 
                     widget.widget.attr('value', true); 
 
+                // make new addresses use the org setting for default country 
+                if(id < 0 && row.getAttribute('fmfield') == 'country') 
+                    widget.widget.attr('value',orgSettings['ui.patron.default_country']);
+
             } else if(row.getAttribute('name') == 'uedit-addr-pending-row') {
 
                 // if it's a pending address, show the 'approve' button
@@ -1292,9 +1349,24 @@
 
 
 function uEditDeleteAddr(id, noAlert) {
+    if (patron.isnew() && orgSettings['ui.patron.registration.require_address']) {
+        if (dojo.query('tr[name=uedit-addr-divider]').length < 2) {
+            alert(localeStrings.NEED_ADDRESS);
+            return;
+        }
+    }
     if(!noAlert) {
-        if(!confirm('Delete address ' + id)) return; /* XXX i18n */
+        if(!confirm(dojo.string.substitute(localeStrings.DELETE_ADDRESS, [id]))) return;
     }
+    var addr = patron.addresses().filter(function(i){return (i.id() == id)})[0];
+    if (addr) { addr.isdeleted(1); }
+    var m_a = patron.mailing_address();
+        if (typeof m_a == 'object' && m_a != null) { m_a = m_a.id(); }
+        if (m_a == id) { patron.mailing_address(null); }
+    var b_a = patron.billing_address();
+        if (typeof b_a == 'object' && b_a != null) { b_a = b_a.id(); }
+        if (b_a == id) { patron.billing_address(null); }
+
     var rows = dojo.query('tr[addr='+id+']', tbody);
     for(var i = 0; i < rows.length; i++)
         rows[i].parentNode.removeChild(rows[i]);

Modified: branches/serials-integration/Open-ILS/web/js/ui/default/booking/reservation.js
===================================================================
--- branches/serials-integration/Open-ILS/web/js/ui/default/booking/reservation.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/js/ui/default/booking/reservation.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -8,6 +8,7 @@
 dojo.require("dojo.data.ItemFileReadStore");
 dojo.require("dijit.form.DateTextBox");
 dojo.require("dijit.form.TimeTextBox");
+dojo.require("dojo.date.stamp");
 dojo.requireLocalization("openils.booking", "reservation");
 
 /*
@@ -60,7 +61,7 @@
     };
 }
 TimestampRange.prototype.get_timestamp = function(when) {
-    return this.any_widget.serialize(this[when]).
+    return dojo.date.stamp.toISOString(this[when]).
         replace("T", " ").substr(0, 19);
 };
 TimestampRange.prototype.get_range = function() {
@@ -69,16 +70,14 @@
         [this.get_timestamp("start"), this.get_timestamp("end")];
 };
 TimestampRange.prototype.update_from_widget = function(widget) {
-    var when = widget.id.match(/(start|end)/)[1];
-    var which = widget.id.match(/(date|time)/)[1];
+    var when = widget.name.match(/(start|end)/)[1];
+    var which = widget.name.match(/(date|time)/)[1];
 
-    if (this.any_widget == undefined)
-        this.any_widget = widget;
     if (this.nodes[when][which] == undefined)
         this.nodes[when][which] = widget.domNode; /* We'll need this later */
 
     if (when && which) {
-        this.update_timestamp(when, which, widget.value);
+        this.update_timestamp(when, which, widget.attr("value"));
     }
 
     this.compute_validity();
@@ -116,8 +115,8 @@
 TimestampRange.prototype.update_timestamp = function(when, which, value) {
     if (which == "date") {
         this[when].setFullYear(value.getFullYear());
-        this[when].setMonth(value.getMonth());
-        this[when].setDate(value.getDate());
+        /* month and date MUST be done together */
+        this[when].setMonth(value.getMonth(), value.getDate());
     } else {    /* "time" */
         this[when].setHours(value.getHours());
         this[when].setMinutes(value.getMinutes());

Copied: branches/serials-integration/Open-ILS/web/js/ui/default/cat (from rev 17886, trunk/Open-ILS/web/js/ui/default/cat)

Modified: branches/serials-integration/Open-ILS/web/js/ui/default/circ/selfcheck/selfcheck.js
===================================================================
--- branches/serials-integration/Open-ILS/web/js/ui/default/circ/selfcheck/selfcheck.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/js/ui/default/circ/selfcheck/selfcheck.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -341,7 +341,16 @@
     );
 
     var evt = openils.Event.parse(this.patron);
-    if(evt) {
+    
+    // verify validity of the card used to log in
+    var inactiveCard = false;
+    if(!evt) {
+        var card = this.patron.cards().filter(
+            function(c) { return (c.barcode() == barcode); })[0];
+        inactiveCard = !openils.Util.isTrue(card.active());
+    }
+
+    if(evt || inactiveCard) {
         this.handleAlert(
             dojo.string.substitute(localeStrings.LOGIN_FAILED, [barcode]),
             false, 'login-failure'
@@ -669,12 +678,12 @@
                 }
 
                 fieldmapper.standardRequest( // fetch the hold objects with fleshed details
-                    ['open-ils.circ', 'open-ils.circ.hold.details.batch.retrieve.atomic'],
+                    ['open-ils.circ', 'open-ils.circ.hold.details.batch.retrieve'],
                     {   async : true,
                         params : [self.authtoken, ids],
-
-                        oncomplete : function(rr) {
-                            self.drawHolds(openils.Util.readResponse(rr));
+                        onresponse : function(rr) {
+                            progressDialog.hide();
+                            self.insertHold(openils.Util.readResponse(rr));
                         }
                     }
                 );
@@ -683,54 +692,45 @@
     );
 }
 
-/**
- * Fetch and add a single hold to the list of holds
- */
-SelfCheckManager.prototype.drawHolds = function(holds) {
+SelfCheckManager.prototype.insertHold = function(data) {
+    var row = this.holdTemplate.cloneNode(true);
 
-    holds = holds.sort(
-        // sort available holds to the top of the list
-        // followed by queue position order
-        function(a, b) {
-            if(a.status == 4) return -1;
-            if(a.queue_position < b.queue_position) return -1;
-            return 1;
-        }
-    );
+    if(data.mvr.isbn()) {
+        this.byName(row, 'jacket').setAttribute('src', '/opac/extras/ac/jacket/small/' + data.mvr.isbn());
+    }
 
-    this.holds = holds;
+    this.byName(row, 'title').innerHTML = data.mvr.title();
+    this.byName(row, 'author').innerHTML = data.mvr.author();
 
-    progressDialog.hide();
+    if(data.status == 4) {
 
-    for(var i in holds) {
+        // hold is ready for pickup
+        this.byName(row, 'status').innerHTML = localeStrings.HOLD_STATUS_READY;
 
-        var data = holds[i];
-        var row = this.holdTemplate.cloneNode(true);
+    } else {
 
-        if(data.mvr.isbn()) {
-            this.byName(row, 'jacket').setAttribute('src', '/opac/extras/ac/jacket/small/' + data.mvr.isbn());
-        }
+        // hold is still pending
+        this.byName(row, 'status').innerHTML = 
+            dojo.string.substitute(
+                localeStrings.HOLD_STATUS_WAITING,
+                [data.queue_position, data.potential_copies]
+            );
+    }
 
-        this.byName(row, 'title').innerHTML = data.mvr.title();
-        this.byName(row, 'author').innerHTML = data.mvr.author();
+    // find the correct place the table to slot in the hold based on queue position
 
-        if(data.status == 4) {
+    var position = (data.status == 4) ? 0 : data.queue_position;
+    row.setAttribute('position', position);
 
-            // hold is ready for pickup
-            this.byName(row, 'status').innerHTML = localeStrings.HOLD_STATUS_READY;
-
-        } else {
-
-            // hold is still pending
-            this.byName(row, 'status').innerHTML = 
-                dojo.string.substitute(
-                    localeStrings.HOLD_STATUS_WAITING,
-                    [data.queue_position, data.potential_copies]
-                );
+    for(var i = 0; i < this.holdTbody.childNodes.length; i++) {
+        var node = this.holdTbody.childNodes[i];
+        if(Number(node.getAttribute('position')) >= position) {
+            this.holdTbody.insertBefore(row, node);
+            return;
         }
+    }
 
-        this.holdTbody.appendChild(row);
-    }
+    this.holdTbody.appendChild(row);
 }
 
 

Modified: branches/serials-integration/Open-ILS/web/js/ui/default/conify/global/acq/distribution_formula.js
===================================================================
--- branches/serials-integration/Open-ILS/web/js/ui/default/conify/global/acq/distribution_formula.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/js/ui/default/conify/global/acq/distribution_formula.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -1,11 +1,23 @@
+dojo.require("dojo.dnd.Container");
+dojo.require("dojo.dnd.Source");
 dojo.require('openils.widget.AutoGrid');
 dojo.require('dijit.form.FilteringSelect');
 dojo.require('openils.PermaCrud');
-var formula;
+dojo.require('openils.widget.AutoFieldWidget');
+dojo.requireLocalization('openils.conify', 'conify');
+var localeStrings = dojo.i18n.getLocalization('openils.conify', 'conify');
+
+
 var formCache = [];
+var formula, entryTbody, entryTemplate, dndSource;
+var virtualId = -1;
+var pcrud;
 
+
 function draw() {
 
+    pcrud = new openils.PermaCrud();
+
     if(formulaId) {
         openils.Util.hide('formula-list-div');
         drawFormulaSummary();
@@ -33,18 +45,31 @@
 
     }
 }
-openils.Util.addOnLoad(draw);
 
-function drawFormulaSummary() {
-    openils.Util.show('formula-entry-div');
-    dfeListGrid.overrideEditWidgets.formula = new
-        dijit.form.TextBox({style:'display:none', value: formulaId});
-    dfeListGrid.loadAll({order_by:{acqdfe : 'formula'}}, {formula : formulaId});
-    var pcrud = new openils.PermaCrud();
-    var formulaName = pcrud.retrieve('acqdf', formulaId);
-    dojo.byId('formula_head').innerHTML = formulaName.name();
+function cloneSelectedFormula() {
+    var item = fListGrid.getSelectedItems()[0];
+    if(!item) return;
+    var formula = new fieldmapper.acqf().fromStoreItem(item);
+    fieldmapper.standardRequest(
+        ['open-ils.acq', 'open-ils.acq.distribution_formula.clone'],
+        {
+            asnyc : true,
+            params : [
+                openils.User.authtoken, 
+                formula.id(), 
+                dojo.string.substitute(localeStrings.ACQ_DISTRIB_FORMULA_NAME_CLONE, [formula.name()])
+            ],
+            oncomplete : function(r) {
+                if(r = openils.Util.readResponse(r)) {
+                    location.href = oilsBasePath + '/conify/global/acq/distribution_formula/' + r;
+                }
+            }
+        }
+    );
 }
 
+openils.Util.addOnLoad(draw);
+
 function getItemCount(rowIndex, item) {
     if(!item) return '';
     var form = formCache[this.grid.store.getValue(item, "id")];
@@ -54,3 +79,156 @@
     return count;
 }
 
+function byName(node, name) {
+    return dojo.query('[name='+name+']', node)[0];
+}
+
+function drawFormulaSummary() {
+    openils.Util.show('formula-entry-div');
+
+    var entries = pcrud.search('acqdfe', {formula: formulaId}, {order_by:{acqdfe : 'position'}});
+    formula = pcrud.retrieve('acqdf', formulaId);
+    formula.entries(entries);
+
+    dojo.byId('formula_head').innerHTML = formula.name();
+    dojo.byId('formula_head').onclick = function() {
+        var name = prompt(localeStrings.ACQ_DISTRIB_FORMULA_NAME_PROMPT, formula.name());
+        if(name && name != formula.name()) {
+            formula.name(name);
+            pcrud = new openils.PermaCrud();
+            pcrud.update(formula);
+            dojo.byId('formula_head').innerHTML = name;
+        }
+    }
+
+    dojo.forEach(entries, function(entry) { addEntry(entry); } );
+}
+
+function addEntry(entry) {
+
+    if(!entryTbody) {
+        entryTbody = dojo.byId('formula-entry-tbody');
+        entryTemplate = entryTbody.removeChild(dojo.byId('formula-entry-tempate'));
+        dndSource = new dojo.dnd.Source(entryTbody);
+        dndSource.selectAll(); 
+        dndSource.deleteSelectedNodes();
+        dndSource.clearItems();
+    }
+
+    if(!entry) {
+        entry = new fieldmapper.acqdfe();
+        entry.formula(formulaId);
+        entry.item_count(1);
+        entry.owning_lib(openils.User.user.ws_ou());
+        entry.id(virtualId--);
+        entry.isnew(true);
+        formula.entries().push(entry);
+    }
+
+    var row = entryTbody.appendChild(entryTemplate.cloneNode(true));
+    row.setAttribute('entry', entry.id());
+    dndSource.insertNodes(false, [row]);
+    byName(row, 'delete').onclick = function() {
+        entry.isdeleted(true);
+        entryTbody.removeChild(row);
+        dndSource.sync();
+    };
+
+    dojo.forEach(
+        ['owning_lib', 'location', 'item_count'],
+        function(field) {
+            new openils.widget.AutoFieldWidget({
+                forceSync : true,
+                fmField : field, 
+                fmObject : entry,
+                fmClass : 'acqdfe',
+                parentNode : byName(row, field),
+                orgDefaultsToWs : true,
+                orgLimitPerms : ['ADMIN_ACQ_DISTRIB_FORMULA'],
+                widgetClass : (field == 'item_count') ? 'dijit.form.NumberSpinner' : null,
+                dijitArgs : (field == 'item_count') ? {min:1, places:0} : null
+            }).build(
+                function(w, ww) {
+                    dojo.connect(w, 'onChange', 
+                        function(newVal) {
+                            entry[field]( newVal );
+                            entry.ischanged(true);
+                        }
+                    )
+                }
+            );
+        }
+    );
+}
+
+function saveFormula() {
+    var pos = 1;
+    var updatedEntries = [];
+    var deletedEntries = [];
+
+    // remove deleted entries from consideration for collision protection
+    for(var i = 0; i < formula.entries().length; i++) {
+        if(formula.entries()[i].isdeleted())
+            deletedEntries.push(formula.entries().splice(i--, 1)[0])
+    }
+
+    // update entry positions and create temporary collision avoidance entries
+    dojo.forEach(
+        dndSource.getAllNodes(),
+        function(node) {
+
+            var entryId = node.getAttribute('entry');
+            var entry = formula.entries().filter(function(e) {return (e.id() == entryId)})[0];
+
+            if(entry.position() != pos) {
+
+                // update the position
+                var changedEntry = entry.clone();
+                changedEntry.position(pos);
+                changedEntry.ischanged(true);
+                updatedEntries.push(changedEntry);
+
+                // clear the virtual ID
+                if(changedEntry.isnew())
+                    changedEntry.id(null); 
+
+                var oldEntry = formula.entries().filter(function(e) {return (e.position() == pos)})[0];
+
+                if(oldEntry) {
+                    // move the entry currently in that spot temporarily into negative territory
+                    var moveMe = oldEntry.clone();
+                    moveMe.ischanged(true);
+                    moveMe.position(moveMe.position() * -1); 
+                    updatedEntries.unshift(moveMe);
+                }
+            }
+            pos++;
+        }
+    );
+
+    // finally, for every entry that changed w/o changing position
+    // throw it on the list for update
+    dojo.forEach(
+        formula.entries(),
+        function(entry) {
+            if(entry.ischanged() && !entry.isdeleted() && !entry.isnew()) {
+                if(updatedEntries.filter(function(e) { return (e.id() == entry.id()) }).length == 0)
+                    updatedEntries.push(entry);
+            }
+        }
+    );
+
+    updatedEntries = deletedEntries.concat(updatedEntries);
+    if(updatedEntries.length) {
+        pcrud = new openils.PermaCrud();
+        try { 
+            pcrud.apply(updatedEntries);
+        } catch(E) {
+            alert('error updating: ' + E);
+            return;
+        }
+        location.href = location.href;
+    }
+}
+
+

Copied: branches/serials-integration/Open-ILS/web/js/ui/default/conify/global/asset/copy_template.js (from rev 17886, trunk/Open-ILS/web/js/ui/default/conify/global/asset/copy_template.js)
===================================================================
--- branches/serials-integration/Open-ILS/web/js/ui/default/conify/global/asset/copy_template.js	                        (rev 0)
+++ branches/serials-integration/Open-ILS/web/js/ui/default/conify/global/asset/copy_template.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -0,0 +1,60 @@
+dojo.require("dojo.data.ItemFileWriteStore");
+dojo.require("dijit.form.CurrencyTextBox");
+dojo.require("dijit.form.FilteringSelect");
+dojo.require("openils.widget.AutoGrid");
+dojo.require("openils.PermaCrud");
+dojo.require("openils.widget.OrgUnitFilteringSelect");
+
+var pcrud;
+var actOwner;
+var actList;
+
+function actInit() {
+    pcrud = new openils.PermaCrud();
+
+    new openils.User().buildPermOrgSelector(
+        "ADMIN_ASSET_COPY_TEMPLATE",
+        actOwnerSelect,
+        null,
+        function() {
+            dojo.connect(
+                actOwnerSelect,
+                "onChange",
+                function() {
+                    actOwner = fieldmapper.aou.findOrgUnit(this.attr("value"));
+                    actGrid.resetStore();
+                    buildActGrid();
+                }
+            );
+            buildActGrid();
+        }
+    );
+}
+
+function buildActGrid() {
+    if (!actOwner)
+        actOwner = fieldmapper.aou.findOrgUnit(openils.User.user.ws_ou());
+
+    pcrud.search(
+        "act", {
+            "owning_lib": fieldmapper.aou.orgNodeTrail(actOwner, true /* asId */)
+        }, {
+            "async": true,
+            "onresponse": function(r) {
+                if ((actList = openils.Util.readResponse(r))) {
+                    actList = openils.Util.objectSort(actList);
+                    actList.forEach(
+                        function(o) {
+                            actGrid.store.newItem(act.toStoreItem(o));
+                        }
+                    );
+                }
+            },
+            "oncomplete": function() {
+                actGrid.hideLoadProgressIndicator();
+            }
+        }
+    );
+}
+
+openils.Util.addOnLoad(actInit);

Copied: branches/serials-integration/Open-ILS/web/js/ui/default/serial (from rev 17886, trunk/Open-ILS/web/js/ui/default/serial)

Modified: branches/serials-integration/Open-ILS/web/js/ui/default/vandelay/vandelay.js
===================================================================
--- branches/serials-integration/Open-ILS/web/js/ui/default/vandelay/vandelay.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/js/ui/default/vandelay/vandelay.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -569,7 +569,7 @@
 }
 
 function vlFormatViewMatchMARC(id) {
-    return '<a href="javascript:void(0);" onclick="vlLoadMARCHtml(' + id + ', false, '+
+    return '<a href="javascript:void(0);" onclick="vlLoadMARCHtml(' + id + ', true, '+
         'function(){displayGlobalDiv(\'vl-match-div\');});">' + this.name + '</a>';
 }
 
@@ -1055,6 +1055,13 @@
     netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
     win = window.open('/xul/server/cat/marcedit.xul'); // XXX version?
 
+    var type;
+    if (currentType == 'bib') {
+        type = 'bre';
+    } else {
+        type = 'are';
+    }
+
     function onsave(r) {
         // after the record is saved, reload the HTML display
         var stat = r.recv().content();
@@ -1066,7 +1073,7 @@
     }
 
     win.xulG = {
-        record : {marc : rec.marc()},
+        record : {marc : rec.marc(), "rtype": type},
         save : {
             label: dojo.byId('vl-marc-edit-save-label').innerHTML,
             func: function(xmlString) {
@@ -1163,7 +1170,7 @@
 
     var store = new dojo.data.ItemFileReadStore({data:_data});
     attrEditorGrid.setStore(store);
-    dojo.connect(attrEditorGrid, 'onRowDblClick', onAttrEditorClick);
+    attrEditorGrid.onRowDblClick = onAttrEditorClick;
     attrEditorGrid.update();
 }
 

Modified: branches/serials-integration/Open-ILS/web/opac/common/js/config.js
===================================================================
--- branches/serials-integration/Open-ILS/web/opac/common/js/config.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/opac/common/js/config.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -356,6 +356,7 @@
 var FETCH_COPIES_FROM_VOLUME	= 'open-ils.search:open-ils.search.asset.copy.retrieve_by_cn_label:1';
 var FETCH_VOLUME_BY_INFO		= 'open-ils.search:open-ils.search.call_number.retrieve_by_info'; /* XXX staff method? */
 var FETCH_VOLUME					= 'open-ils.search:open-ils.search.asset.call_number.retrieve';
+var FETCH_ISSUANCE					= 'open-ils.serial:open-ils.serial.issuance.pub_fleshed.batch.retrieve';
 var FETCH_COPY_LOCATIONS		= 'open-ils.circ:open-ils.circ.copy_location.retrieve.all';
 var FETCH_COPY_NOTES				= 'open-ils.circ:open-ils.circ.copy_note.retrieve.all';
 var FETCH_COPY_STAT_CATS		= 'open-ils.circ:open-ils.circ.asset.stat_cat_entries.fleshed.retrieve_by_copy';

Modified: branches/serials-integration/Open-ILS/web/opac/locale/en-US/lang.dtd
===================================================================
--- branches/serials-integration/Open-ILS/web/opac/locale/en-US/lang.dtd	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/opac/locale/en-US/lang.dtd	2010-10-18 13:46:56 UTC (rev 18371)
@@ -316,6 +316,10 @@
 <!ENTITY staff.cat.opac.view_holds.label "View Holds">
 <!ENTITY staff.cat.opac.view_orders.accesskey "r">
 <!ENTITY staff.cat.opac.view_orders.label "View/Place Orders">
+<!ENTITY staff.cat.opac.alt_serial.accesskey "a">
+<!ENTITY staff.cat.opac.alt_serial.label "Alternate Serial Control">
+<!ENTITY staff.cat.opac.batch_receive.accesskey "i">
+<!ENTITY staff.cat.opac.batch_receive.label "Serials Batch Receive">
 <!ENTITY staff.cat.popup.add_to_bucket "Add to Bucket">
 <!ENTITY staff.cat.popup.add_to_bucket.key "">
 <!ENTITY staff.cat.popup.browse.record.tab.key "">
@@ -680,6 +684,8 @@
 <!ENTITY staff.main.menu.admin.local_admin.hold_matrix_matchpoint.label "Hold Policies">
 <!ENTITY staff.main.menu.admin.local_admin.work_log.label "Work Log">
 <!ENTITY staff.main.menu.admin.local_admin.work_log.accesskey "W">
+<!ENTITY staff.main.menu.admin.local_admin.copy_template.label "Copy Template Editor">
+<!ENTITY staff.main.menu.admin.local_admin.copy_template.accesskey "T">
 <!ENTITY staff.main.menu.admin.local_admin.patrons_due_refunds.label "Patrons with Negative Balances">
 <!ENTITY staff.main.menu.admin.local_admin.patrons_due_refunds.accesskey "N">
 
@@ -695,6 +701,10 @@
 <!ENTITY staff.main.menu.admin.server_admin.conify.circulation_modifier.label "Circulation Modifiers">
 <!ENTITY staff.main.menu.admin.server_admin.conify.org_unit_setting_type "Organization Unit Setting Types">
 <!ENTITY staff.main.menu.admin.server_admin.conify.usr_setting_type "User Setting Types">
+<!ENTITY staff.main.menu.admin.server_admin.conify.config_rule_circ_duration "Circulation Duration Rules">
+<!ENTITY staff.main.menu.admin.server_admin.conify.config_rule_recurring_fine "Circulation Recurring Fine Rules">
+<!ENTITY staff.main.menu.admin.server_admin.conify.config_rule_max_fine "Circulation Max Fine Rules">
+<!ENTITY staff.main.menu.admin.server_admin.conify.config_rule_age_hold_protect "Age Hold Protect Rules">
 <!ENTITY staff.main.menu.admin.server_admin.conify.global_flag.label "Global Flags">
 
 <!ENTITY staff.main.menu.admin.server_admin.acq.label "Acquisitions">
@@ -747,6 +757,19 @@
 <!ENTITY staff.main.menu.admin.server_admin.booking.resource_attr_map.label "Resource Attribute Maps">
 <!ENTITY staff.main.menu.admin.server_admin.booking.resource_attr_map.accesskey "M">
 
+<!ENTITY staff.main.menu.admin.server_admin.serial.label "Serials">
+<!ENTITY staff.main.menu.admin.server_admin.serial.accesskey "S">
+<!ENTITY staff.main.menu.admin.server_admin.serial.subscription.label "Subscriptions">
+<!ENTITY staff.main.menu.admin.server_admin.serial.subscription.accesskey "S">
+<!ENTITY staff.main.menu.admin.server_admin.serial.distribution.label "Distributions">
+<!ENTITY staff.main.menu.admin.server_admin.serial.distribution.accesskey "D">
+<!ENTITY staff.main.menu.admin.server_admin.serial.stream.label "Streams">
+<!ENTITY staff.main.menu.admin.server_admin.serial.stream.accesskey "T">
+<!ENTITY staff.main.menu.admin.server_admin.serial.routing_list_user.label "Routing List Users">
+<!ENTITY staff.main.menu.admin.server_admin.serial.routing_list_user.accesskey "R">
+<!ENTITY staff.main.menu.admin.server_admin.serial.caption_and_pattern.label "Captions and Patterns">
+<!ENTITY staff.main.menu.admin.server_admin.serial.caption_and_pattern.accesskey "C">
+
 <!ENTITY staff.main.menu.admin.developer.label "For developers...">
 <!ENTITY staff.main.menu.admin.download_patrons.accesskey "D">
 <!ENTITY staff.main.menu.admin.download_patrons.label "Download Offline Patron List">
@@ -789,6 +812,8 @@
 <!ENTITY staff.main.menu.cat.add_copy.label "Add Item">
 <!ENTITY staff.main.menu.cat.add_volume.key "V">
 <!ENTITY staff.main.menu.cat.add_volume.label "Add Volume">
+<!ENTITY staff.main.menu.cat.authority_manage.accesskey "t">
+<!ENTITY staff.main.menu.cat.authority_manage.label "Manage Authorities">
 <!ENTITY staff.main.menu.cat.bib_search.accesskey "S">
 <!ENTITY staff.main.menu.cat.bib_search.label "Search the Catalog">
 <!ENTITY staff.main.menu.cat.bib_status.key "B">
@@ -850,6 +875,11 @@
 <!ENTITY staff.main.menu.acq.create_invoice.label "Create Invoice">
 <!ENTITY staff.main.menu.acq.create_invoice.accesskey "V">
 
+<!ENTITY staff.main.menu.serial.label "Serials">
+<!ENTITY staff.main.menu.serial.accesskey "S">
+<!ENTITY staff.main.menu.serial.batch_receive.label "Batch Receive">
+<!ENTITY staff.main.menu.serial.batch_receive.accesskey "B">
+
 <!ENTITY staff.main.menu.booking.label "Booking">
 <!ENTITY staff.main.menu.booking.accesskey "B">
 <!ENTITY staff.main.menu.booking.reservation.label_alt "Create or Cancel Reservations">
@@ -1543,6 +1573,9 @@
 <!ENTITY staff.serial.mfhd_menu.add.label "Add MFHD Record">
 <!ENTITY staff.serial.mfhd_menu.edit.label "Edit MFHD Record">
 <!ENTITY staff.serial.mfhd_menu.delete.label "Delete MFHD Record">
+<!ENTITY staff.serial.scap_editor.pattern_wizard "Pattern Code Wizard">
+<!ENTITY staff.serial.scap_editor.pattern_wizard.accesskey "Z">
+<!ENTITY staff.serial.scap_editor.modify.accesskey "M">
 <!ENTITY staff.serial.scap_editor.modify "Modify Caption and Pattern(s)">
 <!ENTITY staff.serial.scap_editor.modify.accesskey "M">
 <!ENTITY staff.serial.scap_editor.create "Create Caption and Pattern(s)">
@@ -1574,6 +1607,38 @@
 <!ENTITY staff.serial.ssub_editor.create.accesskey "C">
 <!ENTITY staff.serial.ssub_editor.notes "Subscription Notes">
 <!ENTITY staff.serial.ssub_editor.notes.accesskey "N">
+
+<!ENTITY staff.serial.batch_receive "Batch Receive">
+<!ENTITY staff.serial.batch_receive.bib_search_term "Enter an identifier for a bibliographic record:">
+<!ENTITY staff.serial.batch_receive.bib_search_term.accesskey "B">
+<!ENTITY staff.serial.batch_receive.find_record "Find Record">
+<!ENTITY staff.serial.batch_receive.find_record.accesskey "F">
+<!ENTITY staff.serial.batch_receive.title "Title:">
+<!ENTITY staff.serial.batch_receive.author "Author:">
+<!ENTITY staff.serial.batch_receive.fulfilling_sub "Fulfilling Subscription:">
+<!ENTITY staff.serial.batch_receive.choose_sub "Choose a Subscription:">
+<!ENTITY staff.serial.batch_receive.choose_sub.accesskey "S">
+<!ENTITY staff.serial.batch_receive.choose_issuance "Choose an Issuance:">
+<!ENTITY staff.serial.batch_receive.choose_issuance.accesskey "I">
+<!ENTITY staff.serial.batch_receive.next "Next">
+<!ENTITY staff.serial.batch_receive.next.accesskey "N">
+<!ENTITY staff.serial.batch_receive.issuance "Issuance:">
+<!ENTITY staff.serial.batch_receive.no_items "There are no items to receive for this subscription.">
+<!ENTITY staff.serial.batch_receive.org_unit "Org Unit">
+<!ENTITY staff.serial.batch_receive.barcode "Barcode">
+<!ENTITY staff.serial.batch_receive.circ_modifier "Circ Modifier">
+<!ENTITY staff.serial.batch_receive.call_number "Call Number">
+<!ENTITY staff.serial.batch_receive.note "Note">
+<!ENTITY staff.serial.batch_receive.location "Copy Location">
+<!ENTITY staff.serial.batch_receive.price "Price">
+<!ENTITY staff.serial.batch_receive.receive "Receive?">
+<!ENTITY staff.serial.batch_receive.auto_generate "Auto-generate?">
+<!ENTITY staff.serial.batch_receive.recieve_selected "Receive Selected Items">
+<!ENTITY staff.serial.batch_receive.start_over "Start Over">
+<!ENTITY staff.serial.batch_receive.start_over.accesskey "O">
+<!ENTITY staff.serial.batch_receive.with_units "Create Units For Received Items">
+<!ENTITY staff.serial.batch_receive.with_units.accesskey "U">
+
 <!ENTITY staff.survey.wizard.page1 "Initial Settings">
 <!ENTITY staff.survey.wizard.page2 "Add Questions for Survey:">
 <!ENTITY staff.survey.wizard.title "Add a Survey Wizard">
@@ -1765,10 +1830,14 @@
 <!ENTITY staff.server.admin.copy_locations.editor.help "Help">
 <!ENTITY staff.server.admin.copy_locations.editor.opac_visible "OPAC Visible">
 <!ENTITY staff.server.admin.copy_locations.editor.circulate "Circulate">
+<!ENTITY staff.server.admin.copy_locations.editor.create "Create">
 <!ENTITY staff.server.admin.copy_locations.editor.edit "Edit">
 <!ENTITY staff.server.admin.copy_locations.editor.delete "Delete">
 <!ENTITY staff.server.admin.copy_locations.editor.help.holdable "If a copy location is 'Holdable', copies in that location may have holds placed on them.">
 <!ENTITY staff.server.admin.copy_locations.editor.delete.confirm "Are you sure you wish to delete the selected copy location?  Note: If copies are currently attached to this location, the delete operation will fail.">
+<!ENTITY staff.server.admin.copy_locations.editor.prefix "Label prefix">
+<!ENTITY staff.server.admin.copy_locations.editor.suffix "Label suffix">
+<!ENTITY staff.server.admin.copy_locations.editor.welcome "Welcome">
 <!ENTITY staff.server.admin.copy_locations.submit "Submit">
 <!ENTITY staff.server.admin.copy_locations.cancel "Cancel">
 <!ENTITY staff.server.admin.copy_locations.update_success "Update Succeeded">
@@ -2249,11 +2318,17 @@
 <!ENTITY staff.cat.bib_brief.author.accesskey "">
 <!ENTITY staff.cat.bib_brief.edition.label "Edition:">
 <!ENTITY staff.cat.bib_brief.edition.accesskey "">
-<!ENTITY staff.cat.bib_brief.pub_date.label "Publication Date:">
+<!ENTITY staff.cat.bib_brief.pub_date.label "Pub Date:">
 <!ENTITY staff.cat.bib_brief.pub_date.accesskey "">
+<!ENTITY staff.cat.bib_brief.call_number.label "Bib Call #:">
+<!ENTITY staff.cat.bib_brief.call_number.accesskey "">
 <!-- "TCN" is an abbreviation for "title control number" -->
 <!ENTITY staff.cat.bib_brief.title_control_number.label "TCN:">
 <!ENTITY staff.cat.bib_brief.title_control_number.accesskey "">
+<!ENTITY staff.cat.bib_brief.biblio_record_entry_id.label "Record ID:">
+<!ENTITY staff.cat.bib_brief.biblio_record_entry_id.accesskey "">
+<!ENTITY staff.cat.bib_brief.biblio_record_entry_owner.label "Record Owner:">
+<!ENTITY staff.cat.bib_brief.biblio_record_entry_owner.accesskey "">
 <!ENTITY staff.cat.bib_brief.created_by.label "Created By:">
 <!ENTITY staff.cat.bib_brief.created_by.accesskey "">
 <!ENTITY staff.cat.bib_brief.last_edited_by.label "Last Edited By:">
@@ -2362,7 +2437,8 @@
 <!ENTITY staff.cat.copy_browser.actions.cmd_refresh_list.label "Refresh Listing">
 <!ENTITY staff.cat.copy_browser.actions.cmd_refresh_list.accesskey "R">
 <!ENTITY staff.cat.copy_browser.holdings_maintenance.caption "Holdings Maintenance">
-<!ENTITY staff.cat.copy_browser.holdings_maintenance.legend "Green in the list below means the library has volumes for this record.">
+<!ENTITY staff.cat.copy_browser.holdings_maintenance.legend "Green and bold in the list below means the library has volumes for this record.">
+<!ENTITY staff.cat.copy_browser.holdings_maintenance.depth_filter_menu "Limit:">
 <!ENTITY staff.cat.copy_browser.holdings_maintenance.consortial_total "Consortial Total:">
 <!ENTITY staff.cat.copy_browser.holdings_maintenance.consortial_available "Available:">
 <!ENTITY staff.cat.copy_browser.holdings_maintenance.show_acns "Show Volumes">
@@ -2508,6 +2584,8 @@
 <!ENTITY staff.cat.marcedit.help.accesskey "H">
 <!ENTITY staff.cat.marcedit.caption.label "MARC Record">
 <!ENTITY staff.cat.marcedit.toggleFFE.label "Fixed Fields -- Record type: ">
+<!ENTITY staff.cat.marcedit.source.caption "Bibliographic source">
+<!ENTITY staff.cat.marcedit.source.submit.label "Update source">
 <!ENTITY staff.cat.marc_new.load.label "Load">
 <!ENTITY staff.cat.marc_new.load.accesskey "L">
 <!ENTITY staff.cat.marc_view.title "MARC View">
@@ -2599,16 +2677,19 @@
 <!ENTITY staff.cat.spine_labels.close_window.label "Close Window">
 <!ENTITY staff.cat.spine_labels.close_window.accesskey "C">
 <!ENTITY staff.cat.spine_labels.font_size.label "Font size (in points):">
+<!ENTITY staff.cat.spine_labels.font_weight.label 'Font weight ("normal" or "bold"):'>
 <!ENTITY staff.cat.spine_labels.spine_label.label "Spine Label">
 <!ENTITY staff.cat.spine_labels.spine_label.left_margin.label "Left Margin (in characters):">
 <!ENTITY staff.cat.spine_labels.spine_label.label_width.label "Label Width (in characters):">
 <!ENTITY staff.cat.spine_labels.spine_label.label_length.label "Label Length (in lines):">
 <!ENTITY staff.cat.spine_labels.pocket_label.label "Pocket Label">
+<!ENTITY staff.cat.spine_labels.pocket_label.enabled.label "Enabled">
 <!ENTITY staff.cat.spine_labels.pocket_label.middle_margin.label "Middle Margin (in characters):">
 <!ENTITY staff.cat.spine_labels.pocket_label.label_width.label "Label Width (in characters):">
 <!ENTITY staff.cat.spine_labels.pocket_label.label_length.label "Label Length (in lines):">
 <!ENTITY staff.cat.spine_labels.pocket_label.title.label "Include Title (wraps on word at label width)">
 <!ENTITY staff.cat.spine_labels.on_line.label "On line:">
+<!ENTITY staff.cat.spine_labels.pocket_label.include_author.label "Include Author">
 <!ENTITY staff.cat.spine_labels.pocket_label.include_title.label "Include Title (segment after wrapping)">
 <!ENTITY staff.cat.spine_labels.indent_title.label "Indent a space?">
 <!ENTITY staff.cat.spine_labels.inc_call_number.label "Include Call Number">
@@ -2908,6 +2989,8 @@
 <!ENTITY staff.patron.holds_overlay.holds_export.label "Export">
 <!ENTITY staff.patron.holds_overlay.print.label "Print">
 <!ENTITY staff.patron.holds_overlay.print.accesskey "P">
+<!ENTITY staff.patron.holds_overlay.print_full_pull_list.label "Print Full Pull List">
+<!ENTITY staff.patron.holds_overlay.print_full_pull_list.accesskey "u">
 <!ENTITY staff.patron.holds_overlay.place_hold.label "Place Hold">
 <!ENTITY staff.patron.holds_overlay.place_hold.accesskey "H">
 <!ENTITY staff.patron.holds_overlay.show_cancelled_holds.label "Show Cancelled Holds">
@@ -3246,7 +3329,8 @@
 <!ENTITY staff.circ.alternate_copy_summary.Alert.label "Alert">
 <!ENTITY staff.circ.alternate_copy_summary.Alternate_View.label "Alternate View">
 <!ENTITY staff.circ.alternate_copy_summary.Barcode.label "Barcode">
-<!ENTITY staff.circ.alternate_copy_summary.Call_Number.label "Call Number">
+<!ENTITY staff.circ.alternate_copy_summary.Call_Number.label "Item Call #">
+<!ENTITY staff.circ.alternate_copy_summary.Call_Number.accesskey "">
 <!ENTITY staff.circ.alternate_copy_summary.Cataloging_Info.label "Cataloging Info">
 <!ENTITY staff.circ.alternate_copy_summary.Cataloging_Info.accesskey "I">
 <!ENTITY staff.circ.alternate_copy_summary.Checkin_Scan_Time.label "Checkin Scan Time">
@@ -3310,6 +3394,13 @@
 <!ENTITY staff.util.timestamp_dialog.apply_btn.accesskey "A">
 <!ENTITY staff.printing.set_default "Set Default Printer and Print Test Page">
 <!ENTITY staff.printing.page_settings "Page Settings">
+<!ENTITY staff.printing.context.header "Printer Context">
+<!ENTITY staff.printing.context.desc "Different printer settings may be configured for different contexts within the staff client (such as circulation, label printing, etc.).  If settings have not been made for a given context, the staff client will fall back on the 'default' context.">
+<!ENTITY staff.printing.context.radio.default.label "Default">
+<!ENTITY staff.printing.context.radio.receipt.label "Receipt">
+<!ENTITY staff.printing.context.radio.label.label "Label">
+<!ENTITY staff.printing.context.radio.mail.label "Mail">
+<!ENTITY staff.printing.context.radio.offline.label "Offline">
 <!ENTITY staff.printing.normal_settings.header "Normal Settings">
 <!ENTITY staff.printing.advanced_settings.header "Advanced Settings">
 <!ENTITY staff.printing.advanced.mozilla_print "Use default print strategy (Mozilla Print)">

Modified: branches/serials-integration/Open-ILS/web/opac/locale/en-US/opac.dtd
===================================================================
--- branches/serials-integration/Open-ILS/web/opac/locale/en-US/opac.dtd	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/opac/locale/en-US/opac.dtd	2010-10-18 13:46:56 UTC (rev 18371)
@@ -592,6 +592,7 @@
 <!ENTITY common.isbn.label "ISBN:">
 <!ENTITY common.issn.label "ISSN:">
 <!ENTITY common.copy.barcode.label "Copy Barcode:">
+<!ENTITY common.issuance_label.label "Issuance Label:">
 <!ENTITY common.hold.place "Place hold for my account">
 <!ENTITY common.hold.check "Checking for possibility of hold fulfillment...">
 <!ENTITY common.hold.create "Create / Edit a Hold">
@@ -599,6 +600,7 @@
 <!ENTITY common.hold.type.label "Hold Type:">
 <!ENTITY common.hold.volume "Volume Hold">
 <!ENTITY common.hold.copy "Copy Hold">
+<!ENTITY common.hold.issuance "Issuance Hold">
 <!ENTITY common.hold.advanced "Advanced Hold Options">
 <!ENTITY common.hold.delivery "Please select a physical location where your hold can be delivered.">
 <!ENTITY common.hold.checked_out "This item is already checked out.">

Modified: branches/serials-integration/Open-ILS/web/opac/skin/craftsman/js/rdetail.js
===================================================================
--- branches/serials-integration/Open-ILS/web/opac/skin/craftsman/js/rdetail.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/opac/skin/craftsman/js/rdetail.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -238,7 +238,7 @@
 	dojo.require('openils.PermaCrud');
 
 	win.xulG = {
-		"record": {"marc": rec.marc()},
+		"record": {"marc": rec.marc(), "rtype": "sre"},
 		"save": {
 			"label": opac_strings.SAVE_MFHD_LABEL,
 			"func": function(xmlString) {

Modified: branches/serials-integration/Open-ILS/web/opac/skin/craftsman/xml/rdetail/rdetail_extras.xml
===================================================================
--- branches/serials-integration/Open-ILS/web/opac/skin/craftsman/xml/rdetail/rdetail_extras.xml	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/opac/skin/craftsman/xml/rdetail/rdetail_extras.xml	2010-10-18 13:46:56 UTC (rev 18371)
@@ -84,4 +84,10 @@
 	<div id='rdetail_preview_full_text' class='hide_me'>&rdetail.extras.preview.fulltext;</div>
 	<div id='rdetail_preview_title' class='hide_me'>&rdetail.extras.preview.title;</div>
 	<div id='rdetail_preview_badge' class='hide_me'>&rdetail.extras.preview.badge;</div>
+
+    <!-- ChiliFresh setup -->
+    <script language='javascript' type='text/javascript'>
+        var chilifresh = false;
+    </script>
+
 </div>

Modified: branches/serials-integration/Open-ILS/web/opac/skin/craftsman/xml/result/result_table.xml
===================================================================
--- branches/serials-integration/Open-ILS/web/opac/skin/craftsman/xml/result/result_table.xml	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/opac/skin/craftsman/xml/result/result_table.xml	2010-10-18 13:46:56 UTC (rev 18371)
@@ -141,6 +141,11 @@
 		config.names.result.format_pic = 'format_pic'
 	</script>
 
+    <!-- ChiliFresh setup -->
+    <script language='javascript' type='text/javascript'>
+        var chilifresh = false;
+    </script>
+
 </div>
 
 

Modified: branches/serials-integration/Open-ILS/web/opac/skin/default/js/container.js
===================================================================
--- branches/serials-integration/Open-ILS/web/opac/skin/default/js/container.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/opac/skin/default/js/container.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -32,6 +32,7 @@
 
 function containerCreate( name, pub, callback, args ) {
 
+    fieldmapper.IDL.load(['cbreb']);
 	var container = new cbreb();
 	container.btype('bookbag');
 	container.owner( G.user.id() );
@@ -51,6 +52,7 @@
 
 function containerCreateItem( containerId, target, callback, args ) {
 
+    fieldmapper.IDL.load(['cbrebi']);
 	var item = new cbrebi();
 	item.target_biblio_record_entry(target);
 	item.bucket(containerId);

Modified: branches/serials-integration/Open-ILS/web/opac/skin/default/js/holds.js
===================================================================
--- branches/serials-integration/Open-ILS/web/opac/skin/default/js/holds.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/opac/skin/default/js/holds.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -11,6 +11,16 @@
 var noEmailMessage;
 var noEmailMessageXUL;
 
+var holdTargetTypeMap = {
+    M : 'metarecord',
+    T : 'record',
+    V : 'volume',
+    I : 'issuance',
+    C : 'copy'
+};
+
+
+
 function holdsHandleStaff() {
 
     // if we know the recipient's barcode, use it
@@ -180,21 +190,7 @@
 	var args = (oargs) ? oargs : {};
 	args.type = hold.hold_type();
 	var target = hold.target();
-
-	switch(args.type) {
-		case 'M':
-			args.metarecord = target;
-			break;
-		case 'T':
-			args.record = target;
-			break;
-		case 'V':
-			args.volume = target;
-			break;
-		case 'C':
-			args.copy = target;
-			break;
-	}
+    args[holdTargetTypeMap[args.type]] = target;
 	return args;
 }
 
@@ -229,6 +225,9 @@
 		if( type == 'V' ) {
 			_h_set_vol(args, doneCallback);
 
+        } else if( type == 'I' ) {
+            _h_set_issuance(args, doneCallback);
+
 		} else {
 			if( type == 'T' ) {
 				_h_set_rec(args, doneCallback);
@@ -263,6 +262,28 @@
 	}
 }
 
+function _h_set_issuance(args, doneCallback) {
+
+	if( args.issuanceObject ) {
+		args.issuance = args.issuanceObject.id();
+		args.record = args.issuanceObject.subscription().record_entry();
+		_h_set_rec(args, doneCallback);
+
+	} else {
+
+		var vreq = new Request(FETCH_ISSUANCE, [args.issuance]);
+		vreq.callback(
+			function(r) {
+				var issuance = r.getResultObject()[0];
+				args.issuanceObject = issuance;
+				args.record = issuance.subscription().record_entry();
+				_h_set_rec(args, doneCallback);
+			}
+		);
+		vreq.send();
+	}
+}
+
 function _h_set_rec(args, doneCallback) {
 
 	if(args.recordObject) 
@@ -395,8 +416,14 @@
 	appendClear($('holds_title'), text(rec.title()));
 	appendClear($('holds_author'), text(rec.author()));
 
-	if( holdArgs.type == 'V' || holdArgs.type == 'C' ) {
+    if( holdArgs.type == 'I' ) {
+		unHideMe($('holds_type_row'));
+        unHideMe($('holds_is_issuance'));
+        unHideMe($('holds_issuance_row'));
+        appendClear($('holds_issuance_label'), text(holdArgs.issuanceObject.label()));
 
+    } else if( holdArgs.type == 'V' || holdArgs.type == 'C' ) {
+
 		unHideMe($('holds_type_row'));
 		unHideMe($('holds_cn_row'));
 		appendClear($('holds_cn'), text(holdArgs.volumeObject.label()));
@@ -416,6 +443,7 @@
 		hideMe($('holds_type_row'));
 		hideMe($('holds_copy_row'));
 		hideMe($('holds_cn_row'));
+		hideMe($('holds_issuance_row'));
 	}
 
 	removeChildren($('holds_format'));
@@ -759,6 +787,7 @@
 		return;
 	}
 
+    fieldmapper.IDL.load(['ahr']);
 	var hold = new ahr();
 	if(holdArgs.editHold) {
 		hold = holdArgs.editHold;
@@ -782,21 +811,8 @@
 	else
 		hold.email_notify(0);
 
-	var target;
+	var target = holdArgs[holdTargetTypeMap[holdArgs.type]];
 
-	switch(holdArgs.type) {
-		case 'M':
-			target = holdArgs.metarecord; break;
-		case 'T':
-			target = holdArgs.record; break;
-		case 'V':
-			target = holdArgs.volume; break;
-		case 'C':
-			target = holdArgs.copy; break;
-	}
-
-
-
 	hold.pickup_lib(org); 
 	//hold.request_lib(org); 
 	hold.requestor(holdArgs.requestor.id());

Modified: branches/serials-integration/Open-ILS/web/opac/skin/default/js/rdetail.js
===================================================================
--- branches/serials-integration/Open-ILS/web/opac/skin/default/js/rdetail.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/opac/skin/default/js/rdetail.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -155,7 +155,11 @@
     }
 
 
-	if (rdetailDisplaySerialHoldings) {
+	if (rdetailDisplaySerialHoldings && (
+        isXUL() || !fetchOrgSettingDefault(
+            getLocation(), "opac.fully_compressed_serial_holdings")
+        )
+    ) {
 		var req = new Request(FETCH_MFHD_SUMMARY, getRid());
 		req.callback(_holdingsDraw);
 		req.send();
@@ -241,7 +245,7 @@
 	dojo.require('openils.PermaCrud');
 
 	win.xulG = {
-		"record": {"marc": rec.marc()},
+		"record": {"marc": rec.marc(), "rtype": "sre"},
 		"save": {
 			"label": opac_strings.SAVE_MFHD_LABEL,
 			"func": function(xmlString) {
@@ -353,6 +357,10 @@
 		var mfhd_edit = new dijit.Menu({});
 		new dijit.MenuItem({onClick: function(){loadMarcEditor(holdings.sre_id())}, label:opac_strings.EDIT_MFHD_RECORD}).placeAt(mfhd_edit, "first");
 		new dijit.MenuItem({onClick:function(){
+			// Avoid accidental deletion of MFHD records
+			if (!confirm(opac_strings.DELETE_MFHD_CONFIRM)) {
+				return;
+			}
 			var pcrud = new openils.PermaCrud({"authtoken": G.user.session});
 			var mfhd_rec = pcrud.retrieve("sre", holdings.sre_id());
 			if (mfhd_rec) {
@@ -1160,3 +1168,37 @@
 
 }
 
+function rdetailDrawExpandedHoldings(anchor, bibid, type) {
+    anchor.innerHTML = "Hide holdings"; /* XXX i18n */
+    anchor.oldonclick = anchor.onclick;
+    anchor.onclick = function() { anchor.onclick = anchor.oldonclick; anchor.innerHTML = "Show holdings"; dojo.empty(target); };
+
+    var offsets = {"basic": 0, "index": 0, "supplement": 0};
+    var limit = 10; /* XXX give user control over this? */
+    var target = dojo.query("[expanded_holdings='" + type + "']")[0];
+
+    function _load() {
+        dojo.empty(target);
+        fieldmapper.standardRequest(
+            ["open-ils.serial", "open-ils.serial.received_siss.retrieve.by_bib.atomic"], {
+                "params": [bibid, {"offset": offsets[type], "limit": limit}],
+                "async": true,
+                "oncomplete": function(r) {
+                    if (r = openils.Util.readResponse(r)) {
+                        offsets[type] += r.length;
+                        dojo.forEach(
+                            r, function(sum) {
+                                dojo.create("span", {"innerHTML": sum.label()}, target);
+                                dojo.create("br", null, target);
+                            }
+                        );
+                        /* XXX i18n */
+                        if (r.length == limit)
+                            dojo.create("a", {"style": "margin-top: 6px;", "innerHTML": "[More]", "onclick": _load}, target);
+                    }
+                }
+            }
+        );
+    }
+    _load();
+}

Modified: branches/serials-integration/Open-ILS/web/opac/skin/default/js/result_common.js
===================================================================
--- branches/serials-integration/Open-ILS/web/opac/skin/default/js/result_common.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/opac/skin/default/js/result_common.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -93,6 +93,12 @@
 	_debug('Search args: ' + js2JSON(args));
 	_debug('Raw query: ' + getTerm());
 
+	var atomfeed = "/opac/extras/opensearch/1.1/" + findOrgUnit(args.org_unit).shortname() + "/atom-full/" + getStype() + '?searchTerms=' + getTerm();
+	if (args.facets) { atomfeed += ' ' + args.facets; }
+	if (sort) { atomfeed += '&searchSort=' + sort; }
+	if (sortdir) { atomfeed += '&searchSortDir=' + sortdir; }
+	dojo.create('link', {"rel":"alternate", "href":atomfeed, "type":"application/atom+xml"}, dojo.query('head')[0]);
+
 	var req = new Request(method, args, getTerm(), 1);
 	req.callback(handler);
 	req.send();
@@ -433,6 +439,7 @@
 		zero based position the record should have in the display table */
 function resultDisplayRecord(rec, pos, is_mr) {
 
+    fieldmapper.IDL.load(['mvr']);
 	if(rec == null) rec = new mvr(); /* so the page won't die if there was an error */
 	recordsHandled++;
 	recordsCache.push(rec);

Modified: branches/serials-integration/Open-ILS/web/opac/skin/default/xml/common/holds.xml
===================================================================
--- branches/serials-integration/Open-ILS/web/opac/skin/default/xml/common/holds.xml	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/opac/skin/default/xml/common/holds.xml	2010-10-18 13:46:56 UTC (rev 18371)
@@ -62,10 +62,16 @@
 					<td class='holds_cell'><b id='holds_copy'/> </td>
 				</tr>
 
+				<tr class='hide_me' id='holds_issuance_row'>
+					<td class='holds_cell'>&common.issuance_label.label;</td>
+					<td class='holds_cell'><b id='holds_issuance_label'/> </td>
+				</tr>
+
 				<tr class='hide_me' id='holds_type_row'>
 					<td class='holds_cell'>&common.hold.type.label;</td>
 					<td class='holds_cell hide_me' id='holds_is_cn'><b>&common.hold.volume;</b></td>
 					<td class='holds_cell hide_me' id='holds_is_copy'><b>&common.hold.copy;</b></td>
+					<td class='holds_cell hide_me' id='holds_is_issuance'><b>&common.hold.issuance;</b></td>
 				</tr>
 
 				<tr>

Modified: branches/serials-integration/Open-ILS/web/opac/skin/default/xml/common/js_common.xml
===================================================================
--- branches/serials-integration/Open-ILS/web/opac/skin/default/xml/common/js_common.xml	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/opac/skin/default/xml/common/js_common.xml	2010-10-18 13:46:56 UTC (rev 18371)
@@ -7,16 +7,6 @@
 	<script language='javascript' src='<!--#echo var="OILS_JS_BASE"-->/slimtree.js' type='text/javascript'></script>
 
 	<script language='javascript' src='<!--#echo var="OILS_JS_BASE"-->/JSON_v1.js' type='text/javascript'></script>
-	<script language='javascript' src='<!--#echo var="OILS_JS_BASE"-->/fmcore.js' type='text/javascript'></script>
-	<script language='javascript' src='<!--#echo var="OILS_JS_BASE"-->/fmgen.js' type='text/javascript'></script>
-	<script language='javascript' src='<!--#echo var="OILS_JS_BASE"-->/opac_utils.js' type='text/javascript'></script>
-	<script language='javascript' src='<!--#echo var="OILS_JS_BASE"-->/<!--#echo var="locale"-->/OrgTree.js' type='text/javascript'></script>
-	<script language='javascript' src='<!--#echo var="OILS_JS_BASE"-->/<!--#echo var="locale"-->/FacetDefs.js' type='text/javascript'></script>
-	<script language='javascript' src='<!--#echo var="OILS_JS_BASE"-->/OrgLasso.js' type='text/javascript'></script>
-	<script language='javascript' src='<!--#echo var="OILS_JS_BASE"-->/org_utils.js' type='text/javascript'></script>
-	<script language='javascript' src='<!--#echo var="OILS_JS_BASE"-->/RemoteRequest.js' type='text/javascript'></script>
-	<script language='javascript' src='<!--#echo var="OILS_JS_BASE"-->/init.js' type='text/javascript'></script>
-	<script language='javascript' src='<!--#echo var="OILS_JS_BASE"-->/added_content.js' type='text/javascript'></script>
 
 	<!-- Some global js -->
 	<script language='javascript' type='text/javascript'>
@@ -42,27 +32,40 @@
 			getId("home_myopac_link").setAttribute("href", buildOPACLink({page:MYOPAC}, false, true));
 		}
 
-        <!--#if expr="$OILS_OPAC_FORCE_LOGIN_SSL"-->
-            forceLoginSSL = true;
-        <!--#endif -->
+		<!--#if expr="$OILS_OPAC_FORCE_LOGIN_SSL"-->
+			forceLoginSSL = true;
+		<!--#endif -->
 	</script>
 
 	<!-- enable Dojo date picker -->
 	<script language='javascript' type="text/javascript">
 
-		var djConfig = {parseOnLoad: true, isDebug: false}, lang, bidi;
-
 		var locale = location.href.replace( /.+opac\/([^\/]+)\/skin.+/, '$1' );
 		if (!locale) locale = '<!--#echo var="locale"-->';
 
-		djConfig.locale = locale.toLowerCase();
+		 var djConfig = {
+			 locale: locale.toLowerCase(),
+			 AutoIDL: ['aou','aout','pgt','lasso'],
+			 parseOnLoad: true,
+			 isDebug: false
+		 }, lang, bidi;
 
 	</script>
 
 	<script type="text/javascript" src='/js/dojo/dojo/dojo.js'></script>
 	<script type="text/javascript" src='/js/dojo/dojo/openils_dojo.js'></script>
-    <script type="text/javascript" src='/js/dojo/opensrf/opensrf.js'></script>
+	<script type="text/javascript" src='/js/dojo/opensrf/opensrf.js'></script>
+	<script type="text/javascript" src='/js/dojo/fieldmapper/AutoIDL.js'></script>
 
+	<script language='javascript' src='<!--#echo var="OILS_JS_BASE"-->/opac_utils.js' type='text/javascript'></script>
+	<script language='javascript' src='<!--#echo var="OILS_JS_BASE"-->/<!--#echo var="locale"-->/OrgTree.js' type='text/javascript'></script>
+	<script language='javascript' src='<!--#echo var="OILS_JS_BASE"-->/<!--#echo var="locale"-->/FacetDefs.js' type='text/javascript'></script>
+	<script language='javascript' src='<!--#echo var="OILS_JS_BASE"-->/OrgLasso.js' type='text/javascript'></script>
+	<script language='javascript' src='<!--#echo var="OILS_JS_BASE"-->/org_utils.js' type='text/javascript'></script>
+	<script language='javascript' src='<!--#echo var="OILS_JS_BASE"-->/RemoteRequest.js' type='text/javascript'></script>
+	<script language='javascript' src='<!--#echo var="OILS_JS_BASE"-->/init.js' type='text/javascript'></script>
+	<script language='javascript' src='<!--#echo var="OILS_JS_BASE"-->/added_content.js' type='text/javascript'></script>
+
 	<script language="javascript" type="text/javascript">
 		dojo.addOnLoad(init);
 		dojo.require("dijit._Calendar");

Modified: branches/serials-integration/Open-ILS/web/opac/skin/default/xml/rdetail/rdetail_summary.xml
===================================================================
--- branches/serials-integration/Open-ILS/web/opac/skin/default/xml/rdetail/rdetail_summary.xml	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/opac/skin/default/xml/rdetail/rdetail_summary.xml	2010-10-18 13:46:56 UTC (rev 18371)
@@ -131,7 +131,61 @@
 					]]></script>
 				</td>
 			</tr>
+			<tr templated="true"
+				name="serial_holdings_label"
+				class="result_table_title_cell hide_me"
+				type="opac/slot-data"
+				query="datafield[tag=901] subfield[code=c]">
+				<td colspan="2">Issues Held: ${holdingsStatement}
+					<span class="hide_me" name="holdingsStatement" type="opac/template-value"><![CDATA[
+						if (fetchOrgSettingDefault(
+							getLocation(), "opac.fully_compressed_serial_holdings"
+						)) {
+							var bibid = BT.textContent(item_list[0]);
+							var blob = fieldmapper.standardRequest(
+								['open-ils.serial','open-ils.serial.bib.summary_statements'],
+								[bibid, { orgid : getLocation(), depth : getDepth() }]
+							);
 
+							var ret = dojo.create("div");
+							var innerret = dojo.create(
+								"div", {"style":"clear;both;"}, ret
+							);
+
+							var something = false;
+							for (var i in blob) {
+								if (!blob[i].length) continue;
+								something = true;
+								dojo.create(
+									"div", {
+										"innerHTML": blob[i].join(", "),
+										"className": "holding_type_" + i,
+										"style": "float:left;width:33%;"
+									}, innerret
+								);
+								var div = dojo.create("div", {
+									"style": "float:left;width:33%;"
+								});
+								var a = dojo.create(
+									"a", {
+										"innerHTML": "Show holdings",
+										"href": "#",
+										"onclick": "rdetailDrawExpandedHoldings(this,"+bibid+",'"+i+"');return false"
+									}, div
+								);
+								dojo.place(div, innerret);
+								dojo.create("div", {"style":"float:right;width:33%;", "expanded_holdings": i}, innerret);
+							}
+
+							if (something) dojo.removeClass(slot,'hide_me');
+							return ret.innerHTML;
+						} else {
+							return "";
+						}
+					]]></span>
+				</td>
+			</tr>
+
 		</tbody>
 	</table>
 

Modified: branches/serials-integration/Open-ILS/web/templates/base.tt2
===================================================================
--- branches/serials-integration/Open-ILS/web/templates/base.tt2	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/templates/base.tt2	2010-10-18 13:46:56 UTC (rev 18371)
@@ -10,8 +10,20 @@
             href='[% ctx.media_prefix %]/css/skin/[% ctx.skin %].css' />
         <link rel='stylesheet' type='text/css'
             href='[% ctx.media_prefix %]/css/theme/[% ctx.skin %].css' />
-        <script type="text/javascript" src="[% ctx.media_prefix %]/js/dojo/dojo/dojo.js"
-            djConfig="parseOnLoad: true, isDebug:false"></script>
+        <script type="text/javascript">
+var djConfig = {parseOnLoad:true,isDebug:false,AutoIDL:[
+'aou','aout','pgt','lasso','mvr','acp','circ','ccmcmt','asvq','asva','asv','acplo','acqf','acqdfe',
+'vmp','cbs','viiad','vqarad','vqbr','vqbrad','aoa','ac','aua','asvr','actscecm','acqim','acqct','acqexr',
+'acqpro','acqpron','acqipm','acqinv','acqie','acqii','acqpa','acqpc','acqpca','acqftr','acqfc','acqfy','acqfs',
+'acqfscred','acqofscred','acqfdeb','acqf','acqfat','acqfdt','acqfet','acqfst','acqfcb','acqafat','acqafet',
+'acqafst','acqafsb','acqafcb','acqfsrcct','acqfsrcat','acqfsrcb','acqfsb','acqfa','acqfap','acqpl','acqcr',
+'acqpo','acqpoh','acqpon','acqpoi','acqlih','acqliat','acqlin','acqlia','acqlid','acqliad','acqlimad','pgpt',
+'acqligad','acqliuad','acqlipad','acqphsm','acqlilad','acqedi','acqedim','acqdf','acqdfe','acqdfa','acqda','cnal',
+'acqclt','acqclet','acqcl','acqcle','acqscl','acqscle','acqclp','acqclpa','acqlisum','acqft','acqftm','actsce','actscecm',
+'jub','sdist','ssub','sstr','scap','bre','siss','act', 'acpl', 'ccm', 'aiit', 'atevdef', 'ath', 'atreact','atclean','atenv','atevparam','atcol','actsc','cit',
+'atval','crahp','crmf','crrf','crcd','cust','coust','cgf','czs','cbt','csp','brt','brsrc','bra','bram','brav','vaq','vbq','vqar','ccmm','ccmcmtm','citm','cifm','cvrfm']};
+        </script>
+        <script type="text/javascript" src="[% ctx.media_prefix %]/js/dojo/dojo/dojo.js"></script>
         <script type="text/javascript" src="[% ctx.media_prefix %]/js/dojo/dojo/openils_dojo.js"></script>
         <script type="text/javascript" src="[% ctx.media_prefix %]/js/dojo/opensrf/md5.js"></script>
         <script type="text/javascript">

Modified: branches/serials-integration/Open-ILS/web/templates/default/acq/common/inv_dialog.tt2
===================================================================
--- branches/serials-integration/Open-ILS/web/templates/default/acq/common/inv_dialog.tt2	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/templates/default/acq/common/inv_dialog.tt2	2010-10-18 13:46:56 UTC (rev 18371)
@@ -1,24 +1,24 @@
-<script src="[% ctx.media_prefix %]/js/ui/default/acq/common/inv_dialog.js">
+<script type="text/javascript" src="[% ctx.media_prefix %]/js/ui/default/acq/common/inv_dialog.js">
 </script>
 <big><strong>Choose invoice</strong></big>
 <table class="acq-link-invoice-dialog">
     <tr>
         <th>
-            <label for="acq-[% which %]-link-invoice-provider">Provider</label>
+            <label for="acq-[% which %]-link-invoice-inv_ident">
+                Invoice #
+            </label>
         </th>
         <td>
-            <span id="acq-[% which %]-link-invoice-provider"></span>
+            <input id="acq-[% which %]-link-invoice-inv_ident"
+                dojoType="dijit.form.TextBox" />
         </td>
     </tr>
     <tr>
         <th>
-            <label for="acq-[% which %]-link-invoice-inv_ident">
-                Invoice #
-            </label>
+            <label for="acq-[% which %]-link-invoice-provider">Provider</label>
         </th>
         <td>
-            <input id="acq-[% which %]-link-invoice-inv_ident"
-                dojoType="dijit.form.TextBox" />
+            <span id="acq-[% which %]-link-invoice-provider"></span>
         </td>
     </tr>
     <tr>

Modified: branches/serials-integration/Open-ILS/web/templates/default/acq/common/jubgrid.tt2
===================================================================
--- branches/serials-integration/Open-ILS/web/templates/default/acq/common/jubgrid.tt2	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/templates/default/acq/common/jubgrid.tt2	2010-10-18 13:46:56 UTC (rev 18371)
@@ -43,8 +43,8 @@
         .grid_container {width: 100%; height: 100%;}
     </style>
 
-    <script src='[% ctx.media_prefix %]/js/ui/default/acq/common/jubgrid.js'> </script>
-    <script src='[% ctx.media_prefix %]/js/dojo/openils/CopyLocation.js'> </script>
+    <script type="text/javascript" src='[% ctx.media_prefix %]/js/ui/default/acq/common/jubgrid.js'> </script>
+    <script type="text/javascript" src='[% ctx.media_prefix %]/js/dojo/openils/CopyLocation.js'> </script>
     <script type="text/javascript">
     JUBGrid.getPO = function(rowIndex) {
         var data = JUBGrid.jubGrid.model.getRow(rowIndex);

Modified: branches/serials-integration/Open-ILS/web/templates/default/acq/common/li_table.tt2
===================================================================
--- branches/serials-integration/Open-ILS/web/templates/default/acq/common/li_table.tt2	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/templates/default/acq/common/li_table.tt2	2010-10-18 13:46:56 UTC (rev 18371)
@@ -1,6 +1,6 @@
-<script src="[% ctx.media_prefix %]/js/ui/default/acq/common/base64.js"> </script>
-<script src='[% ctx.media_prefix %]/js/ui/default/acq/common/li_table.js'> </script>
-<script src='[% ctx.media_prefix %]/js/ui/default/acq/financial/claim_voucher.js'> </script>
+<script type="text/javascript" src="[% ctx.media_prefix %]/js/ui/default/acq/common/base64.js"> </script>
+<script type="text/javascript" src='[% ctx.media_prefix %]/js/ui/default/acq/common/li_table.js'> </script>
+<script type="text/javascript" src='[% ctx.media_prefix %]/js/ui/default/acq/financial/claim_voucher.js'> </script>
 <div id='acq-lit-table-container'>
     <div id='acq-lit-table-div' class='hidden'>
 
@@ -13,7 +13,7 @@
                             <tr>
                                 <td>
                                     <span>
-                                        <select dojoType='dijit.form.FilteringSelect' value='_' jsId='acqLitLiActionsSelector'>
+                                        <select id="acq-lit-li-actions-selector">
                                             <option mask='*'  value='_'>--Actions--</option>
                                             <option mask='sr' value='save_picklist'>Save Items To Selection List</option>
                                             <option mask='pl' value='selector_ready'>Mark Ready for Selector</option>
@@ -99,8 +99,9 @@
                                 </tr>
                                 <tr>
                                     <td colspan='0'>
-                                        <span name="catalog" class='hidden'><a title='Show In Catalog' name="catalog_link" href="javascript:void(0);">&#x279F; catalog</a></span> 
-                                        <span name="link_to_catalog" class='hidden'><a title='Link To Catalog Record' name="link_to_catalog_link" href="javascript:void(0);">&#x27BE; link to catalog</a></span> 
+                                        <span name="liid"># </span> 
+                                        <span name="catalog" class='hidden'> | <a title='Show In Catalog' name="catalog_link" href="javascript:void(0);">&#x279F; catalog</a></span> 
+                                        <span name="link_to_catalog" class='hidden'> | <a title='Link To Catalog Record' name="link_to_catalog_link" href="javascript:void(0);">&#x27BE; link to catalog</a></span> 
                                         <span name="worksheet"> | <a title='Generate Worksheet' name="worksheet_link" href="javascript:void(0);">&#x270D; worksheet</a></span>
                                         <span name='pl' class='hidden'> | <a title='Select List' name='pl_link' href='javascript:void(0);'>&#x2756; </a></span>
                                         <span name='po' class='hidden'> | <a title='Purchase Order' name='po_link' href='javascript:void(0);'>&#x2318; </a></span>

Modified: branches/serials-integration/Open-ILS/web/templates/default/acq/common/li_table_pager.tt2
===================================================================
--- branches/serials-integration/Open-ILS/web/templates/default/acq/common/li_table_pager.tt2	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/templates/default/acq/common/li_table_pager.tt2	2010-10-18 13:46:56 UTC (rev 18371)
@@ -1,4 +1,4 @@
-<script src="[% ctx.media_prefix %]/js/ui/default/acq/common/li_table_pager.js">
+<script type="text/javascript" src="[% ctx.media_prefix %]/js/ui/default/acq/common/li_table_pager.js">
 </script>
 <div id="acq-litpager-controls">
     <button id="acq-litpager-controls-prev" disabled="disabled">

Modified: branches/serials-integration/Open-ILS/web/templates/default/acq/financial/list_funds.tt2
===================================================================
--- branches/serials-integration/Open-ILS/web/templates/default/acq/financial/list_funds.tt2	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/templates/default/acq/financial/list_funds.tt2	2010-10-18 13:46:56 UTC (rev 18371)
@@ -2,7 +2,7 @@
 [% ctx.page_title = 'Funds' %]
 
 <!-- load the page-specific JS -->
-<script src='[% ctx.media_prefix %]/js/ui/default/acq/financial/list_funds.js'> </script>
+<script type="text/javascript" src='[% ctx.media_prefix %]/js/ui/default/acq/financial/list_funds.js'> </script>
 <script type="text/javascript">
     function getFundName(rowIndex, item) {
         if (!item) return null;

Modified: branches/serials-integration/Open-ILS/web/templates/default/acq/financial/view_fund.tt2
===================================================================
--- branches/serials-integration/Open-ILS/web/templates/default/acq/financial/view_fund.tt2	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/templates/default/acq/financial/view_fund.tt2	2010-10-18 13:46:56 UTC (rev 18371)
@@ -212,6 +212,7 @@
             <script type='dojo/connect' event='onShow'>loadDebitGrid();</script>
             
             <div dojoType="dijit.layout.ContentPane" layoutAlign="top" style='height:600px;'> 
+                <button dojoType="dijit.form.Button" onClick="fundDebitGrid.refresh();">Refresh Grid</button>
                 <div dojoType="dijit.layout.ContentPane" layoutAlign="client">
 
                     <table 

Modified: branches/serials-integration/Open-ILS/web/templates/default/acq/financial/view_funding_source.tt2
===================================================================
--- branches/serials-integration/Open-ILS/web/templates/default/acq/financial/view_funding_source.tt2	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/templates/default/acq/financial/view_funding_source.tt2	2010-10-18 13:46:56 UTC (rev 18371)
@@ -2,7 +2,7 @@
 <script type="text/javascript"> var fundingSourceID = [% ctx.page_args.0 %]; </script>
 
 <!-- load the page-specific JS -->
-<script src='[% ctx.media_prefix %]/js/ui/default/acq/financial/view_funding_source.js'> </script>
+<script type="text/javascript" src='[% ctx.media_prefix %]/js/ui/default/acq/financial/view_funding_source.js'> </script>
 
 <div id='oils-acq-list-header' class='container'>
     <div id='oils-acq-list-header-label'>Funding Source Details</div>

Modified: branches/serials-integration/Open-ILS/web/templates/default/acq/invoice/view.tt2
===================================================================
--- branches/serials-integration/Open-ILS/web/templates/default/acq/invoice/view.tt2	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/templates/default/acq/invoice/view.tt2	2010-10-18 13:46:56 UTC (rev 18371)
@@ -1,7 +1,7 @@
 [% WRAPPER 'default/base.tt2' %]
 [% ctx.page_title = 'Invoicing' %]
-<script src='[% ctx.media_prefix %]/js/ui/default/acq/invoice/common.js'> </script>
-<script src='[% ctx.media_prefix %]/js/ui/default/acq/invoice/view.js'> </script>
+<script type="text/javascript" src='[% ctx.media_prefix %]/js/ui/default/acq/invoice/common.js'> </script>
+<script type="text/javascript" src='[% ctx.media_prefix %]/js/ui/default/acq/invoice/view.js'> </script>
 <script type="text/javascript">var invoiceId = '[% ctx.page_args.0 %]';</script>
 <div dojoType="dijit.layout.ContentPane" style="height:100%">
 
@@ -42,6 +42,7 @@
                     </td>
                     <td class='acq-invoice-center-col'>
                         <span name='inv_item_count'></span>&nbsp;/&nbsp;<span name='phys_item_count'></span>
+                    </td>
                     <td class='acq-invoice-billed-col'><div name='cost_billed'/></td>
                     <td class='acq-invoice-paid-col'><div name='amount_paid'/></td>
                     <td class='acq-invoice-center-col hide-complete'><a href='javascript:void(0);' name='detach'>Detach</a></td>

Modified: branches/serials-integration/Open-ILS/web/templates/default/acq/lineitem/findbib.tt2
===================================================================
--- branches/serials-integration/Open-ILS/web/templates/default/acq/lineitem/findbib.tt2	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/templates/default/acq/lineitem/findbib.tt2	2010-10-18 13:46:56 UTC (rev 18371)
@@ -1,6 +1,6 @@
 [% WRAPPER "default/base.tt2" %]
 [% ctx.page_title = "Locate Bib Record" %]
-<script src="[% ctx.media_prefix %]/js/ui/default/acq/lineitem/findbib.js"></script>
+<script type="text/javascript" src="[% ctx.media_prefix %]/js/ui/default/acq/lineitem/findbib.js"></script>
 <script type="text/javascript">
     function iterateSubfields(item) {
         var out = '';

Modified: branches/serials-integration/Open-ILS/web/templates/default/acq/lineitem/related.tt2
===================================================================
--- branches/serials-integration/Open-ILS/web/templates/default/acq/lineitem/related.tt2	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/templates/default/acq/lineitem/related.tt2	2010-10-18 13:46:56 UTC (rev 18371)
@@ -1,6 +1,6 @@
 [% WRAPPER "default/base.tt2" %]
 [% ctx.page_title = "Related Lineitems" %]
-<script src="[% ctx.media_prefix %]/js/ui/default/acq/lineitem/related.js"></script>
+<script type="text/javascript" src="[% ctx.media_prefix %]/js/ui/default/acq/lineitem/related.js"></script>
 <script type="text/javascript">var targetId = "[% ctx.page_args.0 %]";</script>
 <h1>Related Lineitems</h1>
 <div id="acq-related-mini">

Modified: branches/serials-integration/Open-ILS/web/templates/default/acq/lineitem/search.tt2
===================================================================
--- branches/serials-integration/Open-ILS/web/templates/default/acq/lineitem/search.tt2	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/templates/default/acq/lineitem/search.tt2	2010-10-18 13:46:56 UTC (rev 18371)
@@ -1,6 +1,6 @@
 [% WRAPPER 'default/base.tt2' %]
 [% ctx.page_title = 'Lineitem Search' %]
-<script src="[% ctx.media_prefix %]/js/ui/default/acq/lineitem/search.js"></script>
+<script type="text/javascript" src="[% ctx.media_prefix %]/js/ui/default/acq/lineitem/search.js"></script>
 <!-- later: "[% ctx.page_args.0 %]" -->
 <div id="oils-acq-li-search-form-holder" class="hidden">
     <h1 class="oils-acq-li-search">Lineitem Search</h1>

Modified: branches/serials-integration/Open-ILS/web/templates/default/acq/lineitem/worksheet.tt2
===================================================================
--- branches/serials-integration/Open-ILS/web/templates/default/acq/lineitem/worksheet.tt2	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/templates/default/acq/lineitem/worksheet.tt2	2010-10-18 13:46:56 UTC (rev 18371)
@@ -1,6 +1,6 @@
 [% WRAPPER "default/base.tt2" %]
 [% ctx.page_title = "Lineitem Worksheet" %]
-<script src="[% ctx.media_prefix %]/js/ui/default/acq/lineitem/worksheet.js"></script>
+<script type="text/javascript" src="[% ctx.media_prefix %]/js/ui/default/acq/lineitem/worksheet.js"></script>
 <script type="text/javascript">var liId = "[% ctx.page_args.0 %]";</script>
 <h1>Lineitem Worksheet</h1>
 <br/>

Modified: branches/serials-integration/Open-ILS/web/templates/default/acq/picklist/bib_search.tt2
===================================================================
--- branches/serials-integration/Open-ILS/web/templates/default/acq/picklist/bib_search.tt2	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/templates/default/acq/picklist/bib_search.tt2	2010-10-18 13:46:56 UTC (rev 18371)
@@ -1,5 +1,5 @@
 [% WRAPPER 'default/base.tt2' %]
-<script src='[% ctx.media_prefix %]/js/ui/default/acq/picklist/bib_search.js'> </script>
+<script type="text/javascript" src='[% ctx.media_prefix %]/js/ui/default/acq/picklist/bib_search.js'></script>
 <style type="text/css">
     @import "[% ctx.media_prefix %]/js/dojo/dojox/form/resources/CheckedMultiSelect.css";
 </style>

Modified: branches/serials-integration/Open-ILS/web/templates/default/acq/picklist/brief_record.tt2
===================================================================
--- branches/serials-integration/Open-ILS/web/templates/default/acq/picklist/brief_record.tt2	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/templates/default/acq/picklist/brief_record.tt2	2010-10-18 13:46:56 UTC (rev 18371)
@@ -1,5 +1,5 @@
 [% WRAPPER 'default/base.tt2' %]
-<script src='[% ctx.media_prefix %]/js/ui/default/acq/picklist/brief_record.js'> </script>
+<script type="text/javascript" src='[% ctx.media_prefix %]/js/ui/default/acq/picklist/brief_record.js'> </script>
 
 <h1>New Brief Record</h1><br/>
 <form dojoType='dijit.form.Form'>

Modified: branches/serials-integration/Open-ILS/web/templates/default/acq/picklist/from_bib.tt2
===================================================================
--- branches/serials-integration/Open-ILS/web/templates/default/acq/picklist/from_bib.tt2	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/templates/default/acq/picklist/from_bib.tt2	2010-10-18 13:46:56 UTC (rev 18371)
@@ -1,6 +1,6 @@
 [% WRAPPER "default/base.tt2" %]
 [% ctx.page_title = "Items by Bibliographic ID" %]
-<script src="[% ctx.media_prefix %]/js/ui/default/acq/picklist/from_bib.js">
+<script type="text/javascript" src="[% ctx.media_prefix %]/js/ui/default/acq/picklist/from_bib.js">
 </script>
 <div id="acq-frombib-upload-box">
     <div class="oils-acq-basic-roomy">

Modified: branches/serials-integration/Open-ILS/web/templates/default/acq/picklist/list.tt2
===================================================================
--- branches/serials-integration/Open-ILS/web/templates/default/acq/picklist/list.tt2	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/templates/default/acq/picklist/list.tt2	2010-10-18 13:46:56 UTC (rev 18371)
@@ -1,6 +1,6 @@
 [% WRAPPER 'default/base.tt2' %]
 [% ctx.page_title = 'Selection Lists' %]
-<script src='[% ctx.media_prefix %]/js/ui/default/acq/picklist/view_list.js'> </script>
+<script type="text/javascript" src='[% ctx.media_prefix %]/js/ui/default/acq/picklist/view_list.js'></script>
 
 <script type="text/javascript">
     function formatName(inDatum) {

Modified: branches/serials-integration/Open-ILS/web/templates/default/acq/picklist/upload.tt2
===================================================================
--- branches/serials-integration/Open-ILS/web/templates/default/acq/picklist/upload.tt2	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/templates/default/acq/picklist/upload.tt2	2010-10-18 13:46:56 UTC (rev 18371)
@@ -1,5 +1,5 @@
 [% WRAPPER 'default/base.tt2' %]
-<script src='[% ctx.media_prefix %]/js/ui/default/acq/picklist/upload.js'> </script>
+<script type="text/javascript" src='[% ctx.media_prefix %]/js/ui/default/acq/picklist/upload.js'> </script>
 
 <h1>Upload</h1><br/>
 <form id="acq-pl-upload-form" enctype="multipart/form-data">
@@ -34,7 +34,7 @@
                 <td><div id='acq-pl-upload-agency'></div></td>
             </tr>
             <tr id='acq-pl-upload-picklist'>
-                <td>Add to Picklist</td>
+                <td>Add to Selection List</td>
                 <td>
                     <select jsId='acqPlUploadPlSelector' dojoType='dijit.form.ComboBox'></select>
                 </td>

Modified: branches/serials-integration/Open-ILS/web/templates/default/acq/picklist/user_request.tt2
===================================================================
--- branches/serials-integration/Open-ILS/web/templates/default/acq/picklist/user_request.tt2	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/templates/default/acq/picklist/user_request.tt2	2010-10-18 13:46:56 UTC (rev 18371)
@@ -1,6 +1,6 @@
 [% WRAPPER 'default/base.tt2' %]
 [% ctx.page_title = 'Patron Requests' %]
-<script src='[% ctx.media_prefix %]/js/ui/default/acq/picklist/user_request.js'> </script>
+<script type="text/javascript" src='[% ctx.media_prefix %]/js/ui/default/acq/picklist/user_request.js'></script>
 <script type="text/javascript">var reqId = '[% ctx.page_args.0 %]';</script>
 
     <div dojoType="dijit.layout.StackContainer" id="stackContainer" doLayout="false">
@@ -44,7 +44,7 @@
                 <div>Patron Request</div>
                 <div>
                     <button dojoType="dijit.form.Button" onClick="location.href=oilsBasePath+'/acq/picklist/user_request'">[% ctx.page_title %]</button>
-                    <button dojoType="dijit.form.Button" onClick="fooPicklist()"><span id="add_to_picklist">Add to Picklist</span><span id="view_picklist">View Picklist</span></button>
+                    <button dojoType="dijit.form.Button" onClick="fooPicklist()"><span id="add_to_picklist">Add to Selection List</span><span id="view_picklist">View Selection List</span></button>
                     <button dojoType="dijit.form.Button" onClick="setNoHold()">Set No Hold</button>
                     <span dojoType="dijit.form.DropDownButton">
                         <span>Cancel Request</span>

Modified: branches/serials-integration/Open-ILS/web/templates/default/acq/picklist/view.tt2
===================================================================
--- branches/serials-integration/Open-ILS/web/templates/default/acq/picklist/view.tt2	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/templates/default/acq/picklist/view.tt2	2010-10-18 13:46:56 UTC (rev 18371)
@@ -1,6 +1,6 @@
 [% WRAPPER 'default/base.tt2' %]
 [% ctx.page_title = 'Selection List' %]
-<script src='[% ctx.media_prefix %]/js/ui/default/acq/picklist/view.js'> </script>
+<script type="text/javascript" src='[% ctx.media_prefix %]/js/ui/default/acq/picklist/view.js'></script>
 <div dojoType="dijit.layout.ContentPane" style="height:100%">
     <div class='container'>
         <div id='oils-acq-picklist-header'>

Modified: branches/serials-integration/Open-ILS/web/templates/default/acq/po/events.tt2
===================================================================
--- branches/serials-integration/Open-ILS/web/templates/default/acq/po/events.tt2	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/templates/default/acq/po/events.tt2	2010-10-18 13:46:56 UTC (rev 18371)
@@ -1,5 +1,5 @@
 [% WRAPPER default/base.tt2 %]
-<script src="[% ctx.media_prefix %]/js/ui/default/acq/po/events.js"> </script>
+<script type="text/javascript" src="[% ctx.media_prefix %]/js/ui/default/acq/po/events.js"> </script>
 
 <!-- grid -->
 

Modified: branches/serials-integration/Open-ILS/web/templates/default/acq/po/search.tt2
===================================================================
--- branches/serials-integration/Open-ILS/web/templates/default/acq/po/search.tt2	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/templates/default/acq/po/search.tt2	2010-10-18 13:46:56 UTC (rev 18371)
@@ -20,7 +20,7 @@
     <span><a class="hidden" attr="activator" href="javascript:void(0);">Activate Order</a></span>
 </div>
 <!-- load the page-specific JS -->
-<script src='[% ctx.media_prefix %]/js/ui/default/acq/po/search.js'> </script>
+<script type="text/javascript" src='[% ctx.media_prefix %]/js/ui/default/acq/po/search.js'> </script>
 
 <script type="text/javascript">
     function formatId(id) {

Modified: branches/serials-integration/Open-ILS/web/templates/default/acq/po/view.tt2
===================================================================
--- branches/serials-integration/Open-ILS/web/templates/default/acq/po/view.tt2	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/templates/default/acq/po/view.tt2	2010-10-18 13:46:56 UTC (rev 18371)
@@ -1,11 +1,14 @@
 [% WRAPPER 'default/base.tt2' %]
-<script src="[% ctx.media_prefix %]/js/ui/default/acq/common/base64.js"> </script>
-<script src='[% ctx.media_prefix %]/js/ui/default/acq/po/view_po.js'> </script>
-<script src="[% ctx.media_prefix %]/js/ui/default/acq/po/item_table.js"></script>
+<script type="text/javascript" src="[% ctx.media_prefix %]/js/ui/default/acq/common/base64.js"></script>
+<script type="text/javascript" src='[% ctx.media_prefix %]/js/ui/default/acq/po/view_po.js'></script>
+<script type="text/javascript" src="[% ctx.media_prefix %]/js/ui/default/acq/po/item_table.js"></script>
 <div dojoType="dijit.layout.ContentPane" style="height:100%">
     <div>
         <div id='oils-acq-picklist-header'>
-            <big>Purchase Order</big>
+            <big>
+                Purchase Order (<span id="acq-po-view-state"></span>) 
+            </big>
+            <span id='acq-po-activated-on' class='hidden'></span>
             <table class="oils-generic-table acq-po-info">
                 <tr>
                     <th>ID</th><td><a id="acq-po-view-id"/></td>
@@ -67,6 +70,14 @@
                             <span>Link Invoice</span>
                             <div dojoType="dijit.TooltipDialog"
                                 id="acq-po-link-invoice">
+                                <script type="dojo/connect" event="onOpen">
+                                    if (!invoiceLinkDialogManager) {
+                                        invoiceLinkDialogManager =
+                                            new InvoiceLinkDialogManager(
+                                                "po", PO
+                                            );
+                                    }
+                                </script>
                                 [% INCLUDE "default/acq/common/inv_dialog.tt2"
                                     which = "po" %]
                             </div>
@@ -96,9 +107,7 @@
                     </td>
                 </tr>
                 <tr>
-                    <th>Status</th>
-                    <td><span id="acq-po-view-state"/></td>
-                    <td>
+                    <td colspan='3'>
                         <a class="hidden" id="acq-po-split" href="javascript:void(0);"
                             onclick="if (confirm(localeStrings.CONFIRM_SPLIT_PO)) splitPo();">
                             Split Order by Lineitems

Modified: branches/serials-integration/Open-ILS/web/templates/default/acq/receiving/process.tt2
===================================================================
--- branches/serials-integration/Open-ILS/web/templates/default/acq/receiving/process.tt2	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/templates/default/acq/receiving/process.tt2	2010-10-18 13:46:56 UTC (rev 18371)
@@ -1,5 +1,5 @@
 [% WRAPPER default/base.tt2 %]
-    <script src='[% ctx.media_prefix %]/js/ui/default/acq/receiving/process.js'> </script>
+<script type="text/javascript" src='[% ctx.media_prefix %]/js/ui/default/acq/receiving/process.js'> </script>
     <h1>Receiving Processing</h1><br/>
     <div id='oils-acq-recv-search-block' class='container'>
         <form dojoType='dijit.form.Form' action='' method=''>

Modified: branches/serials-integration/Open-ILS/web/templates/default/acq/search/unified.tt2
===================================================================
--- branches/serials-integration/Open-ILS/web/templates/default/acq/search/unified.tt2	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/templates/default/acq/search/unified.tt2	2010-10-18 13:46:56 UTC (rev 18371)
@@ -1,10 +1,10 @@
 [% WRAPPER "default/base.tt2" %]
 [% ctx.page_title = "Acquisitions Search" %]
-<script src="[% ctx.media_prefix %]/js/ui/default/acq/common/base64.js"></script>
-<script src="[% ctx.media_prefix %]/js/ui/default/acq/search/unified.js"></script>
-<script src="[% ctx.media_prefix %]/js/ui/default/acq/search/invoice.js"></script>
-<script src="[% ctx.media_prefix %]/js/ui/default/acq/search/picklist.js"></script>
-<script src="[% ctx.media_prefix %]/js/ui/default/acq/search/purchase_order.js"></script>
+<script type="text/javascript" src="[% ctx.media_prefix %]/js/ui/default/acq/common/base64.js"></script>
+<script type="text/javascript" src="[% ctx.media_prefix %]/js/ui/default/acq/search/unified.js"></script>
+<script type="text/javascript" src="[% ctx.media_prefix %]/js/ui/default/acq/search/invoice.js"></script>
+<script type="text/javascript" src="[% ctx.media_prefix %]/js/ui/default/acq/search/picklist.js"></script>
+<script type="text/javascript" src="[% ctx.media_prefix %]/js/ui/default/acq/search/purchase_order.js"></script>
 <div id="acq-unified-body" class="hidden">
     <div id="acq-unified-heading">
         <span id="acq-unified-heading-actual">Acquisitions Search</span>
@@ -89,6 +89,11 @@
         </div>
     </div>
     <div id="acq-unified-results-purchase_order" class="hidden">
+        <div class="acq-unified-result-specific-controls">
+            <button onclick="dijit.byId('acq-unified-po-grid').refresh();">
+                Refresh Grid
+            </button>
+        </div>
         <table
             id="acq-unified-po-grid"
             autoHeight="true"
@@ -111,6 +116,10 @@
     </div>
     <div id="acq-unified-results-picklist" class="hidden">
         <div class="acq-unified-result-specific-controls">
+            <button dojoType="dijit.form.Button"
+                onClick="dijit.byId('acq-unified-pl-grid').refresh();">
+                Refresh Grid
+            </button>
             <div dojoType="dijit.form.DropDownButton">
                 <span>New Selection List</span>
                 <div dojoType="dijit.TooltipDialog"
@@ -201,6 +210,9 @@
     </div>
     <div id="acq-unified-results-invoice" class="hidden">
         <div class="acq-unified-result-specific-controls">
+            <button onclick="dijit.byId('acq-unified-inv-grid').refresh();">
+                Refresh Grid
+            </button>
             <button onclick="printInvoiceVouchers();">
                 Print Selected Invoices
             </button>
@@ -217,7 +229,7 @@
             <thead>
                 <tr>
                     <th field="inv_ident" get="getInvIdent"
-                        formatter="formatInvIdent">Vendor Invoice ID</th>
+                        formatter="formatInvIdent"></th>
                 </tr>
             </thead>
         </table>
@@ -229,5 +241,6 @@
         [% INCLUDE "default/acq/common/li_table_pager.tt2" %]
         [% INCLUDE "default/acq/common/li_table.tt2" %]
     </div>
+    <div jsId='progressDialog' dojoType='openils.widget.ProgressDialog'/>
 </div>
 [% END %]

Modified: branches/serials-integration/Open-ILS/web/templates/default/acq/settings/li_attr.tt2
===================================================================
--- branches/serials-integration/Open-ILS/web/templates/default/acq/settings/li_attr.tt2	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/templates/default/acq/settings/li_attr.tt2	2010-10-18 13:46:56 UTC (rev 18371)
@@ -1,5 +1,5 @@
 [% WRAPPER default/base.tt2 %]
-<script src='[% ctx.media_prefix %]/js/ui/default/acq/settings/li_attr.js'> </script>
+<script type="text/javascript" src='[% ctx.media_prefix %]/js/ui/default/acq/settings/li_attr.js'></script>
 
 <div dojoType="dijit.layout.ContentPane" layoutAlign="top">
     <div dojoType="dijit.form.DropDownButton">

Modified: branches/serials-integration/Open-ILS/web/templates/default/actor/user/register.tt2
===================================================================
--- branches/serials-integration/Open-ILS/web/templates/default/actor/user/register.tt2	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/templates/default/actor/user/register.tt2	2010-10-18 13:46:56 UTC (rev 18371)
@@ -1,91 +1,8 @@
 [% ctx.page_title = 'User Editor' %]
 [% WRAPPER default/base.tt2 %]
-<script src='[% ctx.media_prefix %]/js/ui/default/actor/user/register.js'> </script>
+<script type="text/javascript" src='[% ctx.media_prefix %]/js/ui/default/actor/user/register.js'></script>
+<link rel="stylesheet" type="text/css" href="[% ctx.media_prefix %]/css/skin/[% ctx.skin %]/register.css" />
 
-<style type="text/css">
-
-    /* XXX Move me into the CSS tree XXX */
-
-    #uedit-tbody tr td {
-        padding: 5px;
-        text-align: left;
-    }
-
-
-    #uedit-save-div {
-        position: fixed;
-        top:40px;
-        right:30px;
-        width:300px;
-        border:2px solid #d9e8f9;
-        -moz-border-radius: 10px;
-        font-weight: bold;
-        padding: 12px;
-        text-align:center;
-        vertical-align:middle;
-    }
-
-    #uedit-help-div {
-        position: fixed;
-        top:124px;
-        right:30px;
-        width:300px;
-        border:2px dashed #d9e8f9;
-        -moz-border-radius: 10px;
-        font-weight: bold;
-        padding: 20px;
-    }
-
-    #uedit-dupe-div {
-        position: fixed;
-        top:124px;
-        right:30px;
-        width:300px;
-        border:2px dashed #d9e8f9;
-        -moz-border-radius: 10px;
-        font-weight: bold;
-        padding: 20px;
-    }
-
-    .uedit-help {
-        width: 25px;
-        border:1px solid #e0e0e0;
-        text-align:center;
-        vertical-align:middle;
-    }
-    .divider td {
-        min-height:10px;
-        background-color: #e0e0e0;
-    }
-
-    .divider span { padding: 0px 5px 0px 5px; }
-
-    .newaddr-row td {
-        text-align: right;
-        border-top:1px dashed #d9e8f9;
-    }
-    .newaddr-row td:last-child {
-        border-right:1px dashed #d9e8f9;
-    }
-
-    .pending-addr-row td { border:1px solid #aaa; }
-
-    .uedit-addr-del-button {margin-left: 10px; color:red;}
-
-    .dijitTextBoxFocused, .dijitFocused { border:1px dashed #3e3e3e; color: #303030; font-weight:bold;}
-
-    .hide-non-required tr:not([required]) {
-        visibility:hidden;
-        display:none;
-    }
-
-    #require-toggle {
-        margin-top:10px;
-        margin-bottom:-5px;
-    }
-
-</style>
-
 <div dojoType="dijit.form.Form" id="myForm" jsId="myForm" encType="multipart/form-data" action="" method="">
     <script type="dojo/method" event="onSubmit">
         /* we don't want to use the form action, but uEditSave and UEditSaveClone from the Save buttons.  We

Modified: branches/serials-integration/Open-ILS/web/templates/default/actor/user/register_table.tt2
===================================================================
--- branches/serials-integration/Open-ILS/web/templates/default/actor/user/register_table.tt2	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/templates/default/actor/user/register_table.tt2	2010-10-18 13:46:56 UTC (rev 18371)
@@ -59,14 +59,14 @@
         <td>
             <span>Mailing</span><input type='radio' name='mailing_address'>
             <span>Billing</span><input type='radio' name='billing_address'>
-            <button name='delete-button' class='uedit-addr-del-button'>X</button>
+            <button dojoType='dijit.form.Button' scrollOnFocus='false' name='delete-button' class='uedit-addr-del-button'>X</button>
         </td>
     </tr>
 
     <tr name='uedit-addr-pending-row' type='addr-template' class='pending-addr-row hidden'>
         <td colspan='3'>
             <span style='padding-right:10px;'>This is a pending address: </span>
-            <button name='approve-button'>Approve Address</button>
+            <button dojoType='dijit.form.Button' scrollOnFocus='false'  name='approve-button'>Approve Address</button>
             <div name='replaced-addr-div'>
                 <div name='replaced-addr'></div>
             </div>

Modified: branches/serials-integration/Open-ILS/web/templates/default/booking/capture.tt2
===================================================================
--- branches/serials-integration/Open-ILS/web/templates/default/booking/capture.tt2	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/templates/default/booking/capture.tt2	2010-10-18 13:46:56 UTC (rev 18371)
@@ -1,6 +1,6 @@
 [% WRAPPER "default/base.tt2" %]
-<script src="[% ctx.media_prefix %]/js/ui/default/booking/common.js"></script>
-<script src="[% ctx.media_prefix %]/js/ui/default/booking/capture.js"></script>
+<script type="text/javascript" src="[% ctx.media_prefix %]/js/ui/default/booking/common.js"></script>
+<script type="text/javascript" src="[% ctx.media_prefix %]/js/ui/default/booking/capture.js"></script>
 <link rel="stylesheet" type="text/css" href="[% ctx.media_prefix %]/css/skin/[% ctx.skin %]/booking.css" id="booking_stylesheet_link" />
 <script type="text/javascript">openils.Util.addOnLoad(my_init);</script>
 <div id="auto_l10n_start_here">

Modified: branches/serials-integration/Open-ILS/web/templates/default/booking/pickup.tt2
===================================================================
--- branches/serials-integration/Open-ILS/web/templates/default/booking/pickup.tt2	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/templates/default/booking/pickup.tt2	2010-10-18 13:46:56 UTC (rev 18371)
@@ -1,7 +1,7 @@
 [% WRAPPER "default/base.tt2" %]
-<script src="[% ctx.media_prefix %]/js/ui/default/booking/common.js"></script>
-<script src="[% ctx.media_prefix %]/js/ui/default/booking/populator.js"></script>
-<script src="[% ctx.media_prefix %]/js/ui/default/booking/pickup.js"></script>
+<script type="text/javascript" src="[% ctx.media_prefix %]/js/ui/default/booking/common.js"></script>
+<script type="text/javascript" src="[% ctx.media_prefix %]/js/ui/default/booking/populator.js"></script>
+<script type="text/javascript" src="[% ctx.media_prefix %]/js/ui/default/booking/pickup.js"></script>
 <link rel="stylesheet" type="text/css" href="[% ctx.media_prefix %]/css/skin/[% ctx.skin %]/booking.css" />
 <script type="text/javascript">
     dojo.require("dojox.grid.DataGrid");

Modified: branches/serials-integration/Open-ILS/web/templates/default/booking/pull_list.tt2
===================================================================
--- branches/serials-integration/Open-ILS/web/templates/default/booking/pull_list.tt2	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/templates/default/booking/pull_list.tt2	2010-10-18 13:46:56 UTC (rev 18371)
@@ -1,6 +1,6 @@
 [% WRAPPER "default/base.tt2" %]
-<script src="[% ctx.media_prefix %]/js/ui/default/booking/common.js"></script>
-<script src="[% ctx.media_prefix %]/js/ui/default/booking/pull_list.js"></script>
+<script type="text/javascript" src="[% ctx.media_prefix %]/js/ui/default/booking/common.js"></script>
+<script type="text/javascript" src="[% ctx.media_prefix %]/js/ui/default/booking/pull_list.js"></script>
 <link rel="stylesheet" type="text/css" href="[% ctx.media_prefix %]/css/skin/[% ctx.skin %]/booking.css" />
 <script type="text/javascript">openils.Util.addOnLoad(my_init);</script>
 <div id="auto_l10n_start_here">

Modified: branches/serials-integration/Open-ILS/web/templates/default/booking/reservation.tt2
===================================================================
--- branches/serials-integration/Open-ILS/web/templates/default/booking/reservation.tt2	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/templates/default/booking/reservation.tt2	2010-10-18 13:46:56 UTC (rev 18371)
@@ -1,6 +1,6 @@
 [% WRAPPER "default/base.tt2" %]
-<script src="[% ctx.media_prefix %]/js/ui/default/booking/common.js"></script>
-<script src="[% ctx.media_prefix %]/js/ui/default/booking/reservation.js"></script>
+<script type="text/javascript" src="[% ctx.media_prefix %]/js/ui/default/booking/common.js"></script>
+<script type="text/javascript" src="[% ctx.media_prefix %]/js/ui/default/booking/reservation.js"></script>
 <link rel="stylesheet" type="text/css" href="[% ctx.media_prefix %]/css/skin/[% ctx.skin %]/booking.css" />
 <script type="text/javascript">
     dojo.require("dojox.grid.DataGrid");

Modified: branches/serials-integration/Open-ILS/web/templates/default/booking/return.tt2
===================================================================
--- branches/serials-integration/Open-ILS/web/templates/default/booking/return.tt2	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/templates/default/booking/return.tt2	2010-10-18 13:46:56 UTC (rev 18371)
@@ -1,7 +1,7 @@
 [% WRAPPER "default/base.tt2" %]
-<script src="[% ctx.media_prefix %]/js/ui/default/booking/common.js"></script>
-<script src="[% ctx.media_prefix %]/js/ui/default/booking/populator.js"></script>
-<script src="[% ctx.media_prefix %]/js/ui/default/booking/return.js"></script>
+<script type="text/javascript" src="[% ctx.media_prefix %]/js/ui/default/booking/common.js"></script>
+<script type="text/javascript" src="[% ctx.media_prefix %]/js/ui/default/booking/populator.js"></script>
+<script type="text/javascript" src="[% ctx.media_prefix %]/js/ui/default/booking/return.js"></script>
 <link rel="stylesheet" type="text/css" href="[% ctx.media_prefix %]/css/skin/[% ctx.skin %]/booking.css" />
 <script type="text/javascript">
     dojo.require("dojox.grid.DataGrid");

Copied: branches/serials-integration/Open-ILS/web/templates/default/cat (from rev 17886, trunk/Open-ILS/web/templates/default/cat)

Modified: branches/serials-integration/Open-ILS/web/templates/default/circ/selfcheck/main.tt2
===================================================================
--- branches/serials-integration/Open-ILS/web/templates/default/circ/selfcheck/main.tt2	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/templates/default/circ/selfcheck/main.tt2	2010-10-18 13:46:56 UTC (rev 18371)
@@ -1,7 +1,7 @@
 [% ctx.page_title = 'Self Checkout' %]
 [% WRAPPER default/base.tt2 %]
-<script src='[% ctx.media_prefix %]/js/ui/default/circ/selfcheck/selfcheck.js'> </script>
-<script src="[% ctx.media_prefix %]/js/ui/default/circ/selfcheck/payment.js"></script>
+<script type="text/javascript" src='[% ctx.media_prefix %]/js/ui/default/circ/selfcheck/selfcheck.js'> </script>
+<script type="text/javascript" src="[% ctx.media_prefix %]/js/ui/default/circ/selfcheck/payment.js"></script>
 <link rel='stylesheet' type='text/css' href='[% ctx.media_prefix %]/css/skin/[% ctx.skin %]/selfcheck.css'/>
 [% INCLUDE 'default/circ/selfcheck/audio_config.tt2' %]
 

Modified: branches/serials-integration/Open-ILS/web/templates/default/conify/global/acq/distribution_formula.tt2
===================================================================
--- branches/serials-integration/Open-ILS/web/templates/default/conify/global/acq/distribution_formula.tt2	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/templates/default/conify/global/acq/distribution_formula.tt2	2010-10-18 13:46:56 UTC (rev 18371)
@@ -1,22 +1,23 @@
 [% WRAPPER default/base.tt2 %]
 [% ctx.page_title = 'Distribution Formulas' %]
 <script type="text/javascript" src='[% ctx.media_prefix %]/js/ui/default/conify/global/acq/distribution_formula.js'></script>
-<script type="text/javascript"> var formulaId = '[% ctx.page_args.0 %]';
 
-function getFormulaName(rowIndex, item) {
-    if(!item) return '';
-    var name = this.grid.store.getValue(item, 'name');
-    var id = this.grid.store.getValue(item, 'id');
-    return id + ':' + name;
-}
+<script type="text/javascript"> 
+    var formulaId = '[% ctx.page_args.0 %]';
 
-function formatName(value) {
-    if(value) {
-        var vals = value.split(/:/);
-        return '<a href="'+location.href+ '/'+vals[0]+'">'+vals[1]+'</a>';
+    function getFormulaName(rowIndex, item) {
+        if(!item) return '';
+        var name = this.grid.store.getValue(item, 'name');
+        var id = this.grid.store.getValue(item, 'id');
+        return id + ':' + name;
     }
-}
 
+    function formatName(value) {
+        if(value) {
+            var vals = value.split(/:/);
+            return '<a href="'+location.href+ '/'+vals[0]+'">'+vals[1]+'</a>';
+        }
+    }
 </script>
 
 
@@ -27,11 +28,13 @@
             <div>
                 <button dojoType='dijit.form.Button' onClick='fListGrid.showCreateDialog()'>New Formula</button>
                 <button dojoType='dijit.form.Button' onClick='fListGrid.deleteSelected()'>Delete Selected</button>
+                <button dojoType='dijit.form.Button' onClick='cloneSelectedFormula()'>Clone Selected</button>
             </div>
         </div>
         <table  jsId="fListGrid"
                 dojoType="openils.widget.AutoGrid"
-                fieldOrder="['id', 'name', 'owner', 'item_count', 'skip_count']"
+                fieldOrder="['id', 'name', 'owner', 'item_count']"
+                suppressFields="['skip_count']"
                 query="{id: '*'}"
                 defaultCellWidth='12'
                 fmClass='acqdf'
@@ -48,34 +51,49 @@
 
 
 <div id='formula-entry-div'>
-    <div dojoType="dijit.layout.ContentPane" layoutAlign="client">
-        <div id='formula-summary-pane'/>
-    </div>
-        <div dojoType="dijit.layout.ContentPane" layoutAlign="client" class='oils-header-panel'>
-            <div id="formula_head"></div>
-            <div>
-                <button dojoType='dijit.form.Button' onClick='dfeListGrid.showCreateDialog()'>New Formula Entry</button>
-                <button dojoType='dijit.form.Button' onClick='dfeListGrid.deleteSelected()'>Delete Selected</button>
-            </div>
+    <div dojoType="dijit.layout.ContentPane" layoutAlign="client" class='oils-header-panel'>
+        <div><a href='javascript:void(0);' id="formula_head"></a></div>
+        <div>
         </div>
-        <div dojoType="dijit.layout.ContentPane" layoutAlign="client">
-            <table  jsId="dfeListGrid"
-                    autoHeight='true'
-                    dojoType="openils.widget.AutoGrid"
-                    fieldOrder="['id','formula', 'owning_lib', 'location', 'item_count', 'position']"
-                    suppressFields="['formula']"
-                    query="{id: '*'}"
-                    defaultCellWidth='12'
-                    fmClass='acqdfe'
-                    editOnEnter='true'>
-                <thead>
-                    <tr>
-                        <th field='formula' get='getFormulaId' formatter='formatName'/>
-                    </tr>
-                </thead>
-            </table>
-        </div>
     </div>
+    <br/>
+    <div>
+        <button dojoType='dijit.form.Button' onClick='addEntry()'>New Entry</button>
+        <span style='padding-right:20px;'></span>
+        <button dojoType='dijit.form.Button' onClick='saveFormula()'>Apply Changes</button>
+    </div>
+    <br/>
+    <table class='oils-generic-table'>
+        <thead>
+            <tr>
+                <th></th>
+                <th>Owning Library</th>
+                <th>Shelving Location</th>
+                <th>Item Count</th>
+                <th></th>
+            </tr>
+        </thead>
+        <tbody id='formula-entry-tbody'>
+            <tr id='formula-entry-tempate'>
+                <td><div name='delete' dojoType='dijit.form.Button' style='color:red;' scrollOnFocus='false'>X</div></td>
+                <td><div name='owning_lib'></td>
+                <td><div name='location'></td>
+                <td><div name='item_count'></td>
+                <td>
+                    <img src='[% ctx.media_prefix %]/images/dimple.png'/>
+                    <img src='[% ctx.media_prefix %]/images/dimple.png'/>
+                    <img src='[% ctx.media_prefix %]/images/dimple.png'/>
+                <td>
+            </tr>
+        </tbody>
+    </table>
+    <br/>
+    <div>
+        <button dojoType='dijit.form.Button' onClick='addEntry()'>New Entry</button>
+        <span style='padding-right:20px;'></span>
+        <button dojoType='dijit.form.Button' onClick='saveFormula()'>Apply Changes</button>
+    </div>
 </div>
+
 [% END %]
 

Modified: branches/serials-integration/Open-ILS/web/templates/default/conify/global/acq/edi_account.tt2
===================================================================
--- branches/serials-integration/Open-ILS/web/templates/default/conify/global/acq/edi_account.tt2	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/templates/default/conify/global/acq/edi_account.tt2	2010-10-18 13:46:56 UTC (rev 18371)
@@ -1,4 +1,5 @@
 [% WRAPPER default/base.tt2 %]
+[% ctx.page_title = 'EDI Accounts' %]
 <script type="text/javascript" src='[% ctx.media_prefix %]/js/ui/default/conify/global/acq/edi_account.js'> </script>
 
 <script type="text/javascript">

Copied: branches/serials-integration/Open-ILS/web/templates/default/conify/global/asset/copy_template.tt2 (from rev 17886, trunk/Open-ILS/web/templates/default/conify/global/asset/copy_template.tt2)
===================================================================
--- branches/serials-integration/Open-ILS/web/templates/default/conify/global/asset/copy_template.tt2	                        (rev 0)
+++ branches/serials-integration/Open-ILS/web/templates/default/conify/global/asset/copy_template.tt2	2010-10-18 13:46:56 UTC (rev 18371)
@@ -0,0 +1,34 @@
+[% WRAPPER default/base.tt2 %]
+[% ctx.page_title = "Copy Templates" %]
+<script type="text/javascript" src="[% ctx.media_prefix %]/js/ui/default/conify/global/asset/copy_template.js"> </script>
+<div dojoType="dijit.layout.ContentPane" layoutAlign="client">
+    <div dojoType="dijit.layout.ContentPane"
+         layoutAlign="top" class="oils-header-panel">
+        <div>Copy Templates</div>
+        <div>
+            <button dojoType="dijit.form.Button"
+                onClick="actGrid.showCreateDialog()">New Copy Template</button>
+            <button dojoType="dijit.form.Button"
+                onClick="actGrid.deleteSelected()">Delete Selected</button>
+        </div>
+    </div>
+    <div class="oils-acq-basic-roomy">
+        <span>Show templates available at or above</span>
+        <select
+            dojoType="openils.widget.OrgUnitFilteringSelect"
+            jsId="actOwnerSelect"
+            searchAttr="shortname" labelAttr="shortname">
+        </select>
+    </div>
+    <table jsId="actGrid"
+        dojoType="openils.widget.AutoGrid"
+        fieldOrder="['name', 'owning_lib']"
+        suppressFields="['creator','editor','edit_date', 'create_date']"
+        query="{id: '*'}"
+        editStyle="pane"
+        fmClass="act"
+        autoHeight="true"
+        editOnEnter="true">
+    </table>
+</div>
+[% END %]

Modified: branches/serials-integration/Open-ILS/web/templates/default/conify/global/booking/resource_type.tt2
===================================================================
--- branches/serials-integration/Open-ILS/web/templates/default/conify/global/booking/resource_type.tt2	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/templates/default/conify/global/booking/resource_type.tt2	2010-10-18 13:46:56 UTC (rev 18371)
@@ -23,6 +23,7 @@
             fieldOrder="['name', 'fine_interval', 'fine_amount',
                 'owner', 'catalog_item', 'transferable']"
             suppressFields="['record']"
+            suppressEditFields="['record']"
             query="{id: '*'}"
             fmClass='brt'
             showPaginator='true'

Copied: branches/serials-integration/Open-ILS/web/templates/default/conify/global/config/rule_age_hold_protect.tt2 (from rev 17886, trunk/Open-ILS/web/templates/default/conify/global/config/rule_age_hold_protect.tt2)
===================================================================
--- branches/serials-integration/Open-ILS/web/templates/default/conify/global/config/rule_age_hold_protect.tt2	                        (rev 0)
+++ branches/serials-integration/Open-ILS/web/templates/default/conify/global/config/rule_age_hold_protect.tt2	2010-10-18 13:46:56 UTC (rev 18371)
@@ -0,0 +1,27 @@
+[% WRAPPER default/base.tt2 %]
+[% ctx.page_title = 'Age Hold Protect Rules' %]
+<script type="text/javascript">
+    dojo.require('openils.Util');
+    dojo.require('openils.widget.AutoGrid');
+    openils.Util.addOnLoad( function() { ruleAgeProtectGrid.loadAll(); } );
+</script>
+<div dojoType="dijit.layout.ContentPane" layoutAlign="client">
+    <div dojoType="dijit.layout.ContentPane" layoutAlign="top" class='oils-header-panel'>
+        <div>Age Hold Protect Rules</div>
+        <div>
+            <button dojoType='dijit.form.Button' onClick='ruleAgeProtectGrid.showCreateDialog()'>New Age Hold Protect Rule</button>
+            <button dojoType='dijit.form.Button' onClick='ruleAgeProtectGrid.deleteSelected()'>Delete Selected</button>
+        </div>
+    </div>
+    <div>
+    <table  jsId="ruleAgeProtectGrid"
+            dojoType="openils.widget.AutoGrid"
+            fieldOrder="['name', 'age', 'prox']"
+            suppressFields="['id']"
+            query="{id: '*'}"
+            fmClass='crahp'
+            editOnEnter='true'/>
+</div>
+[% END %]
+
+

Copied: branches/serials-integration/Open-ILS/web/templates/default/conify/global/config/rule_circ_duration.tt2 (from rev 17886, trunk/Open-ILS/web/templates/default/conify/global/config/rule_circ_duration.tt2)
===================================================================
--- branches/serials-integration/Open-ILS/web/templates/default/conify/global/config/rule_circ_duration.tt2	                        (rev 0)
+++ branches/serials-integration/Open-ILS/web/templates/default/conify/global/config/rule_circ_duration.tt2	2010-10-18 13:46:56 UTC (rev 18371)
@@ -0,0 +1,27 @@
+[% WRAPPER default/base.tt2 %]
+[% ctx.page_title = 'Circ Duration Rules' %]
+<script type="text/javascript">
+    dojo.require('openils.Util');
+    dojo.require('openils.widget.AutoGrid');
+    openils.Util.addOnLoad( function() { ruleCircDurationGrid.loadAll(); } );
+</script>
+<div dojoType="dijit.layout.ContentPane" layoutAlign="client">
+    <div dojoType="dijit.layout.ContentPane" layoutAlign="top" class='oils-header-panel'>
+        <div>Circ Duration Rules</div>
+        <div>
+            <button dojoType='dijit.form.Button' onClick='ruleCircDurationGrid.showCreateDialog()'>New Duration Rule</button>
+            <button dojoType='dijit.form.Button' onClick='ruleCircDurationGrid.deleteSelected()'>Delete Selected</button>
+        </div>
+    </div>
+    <div>
+    <table  jsId="ruleCircDurationGrid"
+            dojoType="openils.widget.AutoGrid"
+            fieldOrder="['name', 'max_renewals', 'shrt', 'normal', 'extended']"
+            suppressFields="['id']"
+            query="{id: '*'}"
+            fmClass='crcd'
+            editOnEnter='true'/>
+</div>
+[% END %]
+
+

Copied: branches/serials-integration/Open-ILS/web/templates/default/conify/global/config/rule_max_fine.tt2 (from rev 17886, trunk/Open-ILS/web/templates/default/conify/global/config/rule_max_fine.tt2)
===================================================================
--- branches/serials-integration/Open-ILS/web/templates/default/conify/global/config/rule_max_fine.tt2	                        (rev 0)
+++ branches/serials-integration/Open-ILS/web/templates/default/conify/global/config/rule_max_fine.tt2	2010-10-18 13:46:56 UTC (rev 18371)
@@ -0,0 +1,27 @@
+[% WRAPPER default/base.tt2 %]
+[% ctx.page_title = 'Circ Max Fine Rules' %]
+<script type="text/javascript">
+    dojo.require('openils.Util');
+    dojo.require('openils.widget.AutoGrid');
+    openils.Util.addOnLoad( function() { ruleMaxFineGrid.loadAll(); } );
+</script>
+<div dojoType="dijit.layout.ContentPane" layoutAlign="client">
+    <div dojoType="dijit.layout.ContentPane" layoutAlign="top" class='oils-header-panel'>
+        <div>Circ Max Fine Rules</div>
+        <div>
+            <button dojoType='dijit.form.Button' onClick='ruleMaxFineGrid.showCreateDialog()'>New Max Fine Rule</button>
+            <button dojoType='dijit.form.Button' onClick='ruleMaxFineGrid.deleteSelected()'>Delete Selected</button>
+        </div>
+    </div>
+    <div>
+    <table  jsId="ruleMaxFineGrid"
+            dojoType="openils.widget.AutoGrid"
+            fieldOrder="['name', 'amount', 'is_percent']"
+            suppressFields="['id']"
+            query="{id: '*'}"
+            fmClass='crmf'
+            editOnEnter='true'/>
+</div>
+[% END %]
+
+

Copied: branches/serials-integration/Open-ILS/web/templates/default/conify/global/config/rule_recurring_fine.tt2 (from rev 17886, trunk/Open-ILS/web/templates/default/conify/global/config/rule_recurring_fine.tt2)
===================================================================
--- branches/serials-integration/Open-ILS/web/templates/default/conify/global/config/rule_recurring_fine.tt2	                        (rev 0)
+++ branches/serials-integration/Open-ILS/web/templates/default/conify/global/config/rule_recurring_fine.tt2	2010-10-18 13:46:56 UTC (rev 18371)
@@ -0,0 +1,27 @@
+[% WRAPPER default/base.tt2 %]
+[% ctx.page_title = 'Recurring Fine Rules' %]
+<script type="text/javascript">
+    dojo.require('openils.Util');
+    dojo.require('openils.widget.AutoGrid');
+    openils.Util.addOnLoad( function() { ruleRecurringFineGrid.loadAll(); } );
+</script>
+<div dojoType="dijit.layout.ContentPane" layoutAlign="client">
+    <div dojoType="dijit.layout.ContentPane" layoutAlign="top" class='oils-header-panel'>
+        <div>Recurring Fine Rules</div>
+        <div>
+            <button dojoType='dijit.form.Button' onClick='ruleRecurringFineGrid.showCreateDialog()'>New Recurring Fine Rule</button>
+            <button dojoType='dijit.form.Button' onClick='ruleRecurringFineGrid.deleteSelected()'>Delete Selected</button>
+        </div>
+    </div>
+    <div>
+    <table  jsId="ruleRecurringFineGrid"
+            dojoType="openils.widget.AutoGrid"
+            fieldOrder="['name', 'recurrence_interval', 'low', 'normal', 'high']"
+            suppressFields="['id']"
+            query="{id: '*'}"
+            fmClass='crrf'
+            editOnEnter='true'/>
+</div>
+[% END %]
+
+

Copied: branches/serials-integration/Open-ILS/web/templates/default/serial (from rev 17886, trunk/Open-ILS/web/templates/default/serial)

Modified: branches/serials-integration/Open-ILS/web/templates/default/vandelay/inc/item_attrs.tt2
===================================================================
--- branches/serials-integration/Open-ILS/web/templates/default/vandelay/inc/item_attrs.tt2	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/web/templates/default/vandelay/inc/item_attrs.tt2	2010-10-18 13:46:56 UTC (rev 18371)
@@ -4,7 +4,7 @@
 
 <div dojoType="dijit.layout.ContentPane" layoutAlign="client">
     <div dojoType="dijit.layout.ContentPane" layoutAlign="top" class='oils-header-panel'>
-        <div>Import Item Attrbute Definitions</div>
+        <div>Import Item Attribute Definitions</div>
         <div>
             <button dojoType='dijit.form.Button' onClick='itemAttrGrid.showCreateDialog()'>New Definition</button>
             <button dojoType='dijit.form.Button' onClick='itemAttrGrid.deleteSelected()'>Delete Selected</button>

Modified: branches/serials-integration/Open-ILS/xsl/ATOM2XHTML.xsl
===================================================================
--- branches/serials-integration/Open-ILS/xsl/ATOM2XHTML.xsl	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/xsl/ATOM2XHTML.xsl	2010-10-18 13:46:56 UTC (rev 18371)
@@ -412,18 +412,18 @@
 		<xsl:if test="$itemrights"><dd class="rights"><xsl:call-template name="showtext"><xsl:with-param name="node" select="$itemrights" /></xsl:call-template></dd></xsl:if>
 
         <!-- item count -->
-        <xsl:if test="h:volumes">
-            <xsl:if test="h:volumes/h:volume/h:copies/h:copy">
+        <xsl:if test="h:holdings/h:volumes">
+            <xsl:if test="h:holdings/h:volumes/h:volume/h:copies/h:copy">
                 <dd>
-                    <xsl:value-of select="$t-availcopies"/><xsl:value-of select="count(h:volumes/h:volume/h:copies/h:copy/h:status[@ident='0' or @ident='7' or @ident='12'])"/>
+                    <xsl:value-of select="$t-availcopies"/><xsl:value-of select="count(h:holdings/h:volumes/h:volume/h:copies/h:copy/h:status[@ident='0' or @ident='7' or @ident='12'])"/>
                     <span> / </span>
-                    <xsl:value-of select="$t-totalcopies"/><xsl:value-of select="count(h:volumes/h:volume/h:copies/h:copy)"/>
+                    <xsl:value-of select="$t-totalcopies"/><xsl:value-of select="count(h:holdings/h:volumes/h:volume/h:copies/h:copy)"/>
                 </dd>
             </xsl:if>
-            <xsl:if test="h:volumes/h:volume/h:uris/h:uri">
+            <xsl:if test="h:holdings/h:volumes/h:volume/h:uris/h:uri">
                 <dd>
                     <xsl:value-of select="$t-onlineresources"/>
-		    	    <xsl:for-each select="h:volumes/h:volume/h:uris/h:uri">
+		    	    <xsl:for-each select="h:holdings/h:volumes/h:volume/h:uris/h:uri">
                         <a>
     			    	    <xsl:attribute name="href">
 	    			    	    <xsl:value-of select="@href" />

Modified: branches/serials-integration/Open-ILS/xsl/MARC21slim2HTMLCard-holdings.xsl
===================================================================
--- branches/serials-integration/Open-ILS/xsl/MARC21slim2HTMLCard-holdings.xsl	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/xsl/MARC21slim2HTMLCard-holdings.xsl	2010-10-18 13:46:56 UTC (rev 18371)
@@ -33,7 +33,7 @@
      <xsl:apply-templates select="xhtml:abbr[@class='unapi-id']"/>
     </div>
     <br/>
-    <xsl:apply-templates select="hold:volumes"/>
+    <xsl:apply-templates select="hold:holdings/hold:volumes"/>
     <br/>
   </xsl:template>
 

Modified: branches/serials-integration/Open-ILS/xul/staff_client/Makefile.am
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/Makefile.am	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/xul/staff_client/Makefile.am	2010-10-18 13:46:56 UTC (rev 18371)
@@ -4,14 +4,28 @@
 #---------------------------------------------------------
 
 export STAFF_CLIENT_BUILD_ID = $$(/bin/cat build/BUILD_ID)
+export STAFF_CLIENT_VERSION = $$(/bin/cat build/VERSION)
+export STAFF_CLIENT_STAMP_ID = $$(/bin/cat build/STAMP_ID)
 
 # from http://closure-compiler.googlecode.com/files/compiler-latest.zip  FIXME: Autotools this?
 export CLOSURE_COMPILER_JAR = ~/closure-compiler/compiler.jar
+XULRUNNER_VERSION=1.9.1.11
+XULRUNNER_WINFILE=xulrunner-$(XULRUNNER_VERSION).en-US.win32.zip
+XULRUNNER_LINUXFILE=xulrunner-$(XULRUNNER_VERSION).en-US.linux-i686.tar.bz2
+XULRUNNER_URL=http://releases.mozilla.org/pub/mozilla.org/xulrunner/releases/$(XULRUNNER_VERSION)/runtimes/
 
 OPENSRF_JSLIBS = "$(OPENSRF_LIBS)/javascript"
 CHROME_LOCALES = $$(ls -1 chrome/locale)
 SKIN_CSS = $$(ls -1 server/skin/*css | sed -e "s/.css/_custom.css/")
+UPDATESDIR=@localstatedir@/updates
 
+SVN=svn # Because some people might need to override this to 'git svn' or something
+
+export NSIS_EXTRAOPTS
+export NSIS_WICON=$$(if [ -f client/evergreen.ico ]; then echo '-DWICON'; fi)
+export NSIS_AUTOUPDATE=$$([ -f client/defaults/preferences/autoupdate.js ] && echo '-DAUTOUPDATE')
+export NSIS_DEV=$$([ -f client/defaults/preferences/developers.js ] && echo '-DDEVELOPER')
+
 #------------------------------
 # Build ILS XUL CLIENT/SERVER
 #------------------------------
@@ -26,12 +40,6 @@
 	@echo ' * Copying in developer preferences'
 	@cp external/developers.js build/defaults/preferences/
 
-extension: build
-	@echo ' * Packaging as an XPI'
-	@perl -ne '@f = split /\s+/; if (/open_ils_staff_client/) { if (! /chrome:\/\/open_ils_staff_client/) { $$f[ scalar(@f) - 1 ] = "chrome/" . $$f[ scalar(@f) - 1 ]; }; print join(" ", at f) . "\n"; }' build/chrome/chrome.manifest > build/chrome.manifest
-	@(cd build/ && zip -q -r evergreen.xpi * -x server/\* -x defaults/preferences/standalone_xul_app.js)
-	@md5sum build/evergreen.xpi > build/evergreen.xpi.md5
-
 build: build_dir chrome2remote localize_manifest generated custom_skins open-ils stamp 
 	@echo To test the staff client:
 	@echo "  cd build/"
@@ -46,13 +54,14 @@
 	@cp -fR defaults build/
 	@cp -fR components build/
 	@cp application.ini build/
-	@cp install.rdf build/
+	@if [ -f "install.mccoy.rdf" ]; then cp install.mccoy.rdf build/install.rdf; else cp install.rdf build/; fi
 	@cp -fR build/chrome/content/util/ build/server/
 	@cp -fR build/chrome/content/auth/ build/server/
 	@cp build/chrome/content/main/constants.js build/server/main/constants.js
 	@cp build/chrome/content/main/bindings.xml build/server/main/bindings.xml
 	@cp build/chrome/content/OpenILS/data.js build/server/OpenILS/data.js
 	@cp build/chrome/content/OpenILS/global_util.js build/server/OpenILS/global_util.js
+	@if [ -d branding ]; then copy -fR branding/* build/; fi
 	@external/prune_dirs.sh build/
 
 # Convert chrome to remote for server localization
@@ -67,18 +76,48 @@
 		if [ "$$loc" != "en-US" ]; then ( echo "locale open_ils_staff_client $$loc locale/$$loc/" >> build/chrome/chrome.manifest ) ; fi; \
 	done;
 
+# On this page:
+# https://developer.mozilla.org/en/xul_application_packaging
+# The Documentation states:
+# BUILD ID should be a unique build identifier, usually date based, and should be different for each released version
+# VERSION should be in a format as described here:
+# https://developer.mozilla.org/en/Toolkit_version_format
+
+# The default "automatic" BUILD ID is acceptable.
+
+# The version from the README usually conforms to that documentation, unless it is trunk.
+# If we are in trunk, we probably have svn kicking around, ask it for the revision and build an appropriate version string.
+
+# Neither really applies to the STAMP, though.
+# The method below gives the same format STAMPS as previous instructions provided. If README has version 1.2.3.4 then STAMP_ID will become rel_1_2_3_4.
+# Trunk VERSION will end up with 0trunk.release, trunk STAMP ID will be 0trunk_release.
 stamp:
 	@/bin/date +"%Y%m%d.%H%M%S" > build/BUILD_ID
 	@if [ -n "${STAFF_CLIENT_BUILD_ID}" ]; then ( echo "Stamping with Build ID: ${STAFF_CLIENT_BUILD_ID}" ; echo ${STAFF_CLIENT_BUILD_ID} > build/BUILD_ID ) ; fi
 	@if [ -z "${STAFF_CLIENT_BUILD_ID}" ]; then ( echo "No Build ID for versioning" ; echo "none" > build/BUILD_ID ) ; fi
-	@if [ -n "${STAFF_CLIENT_BUILD_ID}" ]; then sed -i s/^Version=.\*/Version=${STAFF_CLIENT_BUILD_ID}/ build/application.ini ; fi
-	@if [ -n "${STAFF_CLIENT_BUILD_ID}" ]; then sed -i s/^BuildID=.\*/BuildID=${STAFF_CLIENT_BUILD_ID}/ build/application.ini ; fi
-	@if [ -n "${STAFF_CLIENT_BUILD_ID}" ]; then find build/ -name '*.css' -exec sed -i s/xul\\\/server/xul\\\/${STAFF_CLIENT_BUILD_ID}\\\/server/g {} \; ; fi
-	@if [ -n "${STAFF_CLIENT_BUILD_ID}" ]; then find build/ -name '*.xul' -exec sed -i s/xul\\\/server/xul\\\/${STAFF_CLIENT_BUILD_ID}\\\/server/g {} \; ; fi
-	@if [ -n "${STAFF_CLIENT_BUILD_ID}" ]; then find build/ -name '*.html' -exec sed -i s/xul\\\/server/xul\\\/${STAFF_CLIENT_BUILD_ID}\\\/server/g {} \; ; fi
-	@if [ -n "${STAFF_CLIENT_BUILD_ID}" ]; then find build/ -name '*.xhtml' -exec sed -i s/xul\\\/server/xul\\\/${STAFF_CLIENT_BUILD_ID}\\\/server/g {} \; ; fi
-	@if [ -n "${STAFF_CLIENT_BUILD_ID}" ]; then find build/ -name '*.js' -exec sed -i s/xul\\\/server/xul\\\/${STAFF_CLIENT_BUILD_ID}\\\/server/g {} \; ; fi
-	@if [ -n "${STAFF_CLIENT_BUILD_ID}" ]; then find build/ -name '*.xml' -exec sed -i s/xul\\\/server/xul\\\/${STAFF_CLIENT_BUILD_ID}\\\/server/g {} \; ; fi
+	@sed -n -e '1 s/^.* \([^ ]*\)$$/\1/p' @top_srcdir@/README > build/VERSION
+	@if [ "${STAFF_CLIENT_VERSION}" == "trunk" ]; then echo "0trunk.$$(${SVN} info | sed -n -e 's/Last Changed Rev: \([0-9][0-9]*\)/\1/p')" > build/VERSION; fi 
+	@if [ -n "${STAFF_CLIENT_VERSION}" ]; then ( echo "Stamping with Version: ${STAFF_CLIENT_VERSION}" ; echo ${STAFF_CLIENT_VERSION} > build/VERSION ) ; fi
+	@if [ -z "${STAFF_CLIENT_VERSION}" ]; then ( echo "No Version" ; echo "none" > build/VERSION ) ; fi
+	@sed -e 's/\./_/g' -e 's/^\([0-9_]*\)$$/rel_&/' build/VERSION > build/STAMP_ID
+	@if [ -n "${STAFF_CLIENT_STAMP_ID}" ]; then ( echo "Stamping with Stamp ID: ${STAFF_CLIENT_STAMP_ID}" ; echo ${STAFF_CLIENT_STAMP_ID} > build/STAMP_ID ) ; fi
+	@if [ -z "${STAFF_CLIENT_STAMP_ID}" ]; then ( echo "No Stamp ID for versioning" ; echo "none" > build/STAMP_ID ) ; fi
+	@if [ -n "${STAFF_CLIENT_VERSION}" ]; then sed -i -e s/^Version=.\*/Version=${STAFF_CLIENT_VERSION}/ build/application.ini ; fi
+	@if [ -n "${STAFF_CLIENT_VERSION}" ]; then sed -i -e "s|<em:version>.*</em:version>|<em:version>${STAFF_CLIENT_VERSION}</em:version>|" build/install.rdf ; fi
+	@if [ -n "${STAFF_CLIENT_VERSION}" ]; then find build/ -name 'constants.js' -exec sed -i -e "s/\(CLIENT_VERSION *= '\)'/\1${STAFF_CLIENT_VERSION}'/" {} \; ; fi
+	@if [ -n "${STAFF_CLIENT_BUILD_ID}" ]; then sed -i -e s/^BuildID=.\*/BuildID=${STAFF_CLIENT_BUILD_ID}/ build/application.ini ; fi
+	@if [ -n "${STAFF_CLIENT_STAMP_ID}" ]; then find build/ -name '*.css' -exec sed -i -e s/xul\\\/server/xul\\\/${STAFF_CLIENT_STAMP_ID}\\\/server/g {} \; ; fi
+	@if [ -n "${STAFF_CLIENT_STAMP_ID}" ]; then find build/ -name '*.xul' -exec sed -i -e s/xul\\\/server/xul\\\/${STAFF_CLIENT_STAMP_ID}\\\/server/g {} \; ; fi
+	@if [ -n "${STAFF_CLIENT_STAMP_ID}" ]; then find build/ -name '*.html' -exec sed -i -e s/xul\\\/server/xul\\\/${STAFF_CLIENT_STAMP_ID}\\\/server/g {} \; ; fi
+	@if [ -n "${STAFF_CLIENT_STAMP_ID}" ]; then find build/ -name '*.xhtml' -exec sed -i -e s/xul\\\/server/xul\\\/${STAFF_CLIENT_STAMP_ID}\\\/server/g {} \; ; fi
+	@if [ -n "${STAFF_CLIENT_STAMP_ID}" ]; then find build/ -name '*.js' -exec sed -i -e s/xul\\\/server/xul\\\/${STAFF_CLIENT_STAMP_ID}\\\/server/g {} \; ; fi
+	@if [ -n "${STAFF_CLIENT_STAMP_ID}" ]; then find build/ -name '*.xml' -exec sed -i -e s/xul\\\/server/xul\\\/${STAFF_CLIENT_STAMP_ID}\\\/server/g {} \; ; fi
+	@if [ -n "${STAFF_CLIENT_STAMP_ID}" ]; then find build/ -name 'constants.js' -exec sed -i -e "s/\(CLIENT_STAMP *= '\)'/\1${STAFF_CLIENT_STAMP_ID}'/" {} \; ; fi
+	@if [ -z "${AUTOUPDATE_HOST}" ]; then rm -f build/defaults/preferences/autoupdate.js; fi
+	@if [ -z "${AUTOUPDATE_HOST}" ]; then sed -i -e /updateURL/d build/install.rdf; fi
+	@if [ -n "${AUTOUPDATE_HOST}" ]; then echo "Applying automatic update host ${AUTOUPDATE_HOST}"; fi
+	@if [ -n "${AUTOUPDATE_HOST}" ]; then sed -i -e "s|::HOSTNAME::|${AUTOUPDATE_HOST}|" -e "s|https\?://\(https\?://\)|\1|" build/defaults/preferences/autoupdate.js; fi
+	@if [ -n "${AUTOUPDATE_HOST}" ]; then sed -i -e "s|::HOSTNAME::|${AUTOUPDATE_HOST}|" -e "s|https\?://\(https\?://\)|\1|" build/install.rdf; fi
 
 bell:
 	@perl -e 'print "Ringing bell..." . chr(7) . "\n";'
@@ -104,14 +143,17 @@
 		if [ ! -f "$$skin" ]; then ( touch build/"$$skin" ); fi \
 	done;
 
-server-xul: build
+needwebdir:
+	@if [ -z "$(WEBDIR)" ]; then echo "!!!--------!!!"; echo "WEBDIR is not set. Must use top level Makefile or set WEBDIR to use this target."; echo "!!!--------!!!"; exit 1; fi
+
+server-xul: needwebdir build
 	@echo $@
 	mkdir -p $(WEBDIR)
 	mkdir -p $(WEBDIR)/xul/
-	@echo "BUILD_ID = $(STAFF_CLIENT_BUILD_ID)"
-	@echo "Copying xul into $(WEBDIR)/xul/$(STAFF_CLIENT_BUILD_ID)"
-	mkdir -p "$(WEBDIR)/xul/$(STAFF_CLIENT_BUILD_ID)"
-	cp -R @top_srcdir@/Open-ILS/xul/staff_client/build/server "${WEBDIR}/xul/${STAFF_CLIENT_BUILD_ID}/"
+	@echo "STAMP_ID = $(STAFF_CLIENT_STAMP_ID)"
+	@echo "Copying xul into $(WEBDIR)/xul/$(STAFF_CLIENT_STAMP_ID)"
+	mkdir -p "$(WEBDIR)/xul/$(STAFF_CLIENT_STAMP_ID)"
+	cp -R @top_srcdir@/Open-ILS/xul/staff_client/build/server "${WEBDIR}/xul/${STAFF_CLIENT_STAMP_ID}/"
 
 compress-javascript: build
 	@echo "Size of build/ before compression = " `du -sh build/`
@@ -123,3 +165,102 @@
 	@find build/ -name '*.js~' -exec perl -e '$$a = "{}"; chop $$a; `mv $$a~ $$a`;' \;
 	@echo "Size of build/ (minus compression.err) after compression = " `du -sh --exclude compression.err build/`
 
+# Easy way to make all three kinds of clients
+
+clients:
+	@make win-client
+	@make linux-client
+	@make generic-client
+
+# By doing this we don't change the original build in the build folder
+# Great for adding/changing things without a full rebuild
+
+client_dir:
+	@if [ ! -f build/BUILD_ID ]; then echo 'ERROR! Current build not stamped!'; exit 1; fi
+	@echo 'Prepping Client Set'
+	@rm -rf client/
+	@mkdir -p client
+	@cp -fR build/* client/
+	@rm -rf client/server/
+	@rm -f client/build.tar*
+
+# When building as a standalone client install.rdf is a bad thing
+# as we haven't "sanitized" the client for extension use
+
+client_app: client_dir
+	@echo 'Cleaning Extension Information'
+	@rm -f client/install.rdf
+
+# If automatic updates are enabled, or the standalone_xul_app.js is present,
+# the extension can break Firefox.
+# Remove those, and we need a chrome.manifest
+
+client_ext: client_dir
+	@echo 'Cleaning App Information'
+	@rm -f client/application.ini
+	@rm -f client/defaults/preferences/autoupdate.js
+	@rm -f client/defaults/preferences/autochannel.js
+	@rm -f client/defaults/preferences/standalone_xul_app.js
+	@echo 'Prepping chrome.manifest'
+	@perl -ne 'if(/open_ils_staff_client/) { s/ (?!chrome:\/\/open_ils_staff_client)([^ ]*)$$/ chrome\/\1/; print; }' client/chrome/chrome.manifest > client/chrome.manifest
+
+# Would merge client_ext into this one, but this way an installer that doesn't
+# use an xpi can be made for extension later, if desired
+
+extension: client_ext
+	@echo ' * Packaging as an XPI'
+	@(cd client/ && zip -q -r ../evergreen.xpi * -x defaults/preferences/standalone_xul_app.js)
+	@md5sum evergreen.xpi > evergreen.xpi.md5
+
+# Generic client, as an xpi, theoretically suitable for --install-app usage
+
+generic-client: client_app
+	@echo 'Packing Generic Client via zip (as xpi file)'
+	@rm -f evergreen_staff_client.xpi
+	@cd client && zip -q -r ../evergreen_staff_client.xpi *
+	@echo done
+
+# These two targets complete the layout defined on
+# https://developer.mozilla.org/en/XULRunner/Deploying_XULRunner_1.8
+# for their respective platforms in regards to XULRunner deployment
+
+# Note that I decided to use win/lin channels for ease of coding platform specific updates
+
+win-xulrunner: client_app
+	@echo 'Preparing Windows xulrunner'
+	@if [ ! -f ${XULRUNNER_WINFILE} ]; then wget ${XULRUNNER_URL}${XULRUNNER_WINFILE}; fi
+	@unzip -q ${XULRUNNER_WINFILE} -dclient
+	@if [ -f client/defaults/preferences/autoupdate.js ]; then echo 'pref("app.update.channel","win");' >> client/defaults/preferences/autochannel.js; fi;
+	@echo 'Preparing stub'
+	@if [ -f xulrunner-stub.exe ]; then cp xulrunner-stub.exe client/evergreen.exe; rm client/xulrunner/xulrunner-stub.exe; else mv client/xulrunner/xulrunner-stub.exe client/evergreen.exe; fi
+
+linux-xulrunner: client_app
+	@echo 'Preparing Linux xulrunner'
+	@if [ ! -f ${XULRUNNER_LINUXFILE} ]; then wget ${XULRUNNER_URL}${XULRUNNER_LINUXFILE}; fi
+	@cd client; tar xjf ../${XULRUNNER_LINUXFILE}; cd ..
+	@if [ -f client/defaults/preferences/autoupdate.js ]; then echo 'pref("app.update.channel","lin");' >> client/defaults/preferences/autochannel.js; fi;
+	@echo 'Preparing stub'
+	@mv client/xulrunner/xulrunner-stub client/evergreen
+
+# Build a windows installer.
+
+win-client: win-xulrunner
+	@echo 'Building installer'
+	@makensis -DPRODUCT_VERSION="${STAFF_CLIENT_VERSION}" ${NSIS_WICON} ${NSIS_AUTOUPDATE} ${NSIS_DEV} ${NSIS_EXTRAOPTS} windowssetup.nsi
+	@echo 'Done'
+
+# For linux, just build a tar.bz2 archive
+
+linux-client: linux-xulrunner
+	@echo 'Packing as evergreen_staff_client.tar.bz2'
+	@rm -f evergreen_staff_client.tar.bz2
+	@cd client; tar cjf ../evergreen_staff_client.tar.bz2 *; cd ..
+	@echo 'Done'
+
+# For running the updates script with the correct updates directory, optionally building clients as well
+
+updates updates-client win-updates win-updates-client linux-updates linux-updates-client generic-updates generic-updates-client extension-updates:
+	@if [ ! -f build/BUILD_ID ]; then echo 'ERROR! Current build not stamped!'; exit 1; fi
+	@if [ ! -x external/make_updates.sh ]; then chmod u+x external/make_updates.sh; fi
+	@if [ ! -x external/make_updates.sh ]; then echo 'ERROR! external/make_updates.sh is not executable!'; exit 1; fi
+	@external/make_updates.sh ${UPDATESDIR} $@

Modified: branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/OpenILS/data.js
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/OpenILS/data.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/OpenILS/data.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -184,6 +184,9 @@
                 case 'acpl': 
                     found = obj.network.simple_request('FM_ACPL_RETRIEVE_VIA_ID.authoritative',[ value ]);
                 break;
+                case 'actsc':
+                    found = obj.network.simple_request('FM_ACTSC_RETRIEVE_VIA_PCRUD',[ ses(), { 'id' : { '=' : value } }]);
+                break;
                 default: return undefined; break;
             }
             if (typeof found.ilsevent != 'undefined') throw(found);
@@ -241,6 +244,56 @@
         }
     },
 
+    'load_saved_print_templates' : function() {
+        var obj = this;
+        try {
+            JSAN.use('util.file'); var file = new util.file('print_list_templates');
+            if (file._file.exists()) {
+                try {
+                    var x = file.get_object();
+                    if (x) {
+                        for (var i in x) {
+                            obj.print_list_templates[i] = x[i];
+                        }
+                        obj.stash('print_list_templates');
+                        obj.data_progress('Saved print templates retrieved from file. ');
+                    }
+                } catch(E) {
+                    alert(E);
+                }
+            }
+            file.close();
+        } catch(E) {
+            alert("Error in OpenILS.data, load_saved_print_templates(): " + E);
+        }
+    },
+
+    'fetch_print_strategy' : function() {
+        var obj = this;
+        try {
+            obj.print_strategy = {};
+            var print_contexts = [ 'default', 'receipt', 'label', 'mail', 'offline' ];
+            for (var i in print_contexts) {
+                JSAN.use('util.file'); var file = new util.file('print_strategy.' + print_contexts[i]);
+                if (file._file.exists()) {
+                    try {
+                        var x = file.get_content();
+                        if (x) {
+                            obj.print_strategy[ print_contexts[i] ] = x;
+                            obj.data_progress('Print strategy ' + print_contexts[i] + ' retrieved from file. ');
+                        }
+                    } catch(E) {
+                        alert(E);
+                    }
+                }
+                file.close();
+            }
+            obj.stash('print_strategy');
+        } catch(E) {
+            alert('Error in OpenILS.data, fetch_print_strategy(): ' + E);
+        }
+    },
+
     'print_list_defaults' : function() {
         var obj = this;
         //if (typeof obj.print_list_templates == 'undefined') {
@@ -381,26 +434,6 @@
         netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
         var obj = this;
 
-
-        JSAN.use('util.file'); var file = new util.file('print_list_templates');
-        obj.print_list_defaults();
-        obj.data_progress('Default print templates set. ');
-        if (file._file.exists()) {
-            try {
-                var x = file.get_object();
-                if (x) {
-                    for (var i in x) {
-                        obj.print_list_templates[i] = x[i];
-                    }
-                    obj.stash('print_list_templates');
-                    obj.data_progress('Saved print templates retrieved from file. ');
-                }
-            } catch(E) {
-                alert(E);
-            }
-        }
-        file.close();
-
         JSAN.use('util.file'); var file = new util.file('global_font_adjust');
         if (file._file.exists()) {
             try {
@@ -431,21 +464,10 @@
         }
         file.close();
 
-        JSAN.use('util.file'); var file = new util.file('print_strategy');
-        if (file._file.exists()) {
-            try {
-                var x = file.get_content();
-                if (x) {
-                    obj.print_strategy = x;
-                    obj.stash('print_strategy');
-                    obj.data_progress('Print strategy retrieved from file. ');
-                }
-            } catch(E) {
-                alert(E);
-            }
-        }
-        file.close();
-
+        obj.print_list_defaults();
+        obj.data_progress('Default print templates set. ');
+        obj.load_saved_print_templates();
+        obj.fetch_print_strategy();
         JSAN.use('util.print'); (new util.print()).GetPrintSettings();
         obj.data_progress('Printer settings retrieved. ');
 
@@ -512,9 +534,11 @@
         this.chain.push(
             function() {
                 try {
-                    var robj = obj.network.simple_request('CIRC_MODIFIER_LIST',[]);
+                    var robj = obj.network.simple_request('CIRC_MODIFIER_LIST',[{'full':true}]);
                     if (typeof robj.ilsevent != 'undefined') throw(robj);
-                    obj.list.circ_modifier = robj;
+                    obj.list.ccm = robj == null ? [] : robj;
+                    obj.hash.ccm = util.functional.convert_object_list_to_hash( obj.list.ccm );
+                    obj.list.circ_modifier = util.functional.map_list( obj.list.ccm, function(o) { return o.code(); } );
                     obj.data_progress('Retrieved circ modifier list. ');
                 } catch(E) {
                     var error = 'Error: ' + js2JSON(E);

Modified: branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/auth/controller.js
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/auth/controller.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/auth/controller.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -388,7 +388,13 @@
                     if (x.status == 200) {
                         window.open('data:text/html,'+window.escape(x.responseText),'upgrade','chrome,resizable,modal,centered');
                     } else {
-                        alert(document.getElementById('authStrings').getString('staff.auth.controller.version_mismatch'));
+                        if(typeof(G.upgradeCheck) == "function")
+                        {
+                            if (confirm("This server does not support your version of the staff client, an upgrade may be required. If you wish to check for an upgrade please press Ok. Otherwise please press cancel."))
+                                G.upgradeCheck();
+                        } else {
+                            alert(document.getElementById('authStrings').getString('staff.auth.controller.version_mismatch'));
+                        }
                     }
                     obj.controller.view.server_prompt.disabled = false;
                 } catch(E) {

Modified: branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/auth/session.js
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/auth/session.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/auth/session.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -26,6 +26,7 @@
             );
 
             if (init) {
+                if (xulG._data) { delete xulG._data; } // quick kludge; we were re-using a poisoned OpenILS.data (from ws_info.xul?) where js2JSON (and maybe other stuff) does not exist
                 JSAN.use('OpenILS.data'); var data = new OpenILS.data(); data.stash_retrieve();
 
                 var params = { 

Modified: branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/cat/opac.js
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/cat/opac.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/cat/opac.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -4,7 +4,6 @@
 var marc_edit_reset = true;
 var copy_browser_reset = true;
 var hold_browser_reset = true;
-var acq_orders_reset = true;
 var serctrl_view_reset = true;
 
 function $(id) { return document.getElementById(id); }
@@ -122,7 +121,7 @@
     var a =    xulG.url_prefix( urls.XUL_MARC_EDIT );
     var b =    {};
     var c =    {
-            'record' : { 'url' : '/opac/extras/supercat/retrieve/marcxml/record/' + docid },
+            'record' : { 'url' : '/opac/extras/supercat/retrieve/marcxml/record/' + docid, "id": docid, "rtype": "bre" },
             'fast_add_item' : function(doc_id,cn_label,cp_barcode) {
                 try {
                     var cat = { util: {} }; /* FIXME: kludge since we can't load remote JSAN libraries into chrome */
@@ -269,19 +268,74 @@
     bottom_pane.get_contentWindow().addEventListener('load',opac_wrapper_set_help_context,false);
 }
 
-function set_acq_orders() {
-    g.view = 'acq_orders';
-    var url = xulG.url_prefix( '/eg/acq/lineitem/related/' ) + window.escape(docid) + '?target=bib';
-    if (acq_orders_reset) {
-        bottom_pane.reset_iframe(url,{},xulG);
-        acq_orders_reset = false;
-    } else {
-        bottom_pane.set_iframe(url,{},xulG);
+
+function open_acq_orders() {
+    try {
+        var content_params = {
+            "session": ses(),
+            "authtime": ses("authtime"),
+            "no_xulG": false,
+            "show_nav_buttons": true,
+            "show_print_button": false
+        };
+
+        ["url_prefix", "new_tab", "set_tab", "close_tab", "new_patron_tab",
+            "set_patron_tab", "volume_item_creator", "get_new_session",
+            "holdings_maintenance_tab", "set_tab_name", "open_chrome_window",
+            "url_prefix", "network_meter", "page_meter", "set_statusbar",
+            "set_help_context"
+        ].forEach(function(k) { content_params[k] = xulG[k]; });
+
+        var loc = urls.XUL_BROWSER + "?url=" + window.escape(
+            xulG.url_prefix("/eg/acq/lineitem/related/") +
+            docid + "?target=bib"
+        );
+        xulG.new_tab(
+            loc, {
+                "tab_name": $("offlineStrings").getString(
+                    "staff.cat.opac.related_items"
+                ),
+                "browser": false
+            }, content_params
+        );
+    } catch (E) {
+        g.error.sdump("D_ERROR", E);
     }
-    opac_wrapper_set_help_context(); 
-    bottom_pane.get_contentWindow().addEventListener('load',opac_wrapper_set_help_context,false);
 }
 
+function open_alt_serial_mgmt() {
+    try {
+        var content_params = {
+            "session": ses(),
+            "authtime": ses("authtime"),
+            "show_nav_buttons": true,
+            "no_xulG": false,
+            "show_print_button": false
+        };
+
+        ["url_prefix", "new_tab", "set_tab", "close_tab", "new_patron_tab",
+            "set_patron_tab", "volume_item_creator", "get_new_session",
+            "holdings_maintenance_tab", "set_tab_name", "open_chrome_window",
+            "url_prefix", "network_meter", "page_meter", "set_statusbar",
+            "set_help_context"
+        ].forEach(function(k) { content_params[k] = xulG[k]; });
+
+        var loc = urls.XUL_BROWSER + "?url=" + window.escape(
+            xulG.url_prefix("/eg/serial/list_subscription/") + docid
+        );
+        xulG.new_tab(
+            loc, {
+                "tab_name": $("offlineStrings").getString(
+                    "staff.cat.opac.serial_alt_mgmt"
+                ),
+                "browser": false
+            }, content_params
+        );
+    } catch (E) {
+        g.error.sdump("D_ERROR", E);
+    }
+}
+
 function set_opac() {
     g.view = 'opac';
     try {
@@ -545,6 +599,30 @@
     }
 }
 
+function batch_receive_in_new_tab() {
+    try {
+        var content_params = {"session": ses(), "authtime": ses("authtime")};
+
+        ["url_prefix", "new_tab", "set_tab", "close_tab", "new_patron_tab",
+            "set_patron_tab", "volume_item_creator", "get_new_session",
+            "holdings_maintenance_tab", "set_tab_name", "open_chrome_window",
+            "url_prefix", "network_meter", "page_meter", "set_statusbar",
+            "set_help_context"
+        ].forEach(function(k) { content_params[k] = xulG[k]; });
+
+        xulG.new_tab(
+            xulG.url_prefix(urls.XUL_SERIAL_BATCH_RECEIVE) +
+                "?docid=" + window.escape(docid), {
+                "tab_name": $("offlineStrings").getString(
+                    "menu.cmd_serial_batch_receive.tab"
+                )
+            }, content_params
+        );
+    } catch (E) {
+        g.error.sdump("D_ERROR", E);
+    }
+}
+
 function remove_me() {
     var url = xulG.url_prefix( urls.XUL_BIB_BRIEF ) + '?docid=' + window.escape(docid);
     dump('removing ' + url + '\n');
@@ -667,7 +745,6 @@
         marc_edit_reset = true;
         copy_browser_reset = true;
         hold_browser_reset = true;
-        acq_orders_reset = true;
         while(top_pane.node.lastChild) top_pane.node.removeChild( top_pane.node.lastChild );
         var children = bottom_pane.node.childNodes;
         for (var i = 0; i < children.length; i++) {
@@ -690,7 +767,6 @@
             case 'marc_edit' : set_marc_edit(); break;
             case 'copy_browser' : set_copy_browser(); break;
             case 'hold_browser' : set_hold_browser(); break;
-            case 'acq_orders' : set_acq_orders(); break;
             case 'serctrl_view' : set_serctrl_view(); break;
             case 'opac' :
             default: set_opac(); break;

Modified: branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/cat/opac.xul
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/cat/opac.xul	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/cat/opac.xul	2010-10-18 13:46:56 UTC (rev 18371)
@@ -49,7 +49,7 @@
                 <menuitem label="&staff.cat.opac.marc_edit.label;" accesskey="&staff.cat.opac.marc_edit.accesskey;" id="marc_edit" oncommand="set_marc_edit();"/>
                 <menuitem label="&staff.cat.opac.copy_browse.label;" accesskey="&staff.cat.opac.copy_browse.accesskey;" id="copy_browse" oncommand="set_copy_browser();"/>
                 <menuitem label="&staff.cat.opac.view_holds.label;" accesskey="&staff.cat.opac.view_holds.accesskey;" id="view_holds" oncommand="set_hold_browser();"/>
-                <menuitem label="&staff.cat.opac.view_orders.label;" accesskey="&staff.cat.opac.view_orders.accesskey;" id="view_orders" oncommand="set_acq_orders();"/>
+                <menuitem label="&staff.cat.opac.view_orders.label;" accesskey="&staff.cat.opac.view_orders.accesskey;" id="view_orders" oncommand="open_acq_orders();"/>
                 <menuseparator/>
                 <menuitem label="&staff.cat.opac.add_bucket.label;" accesskey="&staff.cat.opac.add_bucket.accesskey;" id="add_bucket" oncommand="add_to_bucket();"/>
                 <menuitem label="&staff.cat.opac.mark_for_overlay.label;" accesskey="&staff.cat.opac.mark_for_overlay.accesskey;" id="mark_for_overlay" oncommand="mark_for_overlay();"/>
@@ -73,7 +73,9 @@
                         <menu id="mfhd_delete" label="&staff.serial.mfhd_menu.delete.label;"/>
                     </menupopup>
                 </menu>
-                <menuitem id="serctrl_view" label="&staff.serial.serctrl_view.label;" oncommand="set_serctrl_view();"/>
+                <menuitem id="serctrl_view" label="&staff.serial.serctrl_view.label;" oncommand="set_serctrl_view();" />
+                <menuitem label="&staff.cat.opac.alt_serial.label;" accesskey="&staff.cat.opac.alt_serial.accesskey;" id="alt_serial" oncommand="open_alt_serial_mgmt();" />
+                <menuitem label="&staff.cat.opac.batch_receive.label;" accesskey="&staff.cat.opac.batch_receive.accesskey;" id="batch_receive" oncommand="batch_receive_in_new_tab();"/>
                 </menupopup>
                 </menu>
             </menubar>

Modified: branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/circ/offline.js
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/circ/offline.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/circ/offline.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -52,7 +52,7 @@
                         'cmd_print_last_receipt' : [
                             ['command'],
                             function() { 
-                                JSAN.use('util.print'); var print = new util.print();
+                                JSAN.use('util.print'); var print = new util.print('offline');
                                 print.reprint_last();
                             }
                         ],
@@ -74,55 +74,11 @@
     },
 
     'receipt_init' : function() {
-        function backup_receipt_templates() {
-            data.print_list_templates = {
-                'offline_checkout' : {
-                    'type' : 'offline_checkout',
-                    'header' : 'Patron %patron_barcode%<br/>\r\nYou checked out the following items:<hr/><ol>',
-                    'line_item' : '<li>Barcode: %barcode%<br/>\r\nDue: %due_date%\r\n',
-                    'footer' : '</ol><hr />%TODAY_TRIM%<br/>\r\n<br/>\r\n',
-                },
-                'offline_checkin' : {
-                    'type' : 'offline_checkin',
-                    'header' : 'You checked in the following items:<hr/><ol>',
-                    'line_item' : '<li>Barcode: %barcode%\r\n',
-                    'footer' : '</ol><hr />%TODAY_TRIM%<br/>\r\n<br/>\r\n',
-                },
-                'offline_renew' : {
-                    'type' : 'offline_renew',
-                    'header' : 'You renewed the following items:<hr/><ol>',
-                    'line_item' : '<li>Barcode: %barcode%\r\n',
-                    'footer' : '</ol><hr />%TODAY_TRIM%<br/>\r\n<br/>\r\n',
-                },
-                'offline_inhouse_use' : {
-                    'type' : 'offline_inhouse_use',
-                    'header' : 'You marked the following in-house items used:<hr/><ol>',
-                    'line_item' : '<li>Barcode: %barcode%\r\nUses: %count%',
-                    'footer' : '</ol><hr />%TODAY_TRIM%<br/>\r\n<br/>\r\n',
-                },
-            };
-            data.stash('print_list_templates');
-        }
-
         JSAN.use('OpenILS.data'); var data = new OpenILS.data(); data.init({'via':'stash'});
-        JSAN.use('util.file'); var file = new util.file('print_list_templates');
-        if (file._file.exists()) {
-            try {
-                var x = file.get_object();
-                if (x) {
-                    data.print_list_templates = x;
-                    data.stash('print_list_templates');
-                } else {
-                    backup_receipt_templates();
-                }
-            } catch(E) {
-                alert(E);
-                backup_receipt_templates();
-            }
-        } else {
-            backup_receipt_templates();
-        }
-        file.close();
+        data.print_list_defaults();
+        data.load_saved_print_templates();
+        data.fetch_print_strategy();
+        JSAN.use('util.print'); (new util.print('offline')).GetPrintSettings();
     },
 
     'patron_init' : function() {

Modified: branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/circ/offline_checkin.js
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/circ/offline_checkin.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/circ/offline_checkin.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -113,6 +113,7 @@
             try {
                 var params = {
                     'template' : 'offline_checkin',
+                    'printer_context' : 'offline',
                     'callback' : function() {
                         g.list.clear();
                         var x = $('i_barcode'); x.value = ''; x.focus();

Modified: branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/circ/offline_checkout.js
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/circ/offline_checkout.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/circ/offline_checkout.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -271,6 +271,7 @@
                 var params = {
                     'patron_barcode' : $('p_barcode').value,
                     'template' : 'offline_checkout',
+                    'printer_context' : 'offline',
                     'callback' : function() {
                         g.list.clear();
                         var x = $('i_barcode'); x.value = '';

Modified: branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/circ/offline_in_house_use.js
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/circ/offline_in_house_use.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/circ/offline_in_house_use.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -116,6 +116,7 @@
             try {
                 var params = {
                     'template' : 'offline_inhouse_use',
+                    'printer_context' : 'offline',
                     'callback' : function() {
                         g.list.clear();
                         var x = $('i_barcode'); x.value = ''; x.focus();

Modified: branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/circ/offline_renew.js
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/circ/offline_renew.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/circ/offline_renew.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -226,6 +226,7 @@
                         var params = {
                             'patron_barcode' : $('p_barcode').value,
                             'template' : 'offline_renew',
+                            'printer_context' : 'offline',
                             'callback' : function() {
                                 g.list.clear();
                                 var x = $('i_barcode'); x.value = '';

Modified: branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/main/bindings.xml
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/main/bindings.xml	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/main/bindings.xml	2010-10-18 13:46:56 UTC (rev 18371)
@@ -188,6 +188,20 @@
                                 var msg = "messageCatalog: No text from " + this.src;
                                 alert(msg); throw(msg);
                             }
+                           
+                            try { // fail silently if no custom properties file exists
+                                var custom_src = String(this.src).replace(/\.properties$/,'_custom.properties'); 
+                                var x2 = new XMLHttpRequest();
+                                x2.open("GET",custom_src,false);
+                                x2.send(null);
+                                if (x2.responseText) {
+                                    var props = this._props2object(x2.responseText);
+                                    for (var i in props) {
+                                        this._props[i] = props[i];
+                                    }
+                                }
+                            } catch(EE) {}
+
                     } catch(E) {
                         alert('Error loading properties in messagecatalog in bindings.xml: ' + E);
                         throw(E);

Modified: branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/main/constants.js
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/main/constants.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/main/constants.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -36,6 +36,9 @@
 const PERMS_FILE      = 0644;
 const PERMS_DIR      = 0755;
 
+const CLIENT_VERSION = '';
+const CLIENT_STAMP   = '';
+
 var my_constants = {
     'magical_statuses' : {
         '1' : { 'disable_in_copy_editor' : true, 'block_mark_item_damaged' : false, 'block_mark_item_action' : true }, /* | Checked out    | t */
@@ -126,6 +129,7 @@
     'FM_AHR_PULL_LIST' : { 'app' : 'open-ils.circ', 'method' : 'open-ils.circ.hold_pull_list.retrieve' },
     'FM_AHR_PULL_LIST_COUNT' : { 'app' : 'open-ils.circ', 'method' : 'open-ils.circ.hold_pull_list.retrieve.count' },
     'FM_AHR_ID_LIST_PULL_LIST' : { 'app' : 'open-ils.circ', 'method' : 'open-ils.circ.hold_pull_list.id_list.retrieve', 'secure' : false },
+    'HTML_HOLD_PULL_LIST' : { 'app' : 'open-ils.circ', 'method' : 'open-ils.circ.hold_pull_list.print' },
     'FM_AHR_ONSHELF_RETRIEVE' : { 'app' : 'open-ils.circ', 'method' : 'open-ils.circ.captured_holds.on_shelf.retrieve' },
     'FM_AHR_ID_LIST_ONSHELF_RETRIEVE' : { 'app' : 'open-ils.circ', 'method' : 'open-ils.circ.captured_holds.id_list.on_shelf.retrieve', 'secure' : false },
     'FM_AHR_ID_LIST_EXPIRED_ONSHELF_RETRIEVE' : { 'app' : 'open-ils.circ', 'method' : 'open-ils.circ.captured_holds.id_list.expired_on_shelf.retrieve', 'secure' : false },
@@ -355,6 +359,7 @@
     'AUDIO_circ_bad' : '/xul/server/skin/media/audio/question.wav',
     'AUDIO_event_ASSET_COPY_NOT_FOUND' : '/xul/server/skin/media/audio/redalert.wav',
 
+    'AUTHORITY_MANAGE' : '/eg/cat/authority/list',
     'XUL_AUTH_SIMPLE' : '/xul/server/main/simple_auth.xul',
     'XUL_BIB_BRIEF' : '/xul/server/cat/bib_brief.xul',
     'XUL_BROWSER' : 'chrome://open_ils_staff_client/content/util/browser.xul',
@@ -389,6 +394,7 @@
     'XUL_IN_HOUSE_USE' : '/xul/server/circ/in_house_use.xul',
     'XUL_LIST_CLIPBOARD' : '/xul/server/util/list_clipboard.xul',
     'XUL_LOCAL_ADMIN' : '/xul/server/admin/index.xhtml',
+    'XUL_LOGIN_DATA' : '/xul/server/main/data.xul', 
     'XUL_MARC_NEW' : '/xul/server/cat/marc_new.xul',
     'XUL_MARC_EDIT' : '/xul/server/cat/marcedit.xul',
     'XUL_MARC_VIEW' : '/xul/server/cat/marc_view.xul',
@@ -450,6 +456,7 @@
     'XUL_VOLUME_COPY_CREATOR' : '/xul/server/cat/volume_copy_creator.xul',
     'XUL_VOLUME_EDITOR' : '/xul/server/cat/volume_editor.xul',
     'XUL_WORK_LOG' : '/xul/server/admin/work_log.xul',
+    'XUL_WORKSTATION_INFO' : '/xul/server/main/ws_info.xul',
     'XUL_Z3950_IMPORT' : '/xul/server/cat/z3950.xul',
     'TEST_HTML' : '/xul/server/main/test.html',
     'TEST_XUL' : '/xul/server/main/test.xul',
@@ -457,5 +464,6 @@
     'EG_WEB_BASE' : '/eg',
     'XUL_LOCAL_ADMIN_BASE' : '/xul/server/admin',
     'XUL_REPORTS' : '/reports/oils_rpt.xhtml',
-    'EG_ACQ_PO_VIEW' : '/eg/acq/po/view'
+    'EG_ACQ_PO_VIEW' : '/eg/acq/po/view',
+    'XUL_SERIAL_BATCH_RECEIVE': '/xul/server/serial/batch_receive.xul'
 }

Modified: branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/main/main.js
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/main/main.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/main/main.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -162,7 +162,7 @@
                 var deck = document.getElementById('progress_space');
                 util.widgets.remove_children( deck );
                 var iframe = document.createElement('iframe'); deck.appendChild(iframe);
-                iframe.setAttribute( 'src', url + '/xul/server/main/data.xul' );
+                iframe.setAttribute( 'src', url + urls.XUL_LOGIN_DATA );
                 iframe.contentWindow.xulG = xulG;
                 G.data_xul = iframe.contentWindow;
             } else {
@@ -170,7 +170,7 @@
                 var deck = G.auth.controller.view.ws_deck;
                 JSAN.use('util.widgets'); util.widgets.remove_children('ws_deck');
                 var iframe = document.createElement('iframe'); deck.appendChild(iframe);
-                iframe.setAttribute( 'src', url + '/xul/server/main/ws_info.xul' );
+                iframe.setAttribute( 'src', url + urls.XUL_WORKSTATION_INFO );
                 iframe.contentWindow.xulG = xulG;
                 deck.selectedIndex = deck.childNodes.length - 1;
             }
@@ -224,6 +224,7 @@
                                     throw(offlineStrings.getString('main.transaction_export.filename.error'));
                                 }
                             }
+                            file.close(); file = new util.file('pending_xacts'); // prevents a bug with .moveTo below
                             file._file.moveTo(null,filename);
                         } else {
                             alert(offlineStrings.getString('main.transaction_export.duplicate.warning'));
@@ -291,8 +292,8 @@
 
         /////////////////////////////////////////////////////////////////////////////
 
-        var version = '/xul/server/'.split(/\//)[2];
-        if (version == 'server') {
+        var version = CLIENT_VERSION;
+        if (CLIENT_STAMP.length == 0) {
             version = 'versionless debug build';
             document.getElementById('debug_gb').hidden = false;
         }
@@ -304,6 +305,37 @@
         } catch(E) {
         }
 
+        var appInfo = Components.classes["@mozilla.org/xre/app-info;1"] 
+            .getService(Components.interfaces.nsIXULAppInfo); 
+
+        if (appInfo.ID == "staff-client at open-ils.org")
+        {
+            try {
+                if (G.pref && G.pref.getBoolPref('app.update.enabled')) {
+                    document.getElementById('check_upgrade_sep').hidden = false;
+                    var upgrademenu = document.getElementById('check_upgrade');
+                    upgrademenu.hidden = false;
+                    G.upgradeCheck = function () {
+                        var um = Components.classes["@mozilla.org/updates/update-manager;1"]
+                            .getService(Components.interfaces.nsIUpdateManager);
+                        var prompter = Components.classes["@mozilla.org/updates/update-prompt;1"]
+                            .createInstance(Components.interfaces.nsIUpdatePrompt);
+
+                        if (um.activeUpdate && um.activeUpdate.state == "pending")
+                            prompter.showUpdateDownloaded(um.activeUpdate);
+                        else
+                            prompter.checkForUpdates();
+                    }
+                    upgrademenu.addEventListener(
+                        'command',
+                        G.upgradeCheck,
+                        false
+                    );
+                }
+            } catch(E) {
+            }
+        }
+
         window.title = authStrings.getFormattedString('staff.auth.titlebar.label', version);
         var x = document.getElementById('about_btn');
         x.addEventListener(

Modified: branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/main/main.xul
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/main/main.xul	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/main/main.xul	2010-10-18 13:46:56 UTC (rev 18371)
@@ -22,7 +22,7 @@
     onload="try { main_init(); } catch(E) { alert(E); }"
     onunload="try { G.auth.logoff(); } catch(E) { alert(E); }"
     title="&staff.auth.title;"
-    width="640" height="480"
+    width="640" height="480" windowtype="eg_main"
     xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
 
 
@@ -92,8 +92,16 @@
     <groupbox id="main_groupbox" flex="1" style="overflow: auto;">
         <caption id="main_caption" label="&staff.main.auth.caption;"/>
         <hbox>
-            <button id="about_btn" label="&staff.auth.about_btn.label;" accesskey="&staff.auth.about_btn.accesskey;" />
+            <button type="menu" label="Help" accesskey="l">
+                <menupopup>
+                    <menuitem id="about_btn" label="&staff.auth.about_btn.label;" accesskey="&staff.auth.about_btn.accesskey;" />
+                    <menuitem id="contents_menu" label="Contents" accesskey="c" disabled="true" />
+                    <menuseparator id="check_upgrade_sep" hidden="true" />
+                    <menuitem id="check_upgrade" label="Check for upgrades" accesskey="" hidden="true" />
+                </menupopup>
+            </button>
 
+
             <button id="new_window_btn" label="&staff.auth.new_window_btn.label;" accesskey="&staff.auth.new_window_btn.accesskey;" />
 
             <label value="&staff.auth.locale.label;" accesskey="&staff.auth.locale.accesskey;" control="locale_menu"/>

Modified: branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/main/menu.js
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/main/menu.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/main/menu.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -54,19 +54,19 @@
 
     'init' : function( params ) {
 
+        var obj = this;
+
         urls.remote = params['server'];
 
         // Pull in local customizations
         var r = new XMLHttpRequest();
-        r.open("GET", url_prefix('/xul/server/skin/custom.js'), false);
+        r.open("GET", obj.url_prefix('/xul/server/skin/custom.js'), false);
         r.send(null);
         if (r.status == 200) {
             dump('Evaluating /xul/server/skin/custom.js\n');
             eval( r.responseText );
         }
 
-        var obj = this;
-
         var button_bar = String( obj.data.hash.aous['ui.general.button_bar'] ) == 'true';
         if (button_bar) {
             var x = document.getElementById('main_toolbar');
@@ -617,6 +617,22 @@
                 ['oncommand'],
                 function() { open_eg_web_page('conify/global/permission/grp_penalty_threshold'); }
             ],
+            'cmd_server_admin_config_rule_circ_duration' : [
+                ['oncommand'],
+                function() { open_eg_web_page('conify/global/config/rule_circ_duration'); }
+            ],
+            'cmd_server_admin_config_rule_recurring_fine' : [
+                ['oncommand'],
+                function() { open_eg_web_page('conify/global/config/rule_recurring_fine'); }
+            ],
+            'cmd_server_admin_config_rule_max_fine' : [
+                ['oncommand'],
+                function() { open_eg_web_page('conify/global/config/rule_max_fine'); }
+            ],
+            'cmd_server_admin_config_rule_age_hold_protect' : [
+                ['oncommand'],
+                function() { open_eg_web_page('conify/global/config/rule_age_hold_protect'); }
+            ],
             'cmd_local_admin_external_text_editor' : [
                 ['oncommand'],
                 function() {
@@ -668,6 +684,12 @@
                     );
                 }
             ],
+            "cmd_local_admin_copy_template": [
+                ["oncommand"],
+                function() {
+                    open_eg_web_page("conify/global/asset/copy_template");
+                }
+            ],
             'cmd_local_admin_patrons_due_refunds' : [
                 ['oncommand'],
                 function() {
@@ -1012,6 +1034,14 @@
                 }
             ],
 
+            'cmd_authority_manage' : [
+                ['oncommand'],
+                function() {
+                    obj.data.stash_retrieve();
+                    obj.set_tab(obj.url_prefix(urls.AUTHORITY_MANAGE),{},{});
+                }
+            ],
+
             /* Admin menu */
             'cmd_change_session' : [
                 ['oncommand'],

Modified: branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/main/menu_frame_menus.xul
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/main/menu_frame_menus.xul	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/main/menu_frame_menus.xul	2010-10-18 13:46:56 UTC (rev 18371)
@@ -24,6 +24,7 @@
 
     <command id="cmd_cat_main" key="cat-main-key" />
     <command id="cmd_create_marc" />
+    <command id="cmd_authority_manage" />
     <command id="cmd_circ_checkout" key="circ-checkout-key" />
     <command id="cmd_patron_search" key="patron-search-key" />
     <command id="cmd_circ_checkin" key="circ-checkin-key" />
@@ -127,6 +128,7 @@
     <command id="cmd_local_admin_hold_matrix_matchpoint"/>
     <command id="cmd_local_admin_work_log"/>
     <command id="cmd_local_admin_patrons_due_refunds"/>
+    <command id="cmd_local_admin_copy_template"/>
 
     <!-- server admin menu commands -->
     <command id="cmd_server_admin_org_type"/>
@@ -158,6 +160,10 @@
     <command id="cmd_server_admin_global_flag"/>
     <command id="cmd_server_admin_org_unit_setting_type"/>
     <command id="cmd_server_admin_usr_setting_type"/>
+    <command id="cmd_server_admin_config_rule_circ_duration"/>
+    <command id="cmd_server_admin_config_rule_recurring_fine"/>
+    <command id="cmd_server_admin_config_rule_max_fine"/>
+    <command id="cmd_server_admin_config_rule_age_hold_protect"/>
     <command id="cmd_server_admin_booking_resource" />
     <command id="cmd_server_admin_booking_resource_type" />
     <command id="cmd_server_admin_booking_resource_attr" />
@@ -272,6 +278,8 @@
         <menuseparator />
         <menuitem label="&staff.main.menu.replace_barcode.label;" command="cmd_replace_barcode"/>
         <menuitem label="&staff.main.menu.cat.retrieve_last_record.label;" accesskey="&staff.main.menu.cat.retrieve_last_record.accesskey;" command="cmd_retrieve_last_record" key="retrieve_last_record_key"/>
+        <menuseparator />
+        <menuitem label="&staff.main.menu.cat.authority_manage.label;" accesskey="&staff.main.menu.cat.authority_manage.accesskey;" command="cmd_authority_manage"/>
     </menupopup>
 </menu>
 
@@ -366,6 +374,7 @@
                 <menuitem label="&staff.main.menu.admin.local_admin.conify.survey.label;" command="cmd_local_admin_survey"/>
                 <menuitem label="&staff.server.admin.index.transit_list;" command="cmd_local_admin_transit_list"/>
                 <menuitem label="&staff.main.menu.admin.local_admin.work_log.label;" accesskey="&staff.main.menu.admin.local_admin.work_log.accesskey;" command="cmd_local_admin_work_log"/>
+                <menuitem label="&staff.main.menu.admin.local_admin.copy_template.label;" accesskey="&staff.main.menu.admin.local_admin.copy_template.accesskey;" command="cmd_local_admin_copy_template"/>
             </menupopup>
         </menu>
         <menu id="main.menu.admin.server" label="&staff.main.menu.admin.server_admin.label;">
@@ -382,6 +391,10 @@
                 <menuitem label="&staff.main.menu.admin.server_admin.conify.global_flag.label;" command="cmd_server_admin_global_flag"/>
                 <menuitem label="&staff.main.menu.admin.server_admin.conify.org_unit_setting_type;" command="cmd_server_admin_org_unit_setting_type"/>
                 <menuitem label="&staff.main.menu.admin.server_admin.conify.usr_setting_type;" command="cmd_server_admin_usr_setting_type"/>
+                <menuitem label="&staff.main.menu.admin.server_admin.conify.config_rule_circ_duration;" command="cmd_server_admin_config_rule_circ_duration"/>
+                <menuitem label="&staff.main.menu.admin.server_admin.conify.config_rule_recurring_fine;" command="cmd_server_admin_config_rule_recurring_fine"/>
+                <menuitem label="&staff.main.menu.admin.server_admin.conify.config_rule_max_fine;" command="cmd_server_admin_config_rule_max_fine"/>
+                <menuitem label="&staff.main.menu.admin.server_admin.conify.config_rule_age_hold_protect;" command="cmd_server_admin_config_rule_age_hold_protect"/>
                 <menu id="main.menu.admin.server.acq" label="&staff.main.menu.admin.server_admin.acq.label;" accesskey="&staff.main.menu.admin.server_admin.acq.accesskey;">
                     <menupopup id="main.menu.admin.server.acq.popup">
                         <menuitem label="&staff.main.menu.admin.server_admin.acq.fund.label;" accesskey="&staff.main.menu.admin.server_admin.acq.fund.accesskey;" command="cmd_server_admin_acq_fund" />

Modified: branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/main/menu_frame_overlay.xul
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/main/menu_frame_overlay.xul	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/main/menu_frame_overlay.xul	2010-10-18 13:46:56 UTC (rev 18371)
@@ -83,7 +83,7 @@
         <menu id="main.menu.admin" />
         <menu id="main.menu.help" />
     </menubar>
-    <toolbar id="main_toolbar" hidden="true">
+    <toolbar id="main_toolbar" hidden="true" class="chromeclass-toolbar">
         <toolbarbutton id="tb_checkout" 
             command="cmd_circ_checkout" 
             image="chrome://open_ils_staff_client/skin/media/images/Arrow-rightup-small.png" 

Modified: branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/util/browser.js
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/util/browser.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/util/browser.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -26,6 +26,7 @@
             obj.debug_label = params['debug_label'];
             obj.passthru_content_params = params['passthru_content_params'];
             obj.on_url_load = params['on_url_load'];
+            obj.printer_context = params['printer_context'] || 'default';
 
             JSAN.use('util.controller'); obj.controller = new util.controller();
             obj.controller.init(
@@ -49,7 +50,7 @@
                                 try {
                                     netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
                                     var content = obj.get_content();
-                                    JSAN.use('util.print'); var p = new util.print();
+                                    JSAN.use('util.print'); var p = new util.print(obj.printer_context);
                                     var print_params = {};
                                     if (obj.html_source) {
                                         print_params.msg = obj.html_source;
@@ -58,10 +59,25 @@
                                     if (typeof content.printable_output == 'function') {
                                         print_params.msg = content.printable_output();
                                         print_params.content_type = 'text/plain';
+                                        content = print_params.msg;
                                     }
                                     JSAN.use('OpenILS.data'); var data = new OpenILS.data(); data.stash_retrieve();
-                                    if (data.print_strategy == 'webBrowserPrint' || !data.print_strategy) {
-                                        // Override the print strategy temporarily in this context
+                                    // Override the print strategy temporarily if it's not set or is equal to webBrowserPrint (which is buggy here)
+                                    if (data.print_strategy) {
+                                        if (data.print_strategy[obj.printer_context] || data.print_strategy['default']) {
+                                            if (data.print_strategy[obj.printer_context]) {
+                                                if (data.print_strategy[obj.printer_context] == 'webBrowserPrint') {
+                                                    print_params.print_strategy = 'window.print';
+                                                }
+                                            } else {
+                                                if (data.print_strategy['default'] == 'webBrowserPrint') {
+                                                    print_params.print_strategy = 'window.print';
+                                                }
+                                            }
+                                        } else {
+                                            print_params.print_strategy = 'window.print';
+                                        }
+                                    } else {
                                         print_params.print_strategy = 'window.print';
                                     }
                                     p.NSPrint(content,false,print_params);

Modified: branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/util/browser.xul
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/util/browser.xul	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/util/browser.xul	2010-10-18 13:46:56 UTC (rev 18371)
@@ -54,6 +54,7 @@
                 var p =    { 
                     'url' : url,
                     'push_xulG' : push_xulG,
+                    'printer_context' : xul_param('printer_context'),
                     'html_source' : xul_param('html_source'),
                     'debug_label' : 'debug'
                 };

Modified: branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/util/list.js
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/util/list.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/util/list.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -33,6 +33,8 @@
 
         JSAN.use('util.widgets');
 
+        obj.printer_context = params.printer_context;
+
         if (typeof params.map_row_to_column == 'function') obj.map_row_to_column = params.map_row_to_column;
         if (typeof params.map_row_to_columns == 'function') {
             obj.map_row_to_columns = params.map_row_to_columns;
@@ -1265,7 +1267,7 @@
 
     'dump_csv_to_printer' : function(params) {
         var obj = this;
-        JSAN.use('util.print'); var print = new util.print();
+        JSAN.use('util.print'); var print = new util.print(params.printer_context || obj.printer_context);
         if (typeof params == 'undefined') params = {};
         if (params.no_full_retrieve) {
             print.simple( obj.dump_csv( params ), {'content_type':'text/plain'} );
@@ -1280,7 +1282,7 @@
 
     'dump_extended_format_to_printer' : function(params) {
         var obj = this;
-        JSAN.use('util.print'); var print = new util.print();
+        JSAN.use('util.print'); var print = new util.print(params.printer_context || obj.printer_context);
         if (typeof params == 'undefined') params = {};
         if (params.no_full_retrieve) {
             print.simple( obj.dump_extended_format( params ), {'content_type':'text/plain'} );
@@ -1341,7 +1343,7 @@
                 function() {
                     try {
                         if (!params.list) params.list = obj.dump_with_keys();
-                        JSAN.use('util.print'); var print = new util.print();
+                        JSAN.use('util.print'); var print = new util.print(params.printer_context || obj.printer_context);
                         print.tree_list( params );
                         if (typeof params.callback == 'function') params.callback();
                     } catch(E) {
@@ -1688,9 +1690,10 @@
     },
 
     // Takes fieldmapper class name and attempts to spit out column definitions suitable for .init
-    'fm_columns' : function(hint,column_extras) {
+    'fm_columns' : function(hint,column_extras,prefix) {
         var obj = this;
         var columns = [];
+        if (!prefix) { prefix = ''; }
         try {
             // requires the dojo library fieldmapper.autoIDL
             if (typeof fieldmapper == 'undefined') { throw 'fieldmapper undefined'; }
@@ -1701,7 +1704,24 @@
             var data = obj.data; data.stash_retrieve();
 
             function col_def(my_field) {
-                var col_id = hint + '_' + my_field.name;
+                var col_id = prefix + hint + '_' + my_field.name;
+                var dataobj = hint;
+                var datafield = my_field.name;
+                if (column_extras) {
+                    if (column_extras['*']) {
+                        if (column_extras['*']['dataobj']) {
+                            dataobj = column_extras['*']['dataobj'];
+                        }
+                    }
+                    if (column_extras[col_id]) {
+                        if (column_extras[col_id]['dataobj']) {
+                            dataobj = column_extras[col_id]['dataobj'];
+                        }
+                        if (column_extras[col_id]['datafield']) {
+                            datafield = column_extras[col_id]['datafield'];
+                        }
+                    }
+                }
                 var def = {
                     'id' : col_id,
                     'label' : my_field.label || my_field.name,
@@ -1714,26 +1734,26 @@
                 // my_field.datatype => bool float id int interval link money number org_unit text timestamp
                 if (my_field.datatype == 'link') {
                     def.render = function(my) { 
-                        return typeof my[hint][my_field.name]() == 'object' ? my[hint][my_field.name]()[my_field.key]() : my[hint][my_field.name](); 
+                        return typeof my[dataobj][datafield]() == 'object' ? my[dataobj][datafield]()[my_field.key]() : my[dataobj][datafield](); 
                     }
                 } else {
-                    def.render = function(my) { return my[hint][my_field.name](); }
+                    def.render = function(my) { return my[dataobj][datafield](); }
                 }
                 if (my_field.datatype == 'timestamp') {
                     JSAN.use('util.date');
                     def.render = function(my) {
-                        return util.date.formatted_date( my[hint][my_field.name](), '%{localized}' );
+                        return util.date.formatted_date( my[dataobj][datafield](), '%{localized}' );
                     }
                 }
                 if (my_field.datatype == 'org_unit') {
                     def.render = function(my) {
-                        return typeof my[hint][my_field.name]() == 'object' ? my[hint][my_field.name]().shortname() : data.hash.aou[ my[hint][my_field.name]() ].shortname();
+                        return typeof my[dataobj][datafield]() == 'object' ? my[dataobj][datafield]().shortname() : data.hash.aou[ my[dataobj][datafield]() ].shortname();
                     }
                 }
                 if (my_field.datatype == 'money') {
                     JSAN.use('util.money');
                     def.render = function(my) {
-                        return util.money.sanitize( my[hint][my_field.name]() );
+                        return util.money.sanitize( my[dataobj][datafield]() );
                     }
                 }
                 if (column_extras) {
@@ -1744,19 +1764,42 @@
                         if (column_extras['*']['expanded_label']) {
                             def.label = my_class.label + ': ' + def.label;
                         }
+                        if (column_extras['*']['label_prefix']) {
+                            def.label = column_extras['*']['label_prefix'] + def.label;
+                        }
+                        if (column_extras['*']['remove_virtual']) {
+                            if (my_field.virtual) {
+                                def.remove_me = true;
+                            }
+                        }
                     }
                     if (column_extras[col_id]) {
                         for (var attr in column_extras[col_id]) {
                             def[attr] = column_extras[col_id][attr];
                         }
+                        if (column_extras[col_id]['keep_me']) {
+                            def.remove_me = false;
+                        }
+                        if (column_extras[col_id]['label_prefix']) {
+                            def.label = column_extras[col_id]['label_prefix'] + def.label;
+                        }
                     }
                 }
-                return def;
+                if (def.remove_me) {
+                    dump('Skipping ' + def.label + '\n');
+                    return null;
+                } else {
+                    dump('Defining ' + def.label + '\n');
+                    return def;
+                }
             }
  
             for (var i = 0; i < my_class.fields.length; i++) {
                 var my_field = my_class.fields[i];
-                columns.push( col_def(my_field) );
+                var def = col_def(my_field);
+                if (def) {
+                    columns.push( def );
+                }
             }
 
         } catch(E) {

Modified: branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/util/print.js
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/util/print.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/util/print.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -1,7 +1,7 @@
 dump('entering util/print.js\n');
 
 if (typeof util == 'undefined') util = {};
-util.print = function () {
+util.print = function (context) {
 
     netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
 
@@ -11,8 +11,10 @@
     JSAN.use('util.functional');
     JSAN.use('util.file');
 
+    this.context = context || 'default';
+
     var prefs = Components.classes['@mozilla.org/preferences-service;1'].getService(Components.interfaces['nsIPrefBranch']);
-    var key = 'oils.printer.external.cmd';
+    var key = 'oils.printer.external.cmd.' + this.context;
     var has_key = prefs.prefHasUserValue(key);
     this.oils_printer_external_cmd = has_key ? prefs.getCharPref(key) : '';
 
@@ -83,7 +85,8 @@
 
             var obj = this;
 
-            obj.data.last_print = { 'msg' : msg, 'params' : params}; obj.data.stash('last_print');
+            obj.data.last_print = { 'msg' : msg, 'params' : params, 'context' : this.context};
+            obj.data.stash('last_print');
 
             var silent = false;
             if ( params && params.no_prompt && (params.no_prompt == true || params.no_prompt == 'true') ) {
@@ -102,9 +105,14 @@
             netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
             obj.data.init({'via':'stash'});
 
-            if (params.print_strategy || obj.data.print_strategy) {
+            if (typeof obj.data.print_strategy == 'undefined') {
+                obj.data.print_strategy = {};
+                obj.data.stash('print_strategy');
+            }
 
-                switch(params.print_strategy || obj.data.print_strategy) {
+            if (params.print_strategy || obj.data.print_strategy[obj.context] || obj.data.print_strategy['default']) {
+
+                switch(params.print_strategy || obj.data.print_strategy[obj.context] || obj.data.print_strategy['default']) {
                     case 'dos.print':
                         params.dos_print = true;
                     case 'custom.print':
@@ -296,10 +304,13 @@
             netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
             obj.data.init({'via':'stash'});
 
-            if (params.print_strategy || obj.data.print_strategy) {
+            if (params.print_strategy || obj.data.print_strategy[obj.context] || obj.data.print_strategy['default']) {
 
-dump('params.print_strategy = ' + params.print_strategy + ' || obj.data.print_strategy = ' + obj.data.print_strategy + ' => ' + ( params.print_strategy || obj.data.print_strategy ) + '\n');
-                switch(params.print_strategy || obj.data.print_strategy) {
+                dump('params.print_strategy = ' + params.print_strategy
+                    + ' || obj.data.print_strategy[' + obj.context + '] = ' + obj.data.print_strategy[obj.context] 
+                    + ' || obj.data.print_strategy[default] = ' + obj.data.print_strategy['default'] 
+                    + ' => ' + ( params.print_strategy || obj.data.print_strategy[obj.context] || obj.data.print_strategy['default'] ) + '\n');
+                switch(params.print_strategy || obj.data.print_strategy[obj.context] || obj.data.print_strategy['default']) {
                     case 'dos.print':
                     case 'custom.print':
                         if (typeof w != 'string') {
@@ -515,23 +526,31 @@
         try {
             var error_msg = '';
             netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
-            var file = new util.file('gPrintSettings');
+            var file = new util.file('gPrintSettings.' + this.context);
             if (file._file.exists()) {
                 temp = file.get_object(); file.close();
                 for (var i in temp) {
                     try { this.gPrintSettings[i] = temp[i]; } catch(E) { error_msg += 'Error trying to set gPrintSettings.'+i+'='+temp[i]+' : ' + js2JSON(E) + '\n'; }
                 }
-            } else {
-                this.gPrintSettings.marginTop = 0;
-                this.gPrintSettings.marginLeft = 0;
-                this.gPrintSettings.marginBottom = 0;
-                this.gPrintSettings.marginRight = 0;
-                this.gPrintSettings.headerStrLeft = '';
-                this.gPrintSettings.headerStrCenter = '';
-                this.gPrintSettings.headerStrRight = '';
-                this.gPrintSettings.footerStrLeft = '';
-                this.gPrintSettings.footerStrCenter = '';
-                this.gPrintSettings.footerStrRight = '';
+            }  else if (this.context != 'default') {
+                var file = new util.file('gPrintSettings.default');
+                if (file._file.exists()) {
+                    temp = file.get_object(); file.close();
+                    for (var i in temp) {
+                        try { this.gPrintSettings[i] = temp[i]; } catch(E) { error_msg += 'Error trying to set gPrintSettings.'+i+'='+temp[i]+' : ' + js2JSON(E) + '\n'; }
+                    }
+                } else {
+                    this.gPrintSettings.marginTop = 0;
+                    this.gPrintSettings.marginLeft = 0;
+                    this.gPrintSettings.marginBottom = 0;
+                    this.gPrintSettings.marginRight = 0;
+                    this.gPrintSettings.headerStrLeft = '';
+                    this.gPrintSettings.headerStrCenter = '';
+                    this.gPrintSettings.headerStrRight = '';
+                    this.gPrintSettings.footerStrLeft = '';
+                    this.gPrintSettings.footerStrCenter = '';
+                    this.gPrintSettings.footerStrRight = '';
+                }
             }
             if (error_msg) {
                 this.error.sdump('D_PRINT',error_msg);
@@ -553,7 +572,7 @@
         try {
             var obj = this;
             netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
-            var file = new util.file('gPrintSettings');
+            var file = new util.file('gPrintSettings.' + this.context);
             if (typeof obj.gPrintSettings == 'undefined') obj.GetPrintSettings();
             if (obj.gPrintSettings) file.set_object(obj.gPrintSettings); 
             file.close();

Modified: branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/util/rbrowser.xul
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/util/rbrowser.xul	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/util/rbrowser.xul	2010-10-18 13:46:56 UTC (rev 18371)
@@ -57,6 +57,7 @@
                 var p = { 
                     'url' : url,
                     'push_xulG' : push_xulG,
+                    'printer_context' : xul_param('printer_context'),
                     'html_source' : xul_param('html_source'),
                     'debug_label' : 'debug'
                 } 

Modified: branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/util/widgets.js
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/util/widgets.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/xul/staff_client/chrome/content/util/widgets.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -113,6 +113,7 @@
     var menulist = document.createElement('menulist');
     var menupopup = document.createElement('menupopup'); menulist.appendChild(menupopup);
     for (var i = 0; i < items.length; i++) {
+        if (typeof items[i] == 'undefined') { continue; }
         var label = items[i][0]; var value = items[i][1]; var disabled = items[i][2]; var indent = items[i][3];
         if (indent) {
             for (var j = 0; j < Number(indent); j++) {

Modified: branches/serials-integration/Open-ILS/xul/staff_client/chrome/locale/en-US/offline.properties
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/chrome/locale/en-US/offline.properties	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/xul/staff_client/chrome/locale/en-US/offline.properties	2010-10-18 13:46:56 UTC (rev 18371)
@@ -233,6 +233,7 @@
 menu.cmd_acq_po.tab=Purchase Orders
 menu.cmd_acq_user_requests.tab=Patron Requests
 menu.cmd_acq_claim_eligible.tab=Claim-Ready Items
+menu.cmd_serial_batch_receive.tab=Batch Receive
 menu.cmd_booking_resource.tab=Resources
 menu.cmd_booking_reservation.tab=Reservations
 menu.cmd_booking_reservation_pickup.tab=Reservation Pickup
@@ -259,8 +260,10 @@
 staff.cat.opac.title_for_hold_transfer.destination_needed.label=Need to mark a record as a Title Hold Transfer Destination first.
 staff.cat.opac.title_for_hold_transfer.success.label=Holds transferred.
 staff.cat.opac.title_for_hold_transfer.failure.label=Holds not transferred.
+staff.cat.opac.related_items=Related Lineitems
+staff.cat.opac.serial_alt_mgmt=Subscriptions
 staff.cat.create_or_rebarcode_items=Create or Re-barcode Items
 printing.nothing_to_reprint=Nothing to re-print
 printing.prompt_for_external_print_cmd=Enter external print command and parameters (use %receipt.txt% or %receipt.html% as the file containing the print data. Those values will be substituted with the proper path.):
-printing.print_strategy_saved=Print strategy (%1$s) saved to file system.
+printing.print_strategy_saved=Print strategy (%1$s) for %2$s context saved to file system.
 text_editor.prompt_for_external_cmd=Enter external text editor command and parameters (use %letter.txt% as the file containing the text. This value will be substituted with the proper path.):

Modified: branches/serials-integration/Open-ILS/xul/staff_client/chrome/skin/global.css
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/chrome/skin/global.css	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/xul/staff_client/chrome/skin/global.css	2010-10-18 13:46:56 UTC (rev 18371)
@@ -2,6 +2,8 @@
 @namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"); 
 @namespace html url("http://www.w3.org/TR/REC-html40"); 
 
+window:not([active="true"]) menubar > menu { color: menutext !important }
+
 *|textarea:focus { background-color: #DDFFDD; }
 *|input:focus { background-color: #DDFFDD; }
 

Copied: branches/serials-integration/Open-ILS/xul/staff_client/defaults/preferences/autoupdate.js (from rev 17886, trunk/Open-ILS/xul/staff_client/defaults/preferences/autoupdate.js)
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/defaults/preferences/autoupdate.js	                        (rev 0)
+++ branches/serials-integration/Open-ILS/xul/staff_client/defaults/preferences/autoupdate.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -0,0 +1,29 @@
+// Enable Updater
+pref("app.update.enabled", true);
+// Change to "false" to not automatically update
+pref("app.update.auto", true);
+// 0 downloads without prompt always
+pref("app.update.mode", 0);
+
+// These settings are in seconds
+// Interval for checking
+pref("app.update.interval", 86400);
+// Time before prompting to download - If auto is off, mainly
+pref("app.update.nagTimer.download", 86400);
+// Time before prompting to restart to apply update that has downloaded
+pref("app.update.nagTimer.restart", 1800);
+
+// How often to check timers (above) - in MILLIseconds
+pref("app.update.timer", 600000);
+
+
+// URL for downloading. For Thomas Berezansky's script the update.xml part isn't needed.
+// NOTE: Certs that default to invalid, even those overridden with cert_override.txt, won't work with this!
+pref("app.update.url", "https://::HOSTNAME::/updates/check/%CHANNEL%/%VERSION%/update.xml");
+
+// URL for manual update information
+pref("app.update.url.manual", "http://::HOSTNAME::/updates/manualupdate.html");
+
+// Default details URL for updates
+pref("app.update.url.details", "http://::HOSTNAME::/updates/updatedetails.html");
+

Modified: branches/serials-integration/Open-ILS/xul/staff_client/defaults/preferences/prefs.js
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/defaults/preferences/prefs.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/xul/staff_client/defaults/preferences/prefs.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -5,6 +5,7 @@
 // These are specific to Evergreen
 pref("open-ils.write_in_user_chrome_directory", true);
 pref("open-ils.disable_accesskeys_on_tabs", false);
+pref("toolkit.singletonWindowType", "eg_main");
 
 // Toggles for experimental features that may later become org unit settings
 pref("open-ils.enable_join_tabs", true);

Copied: branches/serials-integration/Open-ILS/xul/staff_client/external/make_updates.sh (from rev 17886, trunk/Open-ILS/xul/staff_client/external/make_updates.sh)
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/external/make_updates.sh	                        (rev 0)
+++ branches/serials-integration/Open-ILS/xul/staff_client/external/make_updates.sh	2010-10-18 13:46:56 UTC (rev 18371)
@@ -0,0 +1,327 @@
+#!/bin/bash
+
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Update Packaging.
+#
+# The Initial Developer of the Original Code is
+# Merrimack Valley Library Consortium.
+# Portions created by the Initial Developer are Copyright (C) 2010
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#  Thomas Berezansky <tsbere at mvlc.org>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+# Portions of this code were based on code by Darin Fisher found here:
+# http://mxr.mozilla.org/mozilla/source/tools/update-packaging/
+
+prefix=${1:-/openils/var/updates}
+BZIP2=${BZIP2:-bzip2}
+
+GEN_UPDATES=0
+WIN_UPDATES=0
+LINUX_UPDATES=0
+EXT_UPDATES=0
+CLIENTS=0
+case "$2" in
+	generic-updates*)
+	echo "Building Generic Updates only"
+	GEN_UPDATES=1
+	;;
+	win-updates*)
+	echo "Building Windows Updates only"
+	WIN_UPDATES=1
+	;;
+	linux-updates*)
+	echo "Building Linux Updates only"
+	LINUX_UPDATES=1
+	;;
+	extension-updates*)
+	echo "Building Extension Updates only"
+	EXT_UPDATES=1
+	;;
+	*)
+	echo "Building All Updates"
+	GEN_UPDATES=1
+	WIN_UPDATES=1
+	LINUX_UPDATES=1
+	EXT_UPDATES=1
+	;;
+esac
+case "$2" in
+	extension-updates*)
+	echo "Extension only - No client"
+	;;
+	*-client)
+	echo "Building Client(s)"
+	CLIENTS=1
+	;;
+	*)
+	echo "Not Building Client(s)"
+	;;
+esac
+
+function unwrap_update
+{
+	SOURCE="$1"
+	DEST="$2"
+	$MAR -C "$2" -x "$1"
+	find "$2" -type f -exec mv {} {}.bz2 \;
+	find "$2" -type f -name '*.bz2' -exec $BZIP2 -d {} \;
+}
+
+function prep_update
+{
+	NEW="$1"
+	OLD="$2"
+	WORK="$3"
+	MANIFEST="$WORK/update.manifest"
+	ARCHIVEFILES="update.manifest"
+	rm -rf "$WORK"
+	mkdir -p "$WORK"
+	rm -f "$MANIFEST"
+	for FILE in `find "$NEW" -type f`; do
+		check_file $FILE
+	done
+	for FILE in `find "$OLD" -type f`; do
+		remove_file $FILE
+	done
+	$BZIP2 -z9 "$MANIFEST"
+	mv "$MANIFEST.bz2" "$MANIFEST"
+	rm -rf "$OLD"
+}
+
+function check_file
+{
+	CHECK_FILE="${1#$NEW/}"
+	if [ $CHECK_FILE == "update.manifest" ]; then
+		return;
+	fi
+	DIR=$(dirname "$WORK/$CHECK_FILE")
+	if [ ! -f "$OLD/$CHECK_FILE" ]; then
+		echo "add \"$CHECK_FILE\"" >> "$MANIFEST"
+		mkdir -p "$DIR"
+		$BZIP2 -cz9 "$NEW/$CHECK_FILE" > "$WORK/$CHECK_FILE"
+		if [ -x "$NEW/$CHECK_FILE" ]; then
+			chmod 0755 "$WORK/$CHECK_FILE"
+		else
+			chmod 0644 "$WORK/$CHECK_FILE"
+		fi
+		ARCHIVEFILES="$ARCHIVEFILES \"$CHECK_FILE\""
+		return
+	elif ! diff "$OLD/$CHECK_FILE" "$NEW/$CHECK_FILE" > /dev/null; then
+		mkdir -p "$DIR"
+		$MBSDIFF "$OLD/$CHECK_FILE" "$NEW/$CHECK_FILE" "$WORK/$CHECK_FILE.patch"
+		$BZIP2 -z9 "$WORK/$CHECK_FILE.patch"
+		$BZIP2 -cz9 "$NEW/$CHECK_FILE" > "$WORK/$CHECK_FILE"
+		PATCHSIZE=`du -b "$WORK/$CHECK_FILE.patch.bz2"`
+		FULLSIZE=`du -b "$WORK/$CHECK_FILE"`
+		PATCHSIZE="${PATCHSIZE%%	*}"
+		FULLSIZE="${FULLSIZE%%	*}"
+		if [ $PATCHSIZE -lt $FULLSIZE ]; then
+			rm -f "$WORK/$CHECK_FILE"
+			mv "$WORK/$CHECK_FILE.patch.bz2" "$WORK/$CHECK_FILE.patch"
+			echo "patch \"$CHECK_FILE.patch\" \"$CHECK_FILE\"" >> "$MANIFEST"
+			ARCHIVEFILES="$ARCHIVEFILES \"$CHECK_FILE.patch\""
+		else
+			rm -f "$WORK/$CHECK_FILE.patch.bz2"
+			if [ -x "$NEW/$CHECK_FILE" ]; then
+				chmod 0755 "$WORK/$CHECK_FILE"
+			else
+				chmod 0644 "$WORK/$CHECK_FILE"
+			fi
+			echo "add \"$CHECK_FILE\"" >> "$MANIFEST"
+			ARCHIVEFILES="$ARCHIVEFILES \"$CHECK_FILE\""
+		fi
+	fi
+	rm -f "$OLD/$CHECK_FILE"
+}
+
+function remove_file
+{
+	RM_FILE="${1#$OLD/}"
+	if [ $RM_FILE != "update.manifest" ]; then
+		echo "remove \"$RM_FILE\"" >> "$MANIFEST"
+	fi
+}
+
+function build_update
+{
+	eval "$MAR -C \"$WORK\" -c output.mar $ARCHIVEFILES"
+	mv "$WORK/output.mar" "$1"
+	rm -rf "$WORK"
+}
+
+function check_mar
+{
+	if which mar; then
+		MAR=${MAR:-mar}
+	fi
+	if which mbsdiff; then
+		MBSDIFF=${MBSDIFF:-mbsdiff}
+	fi
+	if [ ! -x "$MAR" -o ! -x "$MBSDIFF" ]; then
+		if [ ! -f "external/mar" -o ! -f "external/mbsdiff" ]; then
+			wget ftp://ftp.mozilla.org/pub/mozilla.org/xulrunner/mar-generation-tools/mar-generation-tools-linux.zip
+			unzip mar-generation-tools-linux.zip -d external
+		fi
+		MAR="$PWD/external/mar"
+		MBSDIFF="$PWD/external/mbsdiff"
+	fi
+}
+
+function make_full_update
+{
+	echo "Making full update"
+	rm -rf "oldclient"
+	mkdir -p "oldclient"
+	prep_update client oldclient client.working
+	build_update "full_update.mar"
+	mkdir -p "$PUBPATH"
+	mv full_update.mar "$PUBPATH/$VERSION.mar"
+	echo "Making full update patch def"
+	mkdir -p "$PATCHPATH"
+	HASH=$(sha512sum "$PUBPATH/$VERSION.mar")
+	SIZE=$(du -b "$PUBPATH/$VERSION.mar")
+	echo "<patch type=\"complete\" URL=\"$VERSION.mar\" hashFunction=\"sha512\" hashValue=\"${HASH%% *}\" size=\"${SIZE%%	*}\"/>" > "$PATCHPATH/$VERSION.patchline"
+}
+
+function make_partial_update
+{
+	PREV_VERSION="${1%.mar}"
+	if [ "$VERSION" == "$PREV_VERSION" ]; then
+		echo "Skipping partial update for same version"
+		return
+	fi
+	echo "Making partial update from $PREV_VERSION"
+	rm -rf "oldclient"
+	mkdir -p "oldclient"
+	unwrap_update "$ARCHIVEPATH/$1" oldclient
+	prep_update client oldclient client.working
+	build_update "partial_update.mar"
+	mv partial_update.mar "$PUBPATH/$PREV_VERSION-$VERSION.mar"
+	echo "Making partial update patch def"
+	mkdir -p "$PATCHPATH"
+	HASH=$(sha512sum "$PUBPATH/$PREV_VERSION-$VERSION.mar")
+	SIZE=$(du -b "$PUBPATH/$PREV_VERSION-$VERSION.mar")
+	echo "<patch type=\"partial\" URL=\"$PREV_VERSION-$VERSION.mar\" hashFunction=\"sha512\" hashValue=\"${HASH%% *}\" size=\"${SIZE%%	*}\"/>" > "$PATCHPATH/$PREV_VERSION-$VERSION.patchline"
+}
+
+function make_partial_updates
+{
+	echo "Checking for partial update source files"
+	if [ -d "$ARCHIVEPATH" ]; then
+		for OLDVER in `find "$ARCHIVEPATH" -maxdepth 1 -name '*.mar'`; do
+			make_partial_update "${OLDVER##*/}"
+		done
+	fi
+	mkdir -p "$ARCHIVEPATH"
+	echo "Copying full update to archive"
+	cp "$PUBPATH/$VERSION.mar" "$ARCHIVEPATH"
+	echo "Updating current version file"
+	echo "$VERSION" > "$PATCHPATH/VERSION"
+}
+
+function cleanup_files
+{
+	echo "Cleaning up previous update mar files and update patch files"
+	find "$PUBPATH" -maxdepth 1 -name "*.mar" ! -name "*$VERSION.mar" -delete -print
+	find "$PATCHPATH" -maxdepth 1 -name "*.patch" ! -name "*$VERSION.patch" -delete -print
+}
+
+# First, do we have the mar and mbsdiff tools?
+check_mar
+VERSION=`cat build/VERSION`
+
+# Generic Updates - No XULRunner packaged, channel of "release"
+# NOTE: Generic updates CAN update Windows/Linux builds, and will do so if you don't build platform specific ones
+if [ $GEN_UPDATES -eq 1 ]; then
+	PATCHPATH="$prefix/patch"
+	PUBPATH="$prefix/pub"
+	ARCHIVEPATH="$prefix/archives"
+	if [ $CLIENTS -eq 1 ]; then
+		make generic-client
+		mkdir -p "$prefix/pub/clients/"
+		find "$prefix/pub/clients/" -name '*_client.xpi' -delete
+		mv evergreen_staff_client.xpi "$prefix/pub/clients/${VERSION}_client.xpi"
+	else
+		make client_app
+	fi
+	make_full_update
+	make_partial_updates
+	cleanup_files
+fi
+
+# Windows Updates - Windows XULRunner, update channel of "win"
+if [ $WIN_UPDATES -eq 1 ]; then
+	PATCHPATH="$prefix/patch/win"
+	PUBPATH="$prefix/pub/win"
+	ARCHIVEPATH="$prefix/archives/win"
+	if [ $CLIENTS -eq 1 ]; then
+		make win-client
+		mkdir -p "$prefix/pub/clients/"
+		find "$prefix/pub/clients/" -name '*_setup.exe' -delete
+		mv evergreen_staff_client_setup.exe "$prefix/pub/clients/${VERSION}_setup.exe"
+	else
+		make win-xulrunner
+	fi
+	make_full_update
+	make_partial_updates
+	cleanup_files
+fi
+
+# Linux Updates - Linux XULRunner, update channel of "lin'
+if [ $LINUX_UPDATES -eq 1 ]; then
+	PATCHPATH="$prefix/patch/lin"
+	PUBPATH="$prefix/pub/lin"
+	ARCHIVEPATH="$prefix/archives/lin"
+	if [ $CLIENTS -eq 1 ]; then
+		make linux-client
+		mkdir -p "$prefix/pub/clients/"
+		find "$prefix/pub/clients/" -name '*.tar.bz2' -delete
+		mv evergreen_staff_client.tar.bz2 "$prefix/pub/clients/${VERSION}.tar.bz2"
+	else
+		make linux-xulrunner
+	fi
+	make_full_update
+	make_partial_updates
+	cleanup_files
+fi
+
+# Extension Updates
+# Not really "Updates" so much as "Update", plural for consistency in command.
+# Extensions don't do partial updates. Or at least not that I found docs for.
+if [ $EXT_UPDATES -eq 1 ]; then
+	make extension
+	mkdir -p "$prefix/pub/"
+	find "$prefix/pub/" -maxdepth 1 -name '*_extension.xpi' -delete
+	mv evergreen.xpi "$prefix/pub/${VERSION}_extension.xpi" 
+	SHA512=$(sha512sum "$prefix/pub/${VERSION}_extension.xpi")
+	SHA512=${SHA512%% *}
+	sed -e "s|<em:version>.*</em:version>|<em:version>$VERSION</em:version>|" -e "s|<em:updateLink>.*</em:updateLink>|<em:updateLink>https://::HOSTNAME::/updates/${VERSION}_extension.xpi</em:updateLink>|" -e "s|<em:updateHash>.*</em:updateHash>|<em:updateHash>sha512:$SHA512</em:updateHash>|" update.rdf > "$prefix/patch/update.rdf"
+fi

Modified: branches/serials-integration/Open-ILS/xul/staff_client/install.rdf
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/install.rdf	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/xul/staff_client/install.rdf	2010-10-18 13:46:56 UTC (rev 18371)
@@ -14,7 +14,7 @@
 			<Description>
 				<em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
 				<em:minVersion>3.5</em:minVersion>
-				<em:maxVersion>3.5.*</em:maxVersion>
+				<em:maxVersion>3.6.*</em:maxVersion>
 			</Description>
 		</em:targetApplication>
     
@@ -23,6 +23,7 @@
 		<em:description>Evergreen Staff Client</em:description>
    	 
 		<em:homepageURL>http://evergreen-ils.org/</em:homepageURL>
+		<em:updateURL>https://::HOSTNAME::/updates/update.rdf</updateURL>
     
 	</Description>      
 </RDF>

Modified: branches/serials-integration/Open-ILS/xul/staff_client/server/OpenILS/util_overlay.xul
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/server/OpenILS/util_overlay.xul	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/xul/staff_client/server/OpenILS/util_overlay.xul	2010-10-18 13:46:56 UTC (rev 18371)
@@ -13,7 +13,6 @@
         <script>try { dojo.require('dojo.date.locale'); } catch(E) { alert(E); }</script>
         <script>try { dojo.require('dojo.date.stamp'); } catch(E) { alert(E); }</script>
         <script type="text/javascript" src="/xul/server/main/constants.js" />
-        <script type="text/javascript" src="/xul/server/skin/custom.js" />
         <script type="text/javascript" src="/xul/server/OpenILS/data.js" />
         <script type="text/javascript" src="/xul/server/util/barcode.js" />
         <script type="text/javascript" src="/xul/server/util/browser.js" />

Modified: branches/serials-integration/Open-ILS/xul/staff_client/server/admin/copy_locations.js
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/server/admin/copy_locations.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/xul/staff_client/server/admin/copy_locations.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -160,6 +160,8 @@
     appendClear($n( row, 'cl_hold_verify'), (isTrue(cl.hold_verify())) ? _TRUE.cloneNode(true) : _FALSE.cloneNode(true) );
     appendClear($n( row, 'cl_visible'), (isTrue(cl.opac_visible())) ? _TRUE.cloneNode(true) : _FALSE.cloneNode(true) );
     appendClear($n( row, 'cl_circulate'), (isTrue(cl.circulate())) ? _TRUE.cloneNode(true) : _FALSE.cloneNode(true) );
+    $n( row, 'cl_label_prefix').appendChild(text(cl.label_prefix() || ''));
+    $n( row, 'cl_label_suffix').appendChild(text(cl.label_suffix() || ''));
 
     var edit = $n( row, 'cl_edit');
     edit.onclick = function() { clEdit( cl, tbody, row ); };
@@ -201,6 +203,22 @@
     if(isTrue(cl.hold_verify())) arr[6].checked = true;
     else arr[7].checked = true;
 
+    var label_prefix = $n(r, 'cl_edit_label_prefix');
+    if (cl.label_prefix()) {
+        label_prefix.setAttribute('size', cl.label_prefix().length + 3);
+    } else {
+        label_prefix.setAttribute('size', 3);
+    }
+    label_prefix.value = cl.label_prefix();
+
+    var label_suffix = $n(r, 'cl_edit_label_suffix');
+    if (cl.label_suffix()) {
+        label_suffix.setAttribute('size', cl.label_suffix().length + 3);
+    } else {
+        label_suffix.setAttribute('size', 3);
+    }
+    label_suffix.value = cl.label_suffix();
+
     $n(r, 'cl_edit_cancel').onclick = function(){cleanTbody(tbody,'edit');}
     $n(r, 'cl_edit_commit').onclick = function(){clEditCommit( tbody, r, cl ); }
 
@@ -234,6 +252,8 @@
     if(arr[6].checked) cl.hold_verify(1);
     else cl.hold_verify(0);
     cl.name($n(r, 'cl_edit_name').value);
+    cl.label_prefix($n(r, 'cl_edit_label_prefix').value);
+    cl.label_suffix($n(r, 'cl_edit_label_suffix').value);
 
     var req = new Request( UPDATE_CL, SESSION, cl );
     req.send(true);

Modified: branches/serials-integration/Open-ILS/xul/staff_client/server/admin/copy_locations.xhtml
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/server/admin/copy_locations.xhtml	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/xul/staff_client/server/admin/copy_locations.xhtml	2010-10-18 13:46:56 UTC (rev 18371)
@@ -37,7 +37,7 @@
     <body onload='try{clEditorInit();}catch(e){alert(js2JSON(e));}'>
 
         <div class='welcome_box'>
-            <span>Welcome </span><b><span id='user'/></b>
+            <span>&staff.server.admin.copy_locations.editor.welcome; </span><b><span id='user'/></b>
         </div>
 
         <center>
@@ -96,7 +96,7 @@
                         </td>
                     </tr>
                     <tr>
-                        <td colspan='4'><input id='sc_new_submit' type='submit' value='Create' disabled='disabled'/></td>
+                        <td colspan='4'><input id='sc_new_submit' type='submit' value='&staff.server.admin.copy_locations.editor.create;' disabled='disabled'/></td>
                     </tr>
                 </tbody>
             </table>
@@ -116,6 +116,8 @@
                         <td width=''>&staff.server.admin.copy_locations.editor.hold_verify;</td>
                         <td width=''>&staff.server.admin.copy_locations.editor.opac_visible;</td>
                         <td width=''>&staff.server.admin.copy_locations.editor.circulate;</td>
+                        <td width=''>&staff.server.admin.copy_locations.editor.prefix;</td>
+                        <td width=''>&staff.server.admin.copy_locations.editor.suffix;</td>
                         <td width=''>&staff.server.admin.copy_locations.editor.edit;</td>
                         <td width=''>&staff.server.admin.copy_locations.editor.delete;</td>
                     </tr>
@@ -131,8 +133,10 @@
                         <td name='cl_hold_verify'> </td>
                         <td name='cl_visible'> </td>
                         <td name='cl_circulate'> </td>
-                        <td><input type='submit' value='Edit' name='cl_edit' disabled='disabled'> </input></td>
-                        <td><input type='submit' value='Delete' name='cl_delete' disabled='disabled'> </input></td>
+                        <td name='cl_label_prefix'> </td>
+                        <td name='cl_label_suffix'> </td>
+                        <td><input type='submit' value='&staff.server.admin.copy_locations.editor.edit;' name='cl_edit' disabled='disabled'> </input></td>
+                        <td><input type='submit' value='&staff.server.admin.copy_locations.editor.delete;' name='cl_delete' disabled='disabled'> </input></td>
                     </tr>
                 </tbody>
             </table>
@@ -194,6 +198,8 @@
                                 <input type='radio' name='cl_edit_circulate'/>
                             </span>
                         </td>
+                        <td><input name='cl_edit_label_prefix' type='text'> </input></td>
+                        <td><input name='cl_edit_label_suffix' type='text'> </input></td>
                         <td><input type='submit' name='cl_edit_commit' value='&staff.server.admin.copy_locations.submit;'/></td>
                         <td><input type='submit' name='cl_edit_cancel' value='&staff.server.admin.copy_locations.cancel;'/></td>
                     </tr>

Modified: branches/serials-integration/Open-ILS/xul/staff_client/server/admin/printer_settings.html
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/server/admin/printer_settings.html	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/xul/staff_client/server/admin/printer_settings.html	2010-10-18 13:46:56 UTC (rev 18371)
@@ -27,6 +27,15 @@
     <script type="text/javascript" src="printer_settings.js"></script>
 </head><body onload="try { my_init(); } catch(E) { alert(E); }" style="background: white;">
     <div class="messagecatalog" id="offlineStrings" src="/xul/server/locale/<!--#echo var='locale'-->/offline.properties" />
+    <h1>&staff.printing.context.header;</h1>
+    <p>&staff.printing.context.desc;</p>
+    <form>
+        <input type="radio" name="context" value="default" checked="checked" onclick="g.set_printer_context('default');">&staff.printing.context.radio.default.label;</input>
+        <input type="radio" name="context" value="receipt" onclick="g.set_printer_context('receipt');">&staff.printing.context.radio.receipt.label;</input>
+        <input type="radio" name="context" value="label" onclick="g.set_printer_context('label');">&staff.printing.context.radio.label.label;</input>
+        <input type="radio" name="context" value="mail" onclick="g.set_printer_context('mail');">&staff.printing.context.radio.mail.label;</input>
+        <input type="radio" name="context" value="offline" onclick="g.set_printer_context('offline');">&staff.printing.context.radio.offline.label;</input>
+    </form> 
     <h1>&staff.printing.normal_settings.header;</h1>
     <iframe id="sample" src="printer_settings.txt"></iframe><br />
     <button onclick="try { g.printer_settings(); } catch(E) { alert(E); }">&staff.printing.set_default;</button>

Modified: branches/serials-integration/Open-ILS/xul/staff_client/server/admin/printer_settings.js
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/server/admin/printer_settings.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/xul/staff_client/server/admin/printer_settings.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -9,7 +9,7 @@
         JSAN.use('util.error'); g.error = new util.error();
         g.error.sdump('D_TRACE','my_init() for printer_settings.xul');
 
-        JSAN.use('util.print'); g.print = new util.print();
+        g.set_printer_context();
 
         g.prefs = Components.classes['@mozilla.org/preferences-service;1'].getService(Components.interfaces['nsIPrefBranch']);
 
@@ -26,6 +26,11 @@
     }
 }
 
+g.set_printer_context = function(context) {
+    g.context = context || 'default';
+    JSAN.use('util.print'); g.print = new util.print(g.context);
+}
+
 g.page_settings = function() {
     netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
     g.print.page_settings();
@@ -42,7 +47,7 @@
 g.set_print_strategy = function(which) {
     netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
     if (which == 'custom.print') {
-        var key = 'oils.printer.external.cmd';
+        var key = 'oils.printer.external.cmd.' + g.context;
         var has_key = g.prefs.prefHasUserValue(key);
         var value = has_key ? g.prefs.getCharPref(key) : '';
         var cmd = window.prompt(
@@ -52,13 +57,17 @@
         if (!cmd) { return; }
         g.prefs.setCharPref(key,cmd);
     }
-    JSAN.use('util.file'); var file = new util.file('print_strategy');
+    JSAN.use('util.file'); var file = new util.file('print_strategy.' + g.context);
     file.write_content( 'truncate', String( which ) );
     file.close();
     JSAN.use('OpenILS.data'); var data = new OpenILS.data(); data.init({'via':'stash'});
-    data.print_strategy = which; data.stash('print_strategy');
+    if (!data.print_strategy) {
+        data.print_strategy = {};
+    }
+    data.print_strategy[g.context] = which;
+    data.stash('print_strategy');
     alert(
-        document.getElementById('offlineStrings').getFormattedString('printing.print_strategy_saved',[which])
+        document.getElementById('offlineStrings').getFormattedString('printing.print_strategy_saved',[which,g.context])
     );
 }
 

Modified: branches/serials-integration/Open-ILS/xul/staff_client/server/cat/bib_brief_overlay.js
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/server/cat/bib_brief_overlay.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/xul/staff_client/server/cat/bib_brief_overlay.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -71,7 +71,8 @@
                     //dump('value = ' + value + '\n');
                     var n = set(c.id, value ? value : '');
                     if (c.id == 'tcn_source') set_tooltip('tcn',value);
-                    if (c.id == 'doc_id') set_tooltip('title',value);
+                    if (c.id == 'title') set_tooltip('title',value);
+                    if (c.id == 'author') set_tooltip('author',value);
                     //dump('set text on ' + n + ' elements\n');
                 } else {
                     //dump('render is not a function\n');
@@ -81,6 +82,30 @@
             }
         }
 
+        // Let's fetch a bib call number
+        JSAN.use('OpenILS.data');
+        var data = new OpenILS.data();
+        var label_class = data.hash.aous['cat.default_classification_scheme'];
+        if (!label_class) {
+            label_class = 1;
+        }
+        var cn_blob_array = net.simple_request('BLOB_MARC_CALLNUMBERS_RETRIEVE',[params.mvr_id, label_class]);
+        if (! cn_blob_array) { cn_blob_array = []; }
+        var tooltip_text = '';
+        for (var i = 0; i < cn_blob_array.length; i++) {
+            var cn_blob_obj = cn_blob_array[i];
+            for (var j in cn_blob_obj) {
+                tooltip_text += j + ' : ' + cn_blob_obj[j] + '\n';
+            }
+        }
+        if (tooltip_text) {
+            var cn_blob_obj = cn_blob_array[0];
+            for (var j in cn_blob_obj) {
+                set('bib_call_number',cn_blob_obj[j]);
+            }
+            set_tooltip('bib_call_number',tooltip_text);
+        }
+
     } catch(E) {
         alert(location.href + '\nError in bib_brief_overlay(' + js2JSON(params) + '): ' + E);
         return;

Modified: branches/serials-integration/Open-ILS/xul/staff_client/server/cat/bib_brief_overlay.xul
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/server/cat/bib_brief_overlay.xul	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/xul/staff_client/server/cat/bib_brief_overlay.xul	2010-10-18 13:46:56 UTC (rev 18371)
@@ -10,35 +10,45 @@
         <grid id="bib_brief_grid" flex="0">
             <columns>
                 <column />
-                <column flex="1" />
                 <column />
                 <column />
                 <column />
                 <column />
                 <column />
                 <column />
+                <column />
             </columns>
             <rows id="bib_brief_grid_rows">
                 <row id="bib_brief_grid_row1" position="1">
-                    <label value="&staff.cat.bib_brief.title.label;" accesskey="&staff.cat.bib_brief.title.accesskey;" control="title"/>
-                    <textbox id="title" name="title" readonly="true" context="clipboard"/>
-                    <label value="&staff.cat.bib_brief.edition.label;" accesskey="&staff.cat.bib_brief.edition.accesskey;" control="edition"/>
-                    <textbox id="edition" name="edition" readonly="true" context="clipboard"/>
-                    <label value="&staff.cat.bib_brief.created_by.label;" accesskey="&staff.cat.bib_brief.created_by.accesskey;" control="creator"/>
-                    <textbox id="creator" name="creator" readonly="true" context="clipboard"/>
-                    <label value="&staff.cat.bib_brief.last_edited_by.label;" accesskey="&staff.cat.bib_brief.last_edited_by.accesskey;" control="editor"/>
-                    <textbox id="editor" name="editor" readonly="true" context="clipboard"/>
+                    <label value="&staff.cat.bib_brief.title.label;" accesskey="&staff.cat.bib_brief.title.accesskey;" control="title" class="emphasis"/>
+                    <textbox id="title" name="title" readonly="true" context="clipboard" class="plain" onfocus="this.select()"/>
+                    <label value="&staff.cat.bib_brief.edition.label;" accesskey="&staff.cat.bib_brief.edition.accesskey;" control="edition" class="emphasis"/>
+                    <textbox id="edition" name="edition" readonly="true" context="clipboard" class="plain" onfocus="this.select()"/>
+                    <label value="&staff.cat.bib_brief.title_control_number.label;" accesskey="&staff.cat.bib_brief.title_control_number.accesskey;" control="tcn" class="emphasis"/>
+                    <textbox id="tcn" name="tcn" readonly="true" context="clipboard" class="plain" onfocus="this.select()"/>
+                    <label value="&staff.cat.bib_brief.created_by.label;" accesskey="&staff.cat.bib_brief.created_by.accesskey;" control="creator" class="emphasis"/>
+                    <textbox id="creator" name="creator" readonly="true" context="clipboard" class="plain" onfocus="this.select()"/>
                 </row>
                 <row position="2">
-                    <label value="&staff.cat.bib_brief.author.label;" accesskey="&staff.cat.bib_brief.author.accesskey;" control="author"/>
-                    <textbox id="author" name="author" readonly="true" context="clipboard"/>
-                    <label value="&staff.cat.bib_brief.pub_date.label;" accesskey="&staff.cat.bib_brief.pub_date.accesskey;" control="pubdate"/>
-                    <textbox id="pubdate" name="pubdate" readonly="true" context="clipboard"/>
-                    <label value="&staff.cat.bib_brief.title_control_number.label;" accesskey="&staff.cat.bib_brief.title_control_number.accesskey;" control="tcn"/>
-                    <textbox id="tcn" name="tcn" readonly="true" context="clipboard"/>
-                    <label value="&staff.cat.bib_brief.last_edited_on.label;" accesskey="&staff.cat.bib_brief.last_edited_on.accesskey;" control="edit_date"/>
-                    <textbox id="edit_date" name="edit_date" readonly="true" context="clipboard"/>
+                    <label value="&staff.cat.bib_brief.author.label;" accesskey="&staff.cat.bib_brief.author.accesskey;" control="author" class="emphasis"/>
+                    <textbox id="author" name="author" readonly="true" context="clipboard" class="plain" onfocus="this.select()"/>
+                    <label value="&staff.cat.bib_brief.pub_date.label;" accesskey="&staff.cat.bib_brief.pub_date.accesskey;" control="pubdate" class="emphasis"/>
+                    <textbox id="pubdate" name="pubdate" readonly="true" context="clipboard" class="plain" onfocus="this.select()"/>
+                    <label value="&staff.cat.bib_brief.biblio_record_entry_id.label;" accesskey="&staff.cat.bib_brief.biblio_record_entry_id.accesskey;" control="mvr_doc_id" class="emphasis"/>
+                    <textbox id="mvr_doc_id" name="mvr_doc_id" readonly="true" context="clipboard" class="plain" onfocus="this.select()"/>
+                    <label value="&staff.cat.bib_brief.last_edited_by.label;" accesskey="&staff.cat.bib_brief.last_edited_by.accesskey;" control="editor" class="emphasis"/>
+                    <textbox id="editor" name="editor" readonly="true" context="clipboard" class="plain" onfocus="this.select()"/>
                 </row>
+                <row id="bib_brief_grid_row3" position="3">
+                    <label id="bib_call_number_label" value="&staff.cat.bib_brief.call_number.label;" accesskey="&staff.cat.bib_brief.call_number.accesskey;" control="bib_call_number" class="emphasis"/>
+                    <textbox id="bib_call_number" name="bib_call_number" readonly="true" context="clipboard" class="plain" onfocus="this.select()"/>
+                    <hbox id="placeholder1"/>
+                    <hbox id="placeholder2"/>
+                    <label value="&staff.cat.bib_brief.biblio_record_entry_owner.label;" accesskey="&staff.cat.bib_brief.biblio_record_entry_owner.accesskey;" control="owner" class="emphasis"/>
+                    <textbox id="owner" name="owner" readonly="true" context="clipboard" class="plain" onfocus="this.select()"/>
+                    <label value="&staff.cat.bib_brief.last_edited_on.label;" accesskey="&staff.cat.bib_brief.last_edited_on.accesskey;" control="edit_date" class="emphasis"/>
+                    <textbox id="edit_date" name="edit_date" readonly="true" context="clipboard" class="plain" onfocus="this.select()"/>
+                </row>
             </rows>
         </grid>
 </overlay>

Modified: branches/serials-integration/Open-ILS/xul/staff_client/server/cat/copy_browser.js
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/server/cat/copy_browser.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/xul/staff_client/server/cat/copy_browser.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -29,6 +29,48 @@
 
             JSAN.use('util.network'); obj.network = new util.network();
             JSAN.use('OpenILS.data'); obj.data = new OpenILS.data(); obj.data.init({'via':'stash'});
+
+            obj.controller_init(params);
+
+            obj.list_init(params);
+
+            obj.controller.render();
+
+            obj.default_depth = obj.depth_menu_init();
+            obj.default_lib = obj.data.hash.aou[ obj.library_menu_init() ];
+
+            document.getElementById('show_acns').addEventListener(
+                'command',
+                function(ev) {
+                    JSAN.use('util.file'); var file = new util.file('copy_browser_prefs.'+obj.data.server_unadorned);
+                    util.widgets.save_attributes(file, { 'lib_menu' : [ 'value' ], 'show_acns' : [ 'checked' ], 'show_acps' : [ 'checked' ] });
+                },
+                false
+            );
+
+            document.getElementById('show_acps').addEventListener(
+                'command',
+                function(ev) {
+                    JSAN.use('util.file'); var file = new util.file('copy_browser_prefs.'+obj.data.server_unadorned);
+                    util.widgets.save_attributes(file, { 'lib_menu' : [ 'value' ], 'show_acns' : [ 'checked' ], 'show_acps' : [ 'checked' ] });
+                },
+                false
+            );
+
+            obj.show_my_libs( obj.default_lib.id() );
+
+            JSAN.use('util.exec'); var exec = new util.exec(20); exec.timer(obj.funcs,100);
+
+            obj.show_consortial_count();
+
+        } catch(E) {
+            this.error.standard_unexpected_error_alert('cat.copy_browser.init: ',E);
+        }
+    },
+
+    'controller_init' : function(params) {
+        var obj = this;
+        try {
             JSAN.use('util.controller'); obj.controller = new util.controller();
             obj.controller.init(
                 {
@@ -836,18 +878,74 @@
                 }
             );
 
-            obj.list_init(params);
+        } catch(E) {
+            this.error.standard_unexpected_error_alert('cat.copy_browser.controller_init(): ',E);
+        }
+    },
 
+    'depth_menu_init' : function(params) {
+        var obj = this;
+        try {
+            var list = [];
+            var max_depth = 0;
+            for (var i = 0; i < obj.data.list.aout.length; i++) {
+                var type = obj.data.list.aout[i];
+                var depth = type.depth();
+                if ( depth > max_depth) { max_depth = depth; }
+                if (typeof list[depth] == 'undefined') {
+                    list[depth] = [
+                        type.opac_label(),
+                        type.depth(),
+                        false,
+                        ( type.depth() * 2)
+                    ];
+                } else {
+                    list[depth][0] += ' / ' + type.opac_label();
+                }
+            }
+            ml = util.widgets.make_menulist( list, max_depth );
+            ml.setAttribute('id','depth_menu'); document.getElementById('x_depth_menu').appendChild(ml);
+            ml.addEventListener(
+                'command',
+                function(ev) {
+                    obj.default_depth = ev.target.value;
+                    if (document.getElementById('refresh_button')) document.getElementById('refresh_button').focus(); 
+                    JSAN.use('util.file'); var file = new util.file('copy_browser_prefs.'+obj.data.server_unadorned);
+                    util.widgets.save_attributes(file, { 
+                        'lib_menu' : [ 'value' ],
+                        'depth_menu' : [ 'value' ],
+                        'show_acns' : [ 'checked' ],
+                        'show_acps' : [ 'checked' ]
+                    });
+                },
+                false
+            );
+
+            file = new util.file('copy_browser_prefs.'+obj.data.server_unadorned);
+            util.widgets.load_attributes(file);
+            ml.value = ml.getAttribute('value');
+            if (! ml.value) {
+                ml.value = max_depth;
+                ml.setAttribute('value',ml.value);
+            }
+
+            return ml.value;
+        } catch(E) {
+            alert('Error in copy_browser.js, depth_menu_init(): ' + E);
+        }
+    },
+
+    'library_menu_init' : function(params) {
+        var obj = this;
+        try {
+
             obj.org_ids = obj.network.simple_request('FM_AOU_IDS_RETRIEVE_VIA_RECORD_ID.authoritative',[ obj.docid ]);
             if (typeof obj.org_ids.ilsevent != 'undefined') throw(obj.org_ids);
             JSAN.use('util.functional'); 
             obj.org_ids = util.functional.map_list( obj.org_ids, function (o) { return Number(o); });
 
             var org = obj.data.hash.aou[ obj.data.list.au[0].ws_ou() ];
-            //obj.show_libs( org );
 
-            //obj.show_my_libs();
-
             JSAN.use('util.file'); JSAN.use('util.widgets');
 
             var file; var list_data; var ml; 
@@ -855,6 +953,9 @@
             file = new util.file('offline_ou_list'); 
             if (file._file.exists()) {
                 list_data = file.get_object(); file.close();
+                for (var i = 0; i < list_data[0].length; i++) { // make sure all entries are enabled
+                    list_data[0][i][2] = false;
+                }
                 ml = util.widgets.make_menulist( list_data[0], list_data[1] );
                 ml.setAttribute('id','lib_menu'); document.getElementById('x_lib_menu').appendChild(ml);
                 for (var i = 0; i < obj.org_ids.length; i++) {
@@ -877,11 +978,15 @@
                 ml.addEventListener(
                     'command',
                     function(ev) {
-                        //obj.show_my_libs(ev.target.value);
-                        //alert('lib picker, command caught - ml = ' + ml + '\nml.value = ' + ml.value + '\n');
+                        obj.default_lib = obj.data.hash.aou[ ev.target.value ];
                         if (document.getElementById('refresh_button')) document.getElementById('refresh_button').focus(); 
                         JSAN.use('util.file'); var file = new util.file('copy_browser_prefs.'+obj.data.server_unadorned);
-                        util.widgets.save_attributes(file, { 'lib_menu' : [ 'value' ], 'show_acns' : [ 'checked' ], 'show_acps' : [ 'checked' ] });
+                        util.widgets.save_attributes(file, { 
+                            'lib_menu' : [ 'value' ],
+                            'depth_menu' : [ 'value' ],
+                            'show_acns' : [ 'checked' ],
+                            'show_acps' : [ 'checked' ]
+                        });
                         obj.refresh_list();
                     },
                     false
@@ -890,8 +995,6 @@
                 throw(document.getElementById('catStrings').getString('staff.cat.copy_browser.missing_library') + '\n');
             }
 
-            JSAN.use('util.widgets'); 
-        
             file = new util.file('copy_browser_prefs.'+obj.data.server_unadorned);
             util.widgets.load_attributes(file);
             ml.value = ml.getAttribute('value');
@@ -900,32 +1003,10 @@
                 ml.setAttribute('value',ml.value);
             }
 
-            document.getElementById('show_acns').addEventListener(
-                'command',
-                function(ev) {
-                    JSAN.use('util.file'); var file = new util.file('copy_browser_prefs.'+obj.data.server_unadorned);
-                    util.widgets.save_attributes(file, { 'lib_menu' : [ 'value' ], 'show_acns' : [ 'checked' ], 'show_acps' : [ 'checked' ] });
-                },
-                false
-            );
+            return ml.value;
 
-            document.getElementById('show_acps').addEventListener(
-                'command',
-                function(ev) {
-                    JSAN.use('util.file'); var file = new util.file('copy_browser_prefs.'+obj.data.server_unadorned);
-                    util.widgets.save_attributes(file, { 'lib_menu' : [ 'value' ], 'show_acns' : [ 'checked' ], 'show_acps' : [ 'checked' ] });
-                },
-                false
-            );
-
-            obj.show_my_libs( ml.value );
-
-            JSAN.use('util.exec'); var exec = new util.exec(20); exec.timer(obj.funcs,100);
-
-            obj.show_consortial_count();
-
         } catch(E) {
-            this.error.standard_unexpected_error_alert('cat.copy_browser.init: ',E);
+            this.error.standard_unexpected_error_alert('cat.copy_browser.library_menu_init(): ',E);
         }
     },
 
@@ -957,7 +1038,7 @@
                 if (typeof org != 'object') org = obj.data.hash.aou[ org ];
             }
             obj.show_libs( org, false );
-        
+/*        
             var p_org = obj.data.hash.aou[ org.parent_ou() ];
             if (p_org) {
                 obj.funcs.push( function() { 
@@ -980,6 +1061,7 @@
                     document.getElementById('lib_menu').setAttribute('disabled','false'); 
                 } );
             }
+*/
         } catch(E) {
             alert(E);
         }
@@ -999,13 +1081,17 @@
             } );
 
             for (var i = 0; i < obj.data.tree.aou.children().length; i++) {
-                obj.funcs.push(
-                    function(o) {
-                        return function() {
-                            obj.show_libs( o );
-                        }
-                    }( obj.data.tree.aou.children()[i] )
-                );
+                var child = obj.data.tree.aou.children()[i];
+                if (obj.data.hash.aout[child.ou_type()].depth() <= obj.default_depth
+                && orgIsMine(obj.default_lib,child,obj.default_depth)) {
+                    obj.funcs.push(
+                        function(o) {
+                            return function() {
+                                obj.show_libs( o );
+                            }
+                        }( child )
+                    );
+                }
             }
             obj.funcs.push( function() { 
                 document.getElementById('cmd_refresh_list').setAttribute('disabled','false'); 
@@ -1097,11 +1183,15 @@
                         x.setAttribute('container','true');
                         if (show_open) x.setAttribute('open','true');
                         for (var i = 0; i < start_aou.children().length; i++) {
-                            obj.funcs.push(
-                                function(o,p) {
-                                    return function() { obj.append_org(o,p); };
-                                }( start_aou.children()[i], start_aou )
-                            );
+                            var child = start_aou.children()[i];
+                            if (obj.data.hash.aout[child.ou_type()].depth() <= obj.default_depth
+                            && orgIsMine(obj.default_lib,child,obj.default_depth)) {
+                                obj.funcs.push(
+                                    function(o,p) {
+                                        return function() { obj.append_org(o,p); };
+                                    }( child, start_aou )
+                                );
+                            }
                         }
                     }
                 }
@@ -1159,44 +1249,54 @@
 
     'on_select_org' : function(org_id,twisty) {
         var obj = this;
-        var org = obj.data.hash.aou[ org_id ];
-        if (obj.data.hash.aout[ org.ou_type() ].depth() == 0 && ! get_bool( obj.data.hash.aout[ org.ou_type() ].can_have_vols() ) ) return;
-        obj.funcs.push( function() { 
-            document.getElementById('cmd_refresh_list').setAttribute('disabled','true'); 
-            document.getElementById('cmd_show_libs_with_copies').setAttribute('disabled','true'); 
-            document.getElementById('lib_menu').setAttribute('disabled','true'); 
-        } );
-        if (org.children()) {
-            for (var i = 0; i < org.children().length; i++) {
-                obj.funcs.push(
-                    function(o,p) {
-                        return function() {
-                            obj.append_org(o,p)
-                        }
-                    }(org.children()[i],org)
-                );
+        try {
+            var org = obj.data.hash.aou[ org_id ];
+            if (obj.data.hash.aout[ org.ou_type() ].depth() == 0 && ! get_bool( obj.data.hash.aout[ org.ou_type() ].can_have_vols() ) ) return;
+            obj.funcs.push( function() { 
+                document.getElementById('cmd_refresh_list').setAttribute('disabled','true'); 
+                document.getElementById('cmd_show_libs_with_copies').setAttribute('disabled','true'); 
+                document.getElementById('lib_menu').setAttribute('disabled','true'); 
+            } );
+            if (org.children()) {
+                for (var i = 0; i < org.children().length; i++) {
+                    var child = org.children()[i];
+                    if (obj.data.hash.aout[child.ou_type()].depth() <= obj.default_depth
+                    && orgIsMine(obj.default_lib,child,obj.default_depth)) {
+                        obj.funcs.push(
+                            function(o,p) {
+                                return function() {
+                                    obj.append_org(o,p)
+                                }
+                            }(child,org)
+                        );
+                    }
+                }
+            } 
+            if (obj.map_acn[ 'aou_' + org_id ]) {
+                for (var i = 0; i < obj.map_acn[ 'aou_' + org_id ].length; i++) {
+                    obj.funcs.push(
+                        function(o,a) {
+                            return function() {
+                                obj.append_acn(o,a);
+                            }
+                        }( org, obj.map_acn[ 'aou_' + org_id ][i] )
+                    );
+                }
             }
-        } 
-        if (obj.map_acn[ 'aou_' + org_id ]) {
-            for (var i = 0; i < obj.map_acn[ 'aou_' + org_id ].length; i++) {
-                obj.funcs.push(
-                    function(o,a) {
-                        return function() {
-                            obj.append_acn(o,a);
-                        }
-                    }( org, obj.map_acn[ 'aou_' + org_id ][i] )
-                );
-            }
+            obj.funcs.push( function() { 
+                document.getElementById('cmd_refresh_list').setAttribute('disabled','false'); 
+                document.getElementById('cmd_show_libs_with_copies').setAttribute('disabled','false'); 
+                document.getElementById('lib_menu').setAttribute('disabled','false'); 
+            } );
+        } catch(E) {
+            alert('Error in copy_browser.js, on_select_org(): ' + E);
         }
-        obj.funcs.push( function() { 
-            document.getElementById('cmd_refresh_list').setAttribute('disabled','false'); 
-            document.getElementById('cmd_show_libs_with_copies').setAttribute('disabled','false'); 
-            document.getElementById('lib_menu').setAttribute('disabled','false'); 
-        } );
     },
 
     'append_org' : function (org,parent_org,params) {
         var obj = this;
+        netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+        obj.error.consoleService.logStringMessage('append_org: org = ' + org.shortname() + ' parent_org = ' + (parent_org ? parent_org.shortname() : '') + ' params = ' + js2JSON(params) + '\n');
         try {
             if (obj.map_tree[ 'aou_' + org.id() ]) {
                 var x = obj.map_tree[ 'aou_' + org.id() ];
@@ -1534,8 +1634,6 @@
                 }
             );
 
-            obj.controller.render();
-
         } catch(E) {
             this.error.sdump('D_ERROR','cat.copy_browser.list_init: ' + E + '\n');
             alert(E);
@@ -1632,11 +1730,7 @@
             if (typeof obj.org_ids.ilsevent != 'undefined') throw(obj.org_ids);
             JSAN.use('util.functional'); 
             obj.org_ids = util.functional.map_list( obj.org_ids, function (o) { return Number(o); });
-            /*
-            var org = obj.data.hash.aou[ obj.data.list.au[0].ws_ou() ];
-            obj.show_libs( org );
-            */
-            obj.show_my_libs( document.getElementById('lib_menu').value );
+            obj.show_my_libs( obj.default_lib.id() );
             // FIXME - we get a null from the copy_count call if we call it too quickly here
             setTimeout( function() { obj.show_consortial_count(); }, 2000 );
         } catch(E) {

Modified: branches/serials-integration/Open-ILS/xul/staff_client/server/cat/copy_browser.xul
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/server/cat/copy_browser.xul	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/xul/staff_client/server/cat/copy_browser.xul	2010-10-18 13:46:56 UTC (rev 18371)
@@ -139,6 +139,8 @@
         <hbox><label id="legend" style="font-size: large" class="has_copies" value="&staff.cat.copy_browser.holdings_maintenance.legend;" hidden="true"/></hbox>
         <hbox>
             <hbox id="x_lib_menu"/>
+            <label value="&staff.cat.copy_browser.holdings_maintenance.depth_filter_menu;" />
+            <hbox id="x_depth_menu"/>
             <spacer flex="1"/>
             <label value="&staff.cat.copy_browser.holdings_maintenance.consortial_total;"/><label id="consortial_total"/>
             <label value="&staff.cat.copy_browser.holdings_maintenance.consortial_available;"/><label id="consortial_available"/>

Modified: branches/serials-integration/Open-ILS/xul/staff_client/server/cat/copy_editor.js
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/server/cat/copy_editor.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/xul/staff_client/server/cat/copy_editor.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -888,8 +888,8 @@
     [
         $('catStrings').getString('staff.cat.copy_editor.field.circulation_modifier.label'),
         {    
-            render: 'fm.circ_modifier() == null ? $("catStrings").getString("staff.cat.copy_editor.field.unset_or_null") : fm.circ_modifier()',
-            input: 'c = function(v){ g.apply("circ_modifier",v); if (typeof post_c == "function") post_c(v); }; x = util.widgets.make_menulist( [ [ $("catStrings").getString("staff.cat.copy_editor.field.unset_or_null"), "<HACK:KLUDGE:NULL>" ] ].concat( util.functional.map_list( g.data.list.circ_modifier, function(obj) { return [ obj, obj ]; } ).sort() ) ); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
+            render: 'fm.circ_modifier() == null ? $("catStrings").getString("staff.cat.copy_editor.field.unset_or_null") : $("commonStrings").getFormattedString("staff.circ_modifier.display",[fm.circ_modifier(),g.data.hash.ccm[fm.circ_modifier()].name(),g.data.hash.ccm[fm.circ_modifier()].description()])',
+            input: 'c = function(v){ g.apply("circ_modifier",v); if (typeof post_c == "function") post_c(v); }; x = util.widgets.make_menulist( [ [ $("catStrings").getString("staff.cat.copy_editor.field.unset_or_null"), "<HACK:KLUDGE:NULL>" ] ].concat( util.functional.map_list( g.data.list.ccm, function(obj) { return [ $("commonStrings").getFormattedString("staff.circ_modifier.display",[obj.code(),obj.name(),obj.description()]), obj.code() ]; } ).sort() ) ); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
         }
     ],
 ],

Modified: branches/serials-integration/Open-ILS/xul/staff_client/server/cat/marcedit.js
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/server/cat/marcedit.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/xul/staff_client/server/cat/marcedit.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -1,4 +1,4 @@
-// vim: noet:sw=4:ts=4:
+// vim: et:sw=4:ts=4:
 var xmlDeclaration = /^<\?xml version[^>]+?>/;
 
 var serializer = new XMLSerializer();
@@ -18,6 +18,8 @@
 var context_menus;
 var tag_menu;
 var p;
+var auth_pages = {};
+var show_auth_menu = false;
 
 function $(id) { return document.getElementById(id); }
 
@@ -140,11 +142,30 @@
             var cgi = new CGI();
             var _rid = cgi.param('record');
             if (_rid) {
+                window.xulG.record.id = _rid;
                 window.xulG.record.url = '/opac/extras/supercat/retrieve/marcxml/record/' + _rid;
             }
         }
+
         // End faking part...
 
+        /* Check for an explicitly passed record type
+         * This is not the same as the fixed-field record type; we can't trust
+         * the fixed fields when making modifications to the attributes for a
+         * given record (in particular, config.bib_source only applies for bib
+         * records, but an auth or MFHD record with the same ID and bad fixed
+         * fields could trample the config.bib_source value for the
+         * corresponding bib record if we're not careful.
+         *
+         * are = authority record
+         * sre = serial record (MFHD)
+         * bre = bibliographic record
+         */
+        if (!window.xulG.record.rtype) {
+            var cgi = new CGI();
+            window.xulG.record.rtype = cgi.param('rtype') || false;
+        }
+
         document.getElementById('save-button').setAttribute('label', window.xulG.save.label);
         document.getElementById('save-button').setAttribute('oncommand',
             'if ($("xul-editor").hidden) swap_editors(); ' +
@@ -191,8 +212,26 @@
             locale = 'en-US';
         }
 
+        // grab the right tooltip based on MARC type
+        var tooltip_doc = 'marcedit-tooltips.xml';
+        switch (window.xulG.record.rtype) {
+            case 'bre':
+                tooltip_doc = 'marcedit-tooltips.xml';
+                break; 
+            case 'are':
+                tooltip_doc = 'marcedit-tooltips-authority.xml';
+                locale = 'en-US'; // FIXME - note TODO above; at moment only en-US has this
+                break; 
+            case 'sre':
+                tooltip_doc = 'marcedit-tooltips-mfhd.xml';
+                locale = 'en-US'; // FIXME - note TODO above; at moment only en-US has this
+                break; 
+            default: 
+                tooltip_doc = 'marcedit-tooltips.xml';
+        }
+
         // Get the locale-specific tooltips
-        req.open('GET','/xul/server/locale/' + locale + '/marcedit-tooltips.xml',true);
+        req.open('GET','/xul/server/locale/' + locale + '/' + tooltip_doc,true);
 
         context_menus = createComplexXULElement('popupset');
         document.documentElement.appendChild( context_menus );
@@ -288,6 +327,19 @@
         }
         document.getElementById('fastItemAdd_textboxes').hidden = document.getElementById('fastItemAdd_checkbox').hidden || !document.getElementById('fastItemAdd_checkbox').checked;
 
+        // Only show bib sources for bib records that already exist in the database
+        if (xulG.record.rtype == 'bre' && xulG.record.id) {
+            dojo.require('openils.PermaCrud');
+            var authtoken = ses();
+            // Retrieve the current record attributes
+            var bib = new openils.PermaCrud({"authtoken": authtoken}).retrieve('bre', xulG.record.id);
+
+            // Remember the current bib source of the record
+            xulG.record.bre = bib;
+
+            buildBibSourceList(authtoken, xulG.record.id);
+        }
+
     } catch(E) {
         alert('FIXME, MARC Editor, my_init: ' + E);
     }
@@ -671,7 +723,7 @@
     SCO : { Type : /[cd]{1}/,    BLvl : /[abcdms]{1}/ },
     REC : { Type : /[ij]{1}/,    BLvl : /[abcdms]{1}/ },
     COM : { Type : /[m]{1}/,    BLvl : /[abcdms]{1}/ },
-	AUT : { Type : /[z]{1}/,	BLvl : /.{1}/ },
+    AUT : { Type : /[z]{1}/,    BLvl : /.{1}/ },
     MFHD : { Type : /[uvxy]{1}/,  BLvl : /.{1}/ }
 };
 
@@ -949,7 +1001,7 @@
             REC : {start : 18, len : 1, def : ' ' },
             COM : {start : 18, len : 1, def : 'i' }
         }
-	},
+    },
     Item : {
         ldr : {
             MFHD : {start : 18, len : 1, def : 'i' }
@@ -1125,101 +1177,101 @@
             SER : {start : 16, len : 1, def : ' ' }
         }
     },
-	"GeoDiv" : {
-		"_8" : {
-			"AUT" : {"start" : 6, "len" : 1, "def" : ' ' }
-		}
-	},
-	"Roman" : {
-		"_8" : {
-			"AUT" : {"start" : 7, "len" : 1, "def" : ' ' }
-		}
-	},
-	"CatLang" : {
-		"_8" : {
-			"AUT" : {"start" : 8, "len" : 1, "def" : ' ' }
-		}
-	},
-	"Kind" : {
-		"_8" : {
-			"AUT" : {"start" : 9, "len" : 1, "def" : ' ' }
-		}
-	},
-	"Rules" : {
-		"_8" : {
-			"AUT" : {"start" : 10, "len" : 1, "def" : ' ' }
-		}
-	},
-	"SHSys" : {
-		"_8" : {
-			"AUT" : {"start" : 11, "len" : 1, "def" : ' ' }
-		}
-	},
-	"SerType" : {
-		"_8" : {
-			"AUT" : {"start" : 12, "len" : 1, "def" : ' ' }
-		}
-	},
-	"SerNum" : {
-		"_8" : {
-			"AUT" : {"start" : 13, "len" : 1, "def" : ' ' }
-		}
-	},
-	"HeadMain" : {
-		"_8" : {
-			"AUT" : {"start" : 14, "len" : 1, "def" : ' ' }
-		}
-	},
-	"HeadSubj" : {
-		"_8" : {
-			"AUT" : {"start" : 15, "len" : 1, "def" : ' ' }
-		}
-	},
-	"HeadSer" : {
-		"_8" : {
-			"AUT" : {"start" : 16, "len" : 1, "def" : ' ' }
-		}
-	},
-	"TypeSubd" : {
-		"_8" : {
-			"AUT" : {"start" : 17, "len" : 1, "def" : ' ' }
-		}
-	},
-	"TypeGov" : {
-		"_8" : {
-			"AUT" : {"start" : 28, "len" : 1, "def" : ' ' }
-		}
-	},
-	"RefEval" : {
-		"_8" : {
-			"AUT" : {"start" : 29, "len" : 1, "def" : ' ' }
-		}
-	},
-	"RecUpd" : {
-		"_8" : {
-			"AUT" : {"start" : 31, "len" : 1, "def" : ' ' }
-		}
-	},
-	"NameDiff" : {
-		"_8" : {
-			"AUT" : {"start" : 32, "len" : 1, "def" : ' ' }
-		}
-	},
-	"Level" : {
-		"_8" : {
-			"AUT" : {"start" : 33, "len" : 1, "def" : ' ' }
-		}
-	},
-	"ModRec" : {
-		"_8" : {
-			"AUT" : {"start" : 38, "len" : 1, "def" : ' ' }
-		}
-	},
-	"CatSrc" : {
-		"_8" : {
-			"AUT" : {"start" : 39, "len" : 1, "def" : ' ' }
-		}
-	}
+    "GeoDiv" : {
+        "_8" : {
+            "AUT" : {"start" : 6, "len" : 1, "def" : ' ' }
+        }
+    },
+    "Roman" : {
+        "_8" : {
+            "AUT" : {"start" : 7, "len" : 1, "def" : ' ' }
+        }
+    },
+    "CatLang" : {
+        "_8" : {
+            "AUT" : {"start" : 8, "len" : 1, "def" : ' ' }
+        }
+    },
+    "Kind" : {
+        "_8" : {
+            "AUT" : {"start" : 9, "len" : 1, "def" : ' ' }
+        }
+    },
+    "Rules" : {
+        "_8" : {
+            "AUT" : {"start" : 10, "len" : 1, "def" : ' ' }
+        }
+    },
+    "SHSys" : {
+        "_8" : {
+            "AUT" : {"start" : 11, "len" : 1, "def" : ' ' }
+        }
+    },
+    "SerType" : {
+        "_8" : {
+            "AUT" : {"start" : 12, "len" : 1, "def" : ' ' }
+        }
+    },
+    "SerNum" : {
+        "_8" : {
+            "AUT" : {"start" : 13, "len" : 1, "def" : ' ' }
+        }
+    },
+    "HeadMain" : {
+        "_8" : {
+            "AUT" : {"start" : 14, "len" : 1, "def" : ' ' }
+        }
+    },
+    "HeadSubj" : {
+        "_8" : {
+            "AUT" : {"start" : 15, "len" : 1, "def" : ' ' }
+        }
+    },
+    "HeadSer" : {
+        "_8" : {
+            "AUT" : {"start" : 16, "len" : 1, "def" : ' ' }
+        }
+    },
+    "TypeSubd" : {
+        "_8" : {
+            "AUT" : {"start" : 17, "len" : 1, "def" : ' ' }
+        }
+    },
+    "TypeGov" : {
+        "_8" : {
+            "AUT" : {"start" : 28, "len" : 1, "def" : ' ' }
+        }
+    },
+    "RefEval" : {
+        "_8" : {
+            "AUT" : {"start" : 29, "len" : 1, "def" : ' ' }
+        }
+    },
+    "RecUpd" : {
+        "_8" : {
+            "AUT" : {"start" : 31, "len" : 1, "def" : ' ' }
+        }
+    },
+    "NameDiff" : {
+        "_8" : {
+            "AUT" : {"start" : 32, "len" : 1, "def" : ' ' }
+        }
+    },
+    "Level" : {
+        "_8" : {
+            "AUT" : {"start" : 33, "len" : 1, "def" : ' ' }
+        }
+    },
+    "ModRec" : {
+        "_8" : {
+            "AUT" : {"start" : 38, "len" : 1, "def" : ' ' }
+        }
+    },
+    "CatSrc" : {
+        "_8" : {
+            "AUT" : {"start" : 39, "len" : 1, "def" : ' ' }
+        }
+    }
 };
 
 function recordType (rec) {
@@ -1809,10 +1861,25 @@
 function getAuthorityContextMenu (target, sf) {
     var menu_id = sf.parent(). at tag + ':' + sf. at code + '-authority-context-' + sf;
 
-    var old = document.getElementById( menu_id );
-    if (old) old.parentNode.removeChild(old);
+    var page = 0;
+    var old = dojo.byId( menu_id );
+    if (old) {
+        page = auth_pages[menu_id];
+        old.parentNode.removeChild(old);
+    } else {
+        auth_pages[menu_id] = 0;
+    }
 
     var sf_popup = createPopup({ id : menu_id, flex : 1 });
+
+    sf_popup.addEventListener("popuphiding", function(event) {
+        if (show_auth_menu) {
+            show_auth_menu = false;
+            getAuthorityContextMenu(target, sf);
+            dojo.byId(menu_id).openPopup();
+        }  
+    }, false);
+
     context_menus.appendChild( sf_popup );
 
     if (!authority_tag_map[sf.parent(). at tag]) {
@@ -1821,97 +1888,8 @@
         return false;
     }
 
-    var auth_data = searchAuthority( sf, authority_tag_map[sf.parent(). at tag][0], sf. at code, 50);
+    browseAuthority( sf_popup, menu_id, target, sf, 20, page);
 
-    var res = new XML( auth_data.responseText );
-
-    var rec_list = [];
-
-    var recs = res.gw::payload.gw::array.gw::string;
-    for (var i in recs) {
-        var x = recs[i];
-        var xml = new XML(x.toString());
-        var main = xml.datafield.(@tag.toString().match(/^1/)).subfield;
-
-        if (! (main[0].parent(). at tag == authority_tag_map[sf.parent(). at tag][1]) ) continue;
-
-        var main_text = '';
-        for (var i in main) {
-            if (main_text) main_text += ' / ';
-            main_text += main[i];
-        }
-
-        rec_list.push( [ main_text, xml ] );
-    }
-    
-    for (var i in rec_list.sort( function (a, b) { if(a[0] > b[0]) return 1; return -1; } )) {
-
-        var main_text = rec_list[i][0];
-        var xml = rec_list[i][1];
-        var main = xml.datafield.(@tag.toString().match(/^1/)).subfield;
-
-        if (! (main[0].parent(). at tag == authority_tag_map[sf.parent(). at tag][1]) ) continue;
-
-        var grid = document.getElementsByAttribute('name','authority-marc-template')[0].cloneNode(true);
-        grid.setAttribute('name','-none-');
-        grid.setAttribute('style','overflow:scroll');
-
-
-        var submenu = createMenu( { label : main_text } );
-
-        var popup = createMenuPopup({ flex : "1" });
-        submenu.appendChild(popup);
-
-        var fields = xml.datafield;
-        for (var j in fields) {
-
-            var row = createRow(
-                {},
-                createLabel( { value : fields[j]. at tag } ),
-                createLabel( { value : fields[j]. at ind1 } ),
-                createLabel( { value : fields[j]. at ind2 } )
-            );
-
-            var sf_box = createHbox();
-
-            var subfields = fields[j].subfield;
-            for (var k in subfields) {
-                sf_box.appendChild(
-                    createCheckbox(
-                        { label    : '\u2021' + subfields[k]. at code + ' ' + subfields[k],
-                          subfield : subfields[k]. at code,
-                          tag      : subfields[k].parent(). at tag,
-                          value    : subfields[k]
-                        }
-                    )
-                );
-                row.appendChild(sf_box);
-            }
-
-            grid.lastChild.appendChild(row);
-        }
-
-        grid.hidden = false;
-        popup.appendChild( grid );
-
-        popup.appendChild(
-            createMenuitem(
-                { label : $('catStrings').getString('staff.cat.marcedit.apply_selected.label'),
-                  command : function (event) {
-                        applyAuthority(event.target.previousSibling, target, sf);
-                        return true;
-                  }
-                }
-            )
-        );
-
-        sf_popup.appendChild( submenu );
-    }
-
-    if (sf_popup.childNodes.length == 0)
-        sf_popup.appendChild(createLabel( { value : $('catStrings').getString('staff.cat.marcedit.no_authority_match.label') } ) );
-
-    target.setAttribute('context', menu_id);
     return true;
 }
 
@@ -2295,3 +2273,339 @@
 
 }
 
+function browseAuthority (sf_popup, menu_id, target, sf, limit, page) {
+    dojo.require('dojox.xml.parser');
+
+    // map tag + subfield to the appropriate authority browse axis:
+    // currently authority.author, authority.subject, authority.title, authority.topic
+    // based on mappings in OpenILS::Application::SuperCat
+
+    var type;
+
+    // Map based on replacing the first char of the selected tag with '1'
+    switch ('1' + (sf.parent(). at tag.toString()).substring(1)) {
+        case "130":
+            type = 'authority.title';
+            break;
+
+        case "100":
+        case "110":
+        case "111":
+            type = 'authority.author';
+            break;
+
+        case "150":
+            type = 'authority.topic';
+            break;
+
+        case "148":
+        case "151":
+        case "155":
+            type = 'authority.subject';
+            break;
+
+        // No matching tag means no authorities to search - shortcut
+        default:
+            return;
+    }
+
+    if (!limit) {
+        limit = 10;
+    }
+
+    if (!page) {
+        page = 0;
+    }
+
+    var url = '/opac/extras/startwith/marcxml/'
+        + type
+        + '/1' // OU - currently unscoped
+        + '/' + sf.toString()
+        + '/' + page
+        + '/' + limit
+    ;
+
+    // would be good to carve this out into a separate function
+    dojo.xhrGet({"url":url, "handleAs":"xml", "load": function(records) {
+        var create_menu = createMenu({ label: $('catStrings').getString('staff.cat.marcedit.create_authority.label')});
+
+        var cm_popup = create_menu.appendChild(
+            createMenuPopup()
+        );
+
+        cm_popup.appendChild(
+            createMenuitem({ label : $('catStrings').getString('staff.cat.marcedit.create_authority_now.label'),
+                command : function() { 
+                    // Call middle-layer function to create and save the new authority
+                    var source_f = summarizeField(sf);
+                    var new_auth = fieldmapper.standardRequest(
+                        ["open-ils.cat", "open-ils.cat.authority.record.create_from_bib"],
+                        [source_f, ses()]
+                    );
+                    if (new_auth && new_auth.id()) {
+                        var id_sf = <subfield code="0" xmlns="http://www.loc.gov/MARC21/slim">(CONS){new_auth.id()}</subfield>;
+                        sf.parent().appendChild(id_sf);
+                        var new_sf = marcSubfield(id_sf);
+                        target.parentNode.appendChild(new_sf);
+                        alert($('catStrings').getString('staff.cat.marcedit.create_authority_success.label'));
+                    }
+                }
+            })
+        );
+
+        cm_popup.appendChild(
+            createMenuitem({ label : $('catStrings').getString('staff.cat.marcedit.create_authority_edit.label'),
+                command : function() { 
+                    // Generate the new authority by calling the new middle-layer
+                    // function (a non-saving variant), then display in another
+                    // MARC editor
+                    var source_f = summarizeField(sf);
+                    var authtoken = ses();
+                    dojo.require('openils.PermaCrud');
+                    var pcrud = new openils.PermaCrud({"authtoken": authtoken});
+                    var rec = fieldmapper.standardRequest(
+                        ["open-ils.cat", "open-ils.cat.authority.record.create_from_bib.readonly"],
+                        { "params": [source_f] }
+                    );
+                    loadMarcEditor(pcrud, rec, target, sf);
+                }
+            })
+        );
+
+        sf_popup.appendChild(create_menu);
+        sf_popup.appendChild( createComplexXULElement( 'menuseparator' ) );
+
+        // append "Previous page" results browser
+        sf_popup.appendChild(
+            createMenuitem({ label : $('catStrings').getString('staff.cat.marcedit.previous_page.label'),
+                command : function(event) { 
+                    auth_pages[menu_id] -= 1;
+                    show_auth_menu = true;
+                }
+            })
+        );
+        sf_popup.appendChild( createComplexXULElement( 'menuseparator' ) );
+
+        dojo.query('record', records).forEach(function(record) {
+            var main_text = '';
+            var auth_id = dojox.xml.parser.textContent(dojo.query('datafield[tag="901"] subfield[code="c"]', record)[0]);
+            var auth_org = dojox.xml.parser.textContent(dojo.query('controlfield[tag="003"]', record)[0]);
+            // we have grabbed the fields with tags beginning with 1 or 5 and iterate through the subfields
+            dojo.query('datafield[tag^="1"], datafield[tag^="5"]', record).forEach(function(field) {
+                dojo.query('subfield', field).forEach(function(subfield) {
+                    if (main_text) {
+                        main_text += ' / ';
+                    }
+                    main_text += dojox.xml.parser.textContent(subfield);
+                });
+            });
+
+            /*
+             * 
+            if (! (main[0].parent(). at tag == authority_tag_map[sf.parent(). at tag][1]) ) return;
+            */
+
+            var grid = dojo.query('[name="authority-marc-template"]')[0].cloneNode(true);
+            grid.setAttribute('name','-none-');
+            grid.setAttribute('style','overflow:scroll');
+
+            var submenu = createMenu( { label : main_text } );
+
+            var popup = createMenuPopup({ flex : "1" });
+            submenu.appendChild(popup);
+
+            dojo.query('datafield[tag^="1"], datafield[tag^="5"]', record).forEach(function(field) {
+                var row = createRow(
+                    {},
+                    createLabel( { "value" : dojo.attr(field, 'ind1') } ),
+                    createLabel( { "value" : dojo.attr(field, 'ind2') } )
+                );
+
+                var sf_box = createHbox();
+                dojo.query('subfield', field).forEach(function(subfield) {
+                    sf_box.appendChild(
+                        createCheckbox(
+                            { "label"    : '\u2021' + dojo.attr(subfield, 'code') + ' ' + dojox.xml.parser.textContent(subfield),
+                              "subfield" : dojo.attr(subfield, 'code'),
+                              "tag"      : dojo.attr(field, 'tag'),
+                              "value"    : dojox.xml.parser.textContent(subfield)
+                            }
+                        )
+                    );
+                    row.appendChild(sf_box);
+                });
+
+                // Append the authority linking subfield
+                sf_box.appendChild(
+                    createCheckbox(
+                        { "label"    : '\u2021' + '0' + ' (' + auth_org + ')' + auth_id,
+                          "subfield" : '0',
+                          "tag"      : dojo.attr(field, 'tag'),
+                          "value"    : '(' + auth_org + ')' + auth_id
+                        }
+                    )
+                );
+                row.appendChild(sf_box);
+
+                grid.lastChild.appendChild(row);
+            });
+
+            grid.hidden = false;
+            popup.appendChild( grid );
+
+            popup.appendChild(
+                createMenuitem(
+                    { label : $('catStrings').getString('staff.cat.marcedit.apply_selected.label'),
+                      command : function (event) {
+                            applyAuthority(event.target.previousSibling, target, sf);
+                            return true;
+                      }
+                    }
+                )
+            );
+
+            sf_popup.appendChild( submenu );
+        });
+
+        if (sf_popup.childNodes.length == 0) {
+            sf_popup.appendChild(createLabel( { value : $('catStrings').getString('staff.cat.marcedit.no_authority_match.label') } ) );
+        } else {
+            // append "Next page" results browser
+            sf_popup.appendChild( createComplexXULElement( 'menuseparator' ) );
+            sf_popup.appendChild(
+                createMenuitem({ label : $('catStrings').getString('staff.cat.marcedit.next_page.label'),
+                    command : function(event) { 
+                        auth_pages[menu_id] += 1;
+                        show_auth_menu = true;
+                    }
+                })
+            );
+        }
+
+        target.setAttribute('context', menu_id);
+        return true;
+    }});
+
+}
+
+function summarizeField(sf) {
+    var source_f= {
+        "tag": '',
+        "ind1": '',
+        "ind2": '',
+        "subfields": []
+    };
+    for (var i = 0; i < sf.parent().subfield.length(); i++) {
+        source_f.subfields.push([sf.parent().subfield[i]. at code.toString(), sf.parent().subfield[i].toString()]);
+    }
+    source_f.tag = sf.parent(). at tag.toString();
+    source_f.ind1 = sf.parent(). at ind1.toString();
+    source_f.ind1 = sf.parent(). at ind2.toString();
+    return source_f;
+}
+
+
+function buildBibSourceList (authtoken, recId) {
+    /* TODO: Work out how to set the bib source of the bre that does not yet
+     * exist - this is specifically in the case of Z39.50 imports. Right now
+     * we just avoid populating and showing the config.bib_source list
+     */
+    if (!recId) {
+        return false;
+    }
+
+    var bib = xulG.record.bre;
+
+    dojo.require('openils.PermaCrud');
+
+    // cbsList = the XUL menulist that contains the available bib sources 
+    var cbsList = dojo.byId('bib-source-list');
+
+    // bibSources = an array containing all of the bib source objects
+    var bibSources = new openils.PermaCrud({"authtoken": authtoken}).retrieveAll('cbs');
+
+    // A tad ugly, but gives us the index of the bib source ID in cbsList
+    var x = 0;
+    var cbsListArr = [];
+    dojo.forEach(bibSources, function (item) {
+        cbsList.appendItem(item.source(), item.id());
+        cbsListArr[item.id()] = x;
+        x++;
+    });
+
+    // Show the current value of the bib source for this record
+    cbsList.selectedIndex = cbsListArr[bib.source()];
+
+    // Display the bib source selection widget
+    dojo.byId('bib-source-list-caption').hidden = false;
+    dojo.byId('bib-source-list').hidden = false;
+    dojo.byId('bib-source-list-button').disabled = true;
+    dojo.byId('bib-source-list-button').hidden = false;
+}
+
+// Fired when the "Update Source" button is clicked
+// Updates the value of the bib source for the current record
+function updateBibSource() {
+    var authtoken = ses();
+    var cbs = dojo.byId('bib-source-list').selectedItem.value;
+    var recId = xulG.record.id;
+    var pcrud = new openils.PermaCrud({"authtoken": authtoken});
+    var bib = pcrud.retrieve('bre', recId);
+    if (bib.source() != cbs) {
+        bib.source(cbs);
+        bib.ischanged = true;
+        pcrud.update(bib);
+    }
+}
+
+function onBibSourceSelect() {
+    var cbs = dojo.byId('bib-source-list').selectedItem.value;
+    var bib = xulG.record.bre;
+    if (bib.source() != cbs) {
+        dojo.byId('bib-source-list-button').disabled = false;   
+    } else {
+        dojo.byId('bib-source-list-button').disabled = true;   
+    }
+}
+
+function loadMarcEditor(pcrud, marcxml, target, sf) {
+    /*
+       To run in Firefox directly, must set signed.applets.codebase_principal_support
+       to true in about:config
+     */
+    netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
+    win = window.open('/xul/server/cat/marcedit.xul'); // XXX version?
+
+    // Match marc2are.pl last_xact_id format, roughly
+    var now = new Date;
+    var xact_id = 'IMPORT-' + Date.parse(now);
+    
+    win.xulG = {
+        "record": {"marc": marcxml, "rtype": "are"},
+        "save": {
+            "label": $('catStrings').getString('staff.cat.marcedit.save.label'),
+            "func": function(xmlString) {
+                var rec = new are();
+                rec.marc(xmlString);
+                rec.last_xact_id(xact_id);
+                rec.isnew(true);
+                pcrud.create(rec, {
+                    "oncomplete": function (r, objs) {
+                        var new_rec = objs[0];
+                        if (!new_rec) {
+                            return '';
+                        }
+                        var id_sf = <subfield code="0" xmlns="http://www.loc.gov/MARC21/slim">(CONS){new_rec.id()}</subfield>;
+                        sf.parent().appendChild(id_sf);
+                        var new_sf = marcSubfield(id_sf);
+                        target.parentNode.appendChild(new_sf);
+                        alert($('catStrings').getString('staff.cat.marcedit.create_authority_success.label'));
+                        win.close();
+                    }
+                });
+            }
+        }
+    };
+}
+
+

Modified: branches/serials-integration/Open-ILS/xul/staff_client/server/cat/marcedit.xul
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/server/cat/marcedit.xul	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/xul/staff_client/server/cat/marcedit.xul	2010-10-18 13:46:56 UTC (rev 18371)
@@ -236,6 +236,12 @@
                 </grid>
             </vbox>
         </groupbox>
+
+            <vbox>
+                <caption id="bib-source-list-caption" hidden="true">&staff.cat.marcedit.source.caption;</caption>
+                <menulist id="bib-source-list" rows="3" hidden="true" onselect='onBibSourceSelect();'><menupopup id='bib-source-list-popup'></menupopup></menulist>
+                <button id="bib-source-list-button" label="&staff.cat.marcedit.source.submit.label;" disabled="true" oncommand="updateBibSource();" hidden="true"/>
+            </vbox>
         </hbox>
 
         <grid id="recGrid" flex="1">

Modified: branches/serials-integration/Open-ILS/xul/staff_client/server/cat/spine_labels.js
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/server/cat/spine_labels.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/xul/staff_client/server/cat/spine_labels.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -33,11 +33,18 @@
                 for (var i = 0; i < g.barcodes.length; i++) {
                     var copy = g.network.simple_request( 'FM_ACP_RETRIEVE_VIA_BARCODE.authoritative', [ g.barcodes[i] ] );
                     if (typeof copy.ilsevent != 'undefined') throw(copy);
+                    var label_prefix = copy.location().label_prefix() || '';
+                    var label_suffix = copy.location().label_suffix() || '';
                     if (!g.volumes[ copy.call_number() ]) {
                         var volume = g.network.simple_request( 'FM_ACN_RETRIEVE.authoritative', [ copy.call_number() ] );
                         if (typeof volume.ilsevent != 'undefined') throw(volume);
                         var record = g.network.simple_request('MODS_SLIM_RECORD_RETRIEVE.authoritative', [ volume.record() ]);
                         volume.record( record );
+
+                        /* Jam the prefixes and suffixes into the volume object */
+                        volume.prefix = label_prefix;
+                        volume.suffix = label_suffix;
+
                         g.volumes[ volume.id() ] = volume;
                     }
                     if (g.volumes[ copy.call_number() ].copies()) {
@@ -67,142 +74,398 @@
             alert( util.functional.map_list( g.cols, function(o) { return '%' + o.id + '%'; } ).join(" ") );
         }
 
-        function $(id) { return document.getElementById(id); }
+        function $(id) { return dojo.byId(id); }
 
-        function generate() {
+        function generate(override) {
             try {
                 var idx = 0;
-                JSAN.use('util.text'); JSAN.use('util.money');
-                JSAN.use('util.widgets'); util.widgets.remove_children('panel'); var pn = $('panel'); $('preview').disabled = false;
-                var lw = Number($('lw').value) || 8; /* spine label width */
-                var ll = Number($('ll').value) || 9; /* spine label length */
-                var plw = Number($('plw').value) || 28; /* pocket label width */
-                var pll = Number($('pll').value) || 9; /* pocket label length */
-                for (var i in g.volumes) {
-                    var vb = document.createElement('vbox'); pn.appendChild(vb); vb.setAttribute('name','template'); vb.setAttribute('acn_id',g.volumes[i].id());
-                    var ds = document.createElement('description'); vb.appendChild(ds);
-                    ds.appendChild( document.createTextNode( g.volumes[i].label() ) );
-                    var ds2 = document.createElement('description'); vb.appendChild(ds2);
-                    ds2.appendChild( document.createTextNode( g.volumes[i].copies().length + (
-                        g.volumes[i].copies().length == 1 ? $("catStrings").getString('staff.cat.spine_labels.copy') : $("catStrings").getString('staff.cat.spine_labels.copies')) ) );
-                    ds2.setAttribute('style','color: green');
-                    var hb = document.createElement('hbox'); vb.appendChild(hb);
+                JSAN.use('util.text');
+                JSAN.use('util.money');
+                JSAN.use('util.widgets');
+                var pn = $('panel');
+                $('preview').disabled = false;
 
-                    var gb = document.createElement('groupbox'); hb.appendChild(gb); 
-                    /* take the call number and split it on whitespace */
-                    var names = String(g.volumes[i].label()).split(/\s+/);
-                    var j = 0;
-                    while (j < ll || j < pll) {
-                        var hb2 = document.createElement('hbox'); gb.appendChild(hb2);
-                        
-                        /* spine */
-                        if (j < ll) {
-                            var tb = document.createElement('textbox'); hb2.appendChild(tb); 
-                            tb.value = '';
-                            tb.setAttribute('class','plain'); tb.setAttribute('style','font-family: monospace');
-                            tb.setAttribute('size',lw+1); tb.setAttribute('maxlength',lw);
-                            tb.setAttribute('name','spine');
-                            var name = names.shift(); if (name) {
-                                name = String( name );
-                                /* if the name is greater than the label width... */
-                                if (name.length > lw) {
-                                    /* then try to split it on periods */
-                                    var sname = name.split(/\./);
-                                    if (sname.length > 1) {
-                                        /* if we can, then put the periods back in on each splitted element */
-                                        if (name.match(/^\./)) sname[0] = '.' + sname[0];
-                                        for (var k = 1; k < sname.length; k++) sname[k] = '.' + sname[k];
-                                        /* and put all but the first one back into the names array */
-                                        names = sname.slice(1).concat( names );
-                                        /* if the name fragment is still greater than the label width... */
-                                        if (sname[0].length > lw) {
-                                            /* then just truncate and throw the rest back into the names array */
-                                            tb.value = sname[0].substr(0,lw);
-                                            names = [ sname[0].substr(lw) ].concat( names );
-                                        } else {
-                                            /* otherwise we're set */
-                                            tb.value = sname[0];
-                                        }
-                                    } else {
-                                        /* if we can't split on periods, then just truncate and throw the rest back into the names array */
-                                        tb.value = name.substr(0,lw);
-                                        names = [ name.substr(lw) ].concat( names );
-                                    }
+                /* Grab from OU settings, then fall back to hardcoded defaults */
+                var label_cfg = {};
+                label_cfg.spine_width = Number($('lw').value); /* spine label width */
+                if (!label_cfg.spine_width) {
+                    label_cfg.spine_width = g.data.hash.aous['cat.spine.line.width'] || 8;
+                    $('lw').value = label_cfg.spine_width;
+                }
+                label_cfg.spine_length = Number($('ll').value); /* spine label length */
+                if (!label_cfg.spine_length) {
+                    label_cfg.spine_length = g.data.hash.aous['cat.spine.line.height'] || 9;
+                    $('ll').value = label_cfg.spine_length;
+                }
+                label_cfg.spine_left_margin = Number($('lm').value); /* left margin */
+                if (!label_cfg.spine_left_margin) {
+                    label_cfg.spine_left_margin = g.data.hash.aous['cat.spine.line.margin'] || 0;
+                    $('lm').value = label_cfg.spine_left_margin;
+                }
+                label_cfg.font_size = Number( $('pt').value );  /* font size */
+                if (!label_cfg.font_size) {
+                    label_cfg.font_size = g.data.hash.aous['cat.label.font.size'] || 10;
+                    $('pt').value = label_cfg.font_size;
+                }
+                label_cfg.font_weight = $('font_weight').value;  /* font weight */
+                if (!label_cfg.font_weight) {
+                    label_cfg.font_weight = g.data.hash.aous['cat.label.font.weight'] || 'normal';
+                    $('font_weight').value = label_cfg.font_weight;
+                }
+                label_cfg.font_family = g.data.hash.aous['cat.label.font.family'] || 'monospace';
+                label_cfg.pocket_width = Number($('plw').value) || 28; /* pocket label width */
+                label_cfg.pocket_length = Number($('pll').value) || 9; /* pocket label length */
+
+                if (override) {
+                    var gb = $('acn_' + g.volumes[override.acn].id());
+                    util.widgets.remove_children('acn_' + g.volumes[override.acn].id());
+                    generate_labels(g.volumes[override.acn], gb, label_cfg, override);
+                } else {
+                    util.widgets.remove_children('panel');
+                    for (var i in g.volumes) {
+                        var vb = document.createElement('vbox'); pn.appendChild(vb);
+                        vb.setAttribute('name','template');
+                        vb.setAttribute('acn_id',g.volumes[i].id());
+                        var ds = document.createElement('description'); vb.appendChild(ds);
+                        ds.appendChild( document.createTextNode( g.volumes[i].label() ) );
+                        var ds2 = document.createElement('description'); vb.appendChild(ds2);
+                        ds2.appendChild( document.createTextNode( g.volumes[i].copies().length + ' ' + (
+                            g.volumes[i].copies().length == 1 ? $("catStrings").getString('staff.cat.spine_labels.copy') : $("catStrings").getString('staff.cat.spine_labels.copies')) ) );
+                        ds2.setAttribute('style','color: green');
+                        var hb = document.createElement('hbox'); vb.appendChild(hb);
+
+                        var gb = document.createElement('groupbox');
+                        hb.appendChild(gb); 
+                        gb.setAttribute('id','acn_' + g.volumes[i].id());
+                        gb.setAttribute('style','border: solid black 2px');
+
+                        generate_labels(g.volumes[i], gb, label_cfg, override);
+
+                        idx++;
+                    }
+                }
+            } catch(E) {
+                g.error.standard_unexpected_error_alert($("catStrings").getString('staff.cat.spine_labels.generate.std_unexpeceted_err'),E);
+            }
+        }
+
+        function generate_labels(volume, label_node, label_cfg, override) {
+            var names;
+            var callnum;
+
+            if (override && volume.id() == override.acn) {
+                /* If we're calling ourself, we'll have an altered label */
+                callnum = String(override.label);
+            } else {
+                /* take the call number and split it on whitespace */
+                callnum = String(volume.label());
+            }
+
+            /* for LC, split between classification subclass letters and numbers */
+            var lc_class_re = /^([A-Z]{1,3})([0-9]+.*?)$/i;
+            var lc_class_match = lc_class_re.exec(callnum);
+            if (lc_class_match && lc_class_match.length > 1) {
+                callnum = lc_class_match[1] + ' ' + lc_class_match[2];
+            }
+
+            /* for LC, split between Cutter numbers */
+            var lc_cutter_re = /^(.*)(\.[A-Z]{1}[0-9]+.*?)$/ig;
+            var lc_cutter_match = lc_cutter_re.exec(callnum);
+            if (lc_cutter_match && lc_cutter_match.length > 1) {
+                callnum = '';
+                for (var i = 1; i < lc_cutter_match.length; i++) {
+                    callnum += lc_cutter_match[i] + ' ';
+                }
+            }
+
+            /* Only add the prefixes and suffixes once */
+            if (!override || volume.id() != override.acn) {
+                if (volume.prefix) {
+                    callnum = volume.prefix + ' ' + callnum;
+                }
+                if (volume.suffix) {
+                    callnum += ' ' + volume.suffix;
+                }
+            }
+
+            names = callnum.split(/\s+/);
+            var j = 0;
+            while (j < label_cfg.spine_length || j < label_cfg.pocket_length) {
+                var hb2 = document.createElement('hbox'); label_node.appendChild(hb2);
+                
+                /* spine */
+                if (j < label_cfg.spine_length) {
+                    var tb = document.createElement('textbox'); hb2.appendChild(tb); 
+                    tb.value = '';
+                    tb.setAttribute('class','plain');
+                    tb.setAttribute('style',
+                        'font-family: ' + label_cfg.font_family
+                        + '; font-size: ' + label_cfg.font_size
+                        + '; font-weight: ' + label_cfg.font_weight
+                    );
+                    tb.setAttribute('size',label_cfg.spine_width+1);
+                    tb.setAttribute('maxlength',label_cfg.spine_width);
+                    tb.setAttribute('name','spine');
+                    var spine_row_id = 'acn_' + volume.id() + '_spine_' + j;
+                    tb.setAttribute('id',spine_row_id);
+
+                    var name = names.shift();
+                    if (name) {
+                        name = String( name );
+
+                        /* if the name is greater than the label width... */
+                        if (name.length > label_cfg.spine_width) {
+                            /* then try to split it on periods */
+                            var sname = name.split(/\./);
+                            if (sname.length > 1) {
+                                /* if we can, then put the periods back in on each splitted element */
+                                if (name.match(/^\./)) sname[0] = '.' + sname[0];
+                                for (var k = 1; k < sname.length; k++) sname[k] = '.' + sname[k];
+                                /* and put all but the first one back into the names array */
+                                names = sname.slice(1).concat( names );
+                                /* if the name fragment is still greater than the label width... */
+                                if (sname[0].length > label_cfg.spine_width) {
+                                    /* then just truncate and throw the rest back into the names array */
+                                    tb.value = sname[0].substr(0,label_cfg.spine_width);
+                                    names = [ sname[0].substr(label_cfg.spine_width) ].concat( names );
                                 } else {
                                     /* otherwise we're set */
-                                    tb.value = name;
+                                    tb.value = sname[0];
                                 }
+                            } else {
+                                /* if we can't split on periods, then just truncate and throw the rest back into the names array */
+                                tb.value = name.substr(0,label_cfg.spine_width);
+                                names = [ name.substr(label_cfg.spine_width) ].concat( names );
                             }
+                        } else {
+                            /* otherwise we're set */
+                            tb.value = name;
                         }
+                    }
+                    dojo.connect($(spine_row_id), 'onkeypress', 'spine_label_key_events');
+                }
 
-                        /* pocket */
-                        if ($('pl').checked && j < pll) {
-                            var tb2 = document.createElement('textbox'); hb2.appendChild(tb2); 
+                /* pocket */
+                if ($('pl').checked && j < label_cfg.pocket_length) {
+                    var tb2 = document.createElement('textbox'); hb2.appendChild(tb2); 
+                    tb2.value = '';
+                    tb2.setAttribute('class','plain');
+                    tb2.setAttribute('style',
+                        'font-family: ' + label_cfg.font_family
+                        + '; font-size: ' + label_cfg.font_size
+                        + '; font-weight: ' + label_cfg.font_weight
+                    );
+                    tb2.setAttribute('size',label_cfg.pocket_width+1); tb2.setAttribute('maxlength',label_cfg.pocket_width);
+                    tb2.setAttribute('name','pocket');
+                    if ($('title').checked && $('title_line').value == j + 1 && instanceOf(volume.record(),mvr)) {
+                        if (volume.record().title()) {
+                            tb2.value = util.text.wrap_on_space( volume.record().title(), label_cfg.pocket_width )[0];
+                        } else {
                             tb2.value = '';
-                            tb2.setAttribute('class','plain'); tb2.setAttribute('style','font-family: monospace');
-                            tb2.setAttribute('size',plw+1); tb2.setAttribute('maxlength',plw);
-                            tb2.setAttribute('name','pocket');
-                            if ($('title').checked && $('title_line').value == j + 1 && instanceOf(g.volumes[i].record(),mvr)) {
-                                if (g.volumes[i].record().title()) {
-                                    tb2.value = util.text.wrap_on_space( g.volumes[i].record().title(), plw )[0];
-                                } else {
-                                    tb2.value = '';
-                                }
+                        }
+                    }
+                    if ($('title_r').checked && $('title_r_line').value == j + 1 && instanceOf(volume.record(),mvr)) {
+                        if (volume.record().title()) {
+                            tb2.value = ( ($('title_r_indent').checked ? ' ' : '') + util.text.wrap_on_space( volume.record().title(), label_cfg.pocket_width )[1]).substr(0,label_cfg.pocket_width);
+                        } else {
+                            tb2.value = '';
+                        }
+                    }
+                    if ($('author').checked && $('author_line').value == j + 1 && instanceOf(volume.record(),mvr)) {
+                        if (volume.record().author()) {
+                            tb2.value = volume.record().author().substr(0,label_cfg.pocket_width);
+                        } else {
+                            tb2.value = '';
+                        }
+                    }
+                    if ($('call_number').checked && $('call_number_line').value == j + 1) {
+                        tb2.value = volume.label().substr(0,label_cfg.pocket_width);
+                    }
+                    if ($('owning_lib_shortname').checked && $('owning_lib_shortname_line').value == j + 1) {
+                        var lib = volume.owning_lib();
+                        if (!instanceOf(lib,aou)) lib = g.data.hash.aou[ lib ];
+                        tb2.value = lib.shortname().substr(0,label_cfg.pocket_width);
+                    }
+                    if ($('owning_lib').checked && $('owning_lib_line').value == j + 1) {
+                        var lib = volume.owning_lib();
+                        if (!instanceOf(lib,aou)) lib = g.data.hash.aou[ lib ];
+                        tb2.value = lib.name().substr(0,label_cfg.pocket_width);
+                    }
+                    if ($('shelving_location').checked && $('shelving_location_line').value == j + 1) {
+                        tb2.value = '%location%';
+                    }
+                    if ($('barcode').checked && $('barcode_line').value == j + 1) {
+                        tb2.value = '%barcode%';
+                    }
+                    if ($('custom1').checked && $('custom1_line').value == j + 1) {
+                        tb2.value = $('custom1_tb').value;
+                    }
+                    if ($('custom2').checked && $('custom2_line').value == j + 1) {
+                        tb2.value = $('custom2_tb').value;
+                    }
+                    if ($('custom3').checked && $('custom3_line').value == j + 1) {
+                        tb2.value = $('custom3_tb').value;
+                    }
+                    if ($('custom4').checked && $('custom4_line').value == j + 1) {
+                        tb2.value = $('custom4_tb').value;
+                    }
+                }
+
+                j++;
+            }
+        }
+
+        function spine_label_key_events (event) {
+
+            /* Current value of the inpux box */
+            var line_value = event.target.value;
+
+            /* Cursor positions */
+            var sel_start = event.target.selectionStart;
+            var sel_end = event.target.selectionEnd;
+
+            /* Identifiers for this row: "acn_ID_spine_ROW" */
+            var atts = event.target.id.split('_');
+            var row_id = {
+                "acn": atts[1],
+                "spine": atts[3],
+                "prefix": 'acn_' + atts[1] + '_spine_'
+            };
+
+            switch (event.charOrCode) {
+                case dojo.keys.ENTER : {
+                    /* Create a new row by inserting a space at the
+                     * current cursor point, then regenerating the
+                     * label
+                     */
+                    if (sel_start == sel_end) {
+                        if (sel_start == 0) {
+                            /* If the cursor is at the start of the line:
+                             * insert new line
+                             */
+                            line_value = ' ' + line_value;
+                        } else if (sel_start == line_value.length) {
+                            /* Special case if the cursor is at the end of the line:
+                             * move to next line
+                             */
+                            var next_row = $(row_id.prefix + (parseInt(row_id.spine) + 1));
+                            if (next_row) {
+                                next_row.focus();
                             }
-                            if ($('title_r').checked && $('title_r_line').value == j + 1 && instanceOf(g.volumes[i].record(),mvr)) {
-                                if (g.volumes[i].record().title()) {
-                                    tb2.value = ( ($('title_r_indent').checked ? ' ' : '') + util.text.wrap_on_space( g.volumes[i].record().title(), plw )[1]).substr(0,plw);
-                                } else {
-                                    tb2.value = '';
-                                }
+                            break;
+                        } else {
+                            line_value = line_value.substr(0, sel_start) + ' ' + line_value.substr(sel_end);
+                        }
+                    } else {
+                        line_value = line_value.substr(0, sel_start) + ' ' + line_value.substr(sel_end);
+                    }
+                    event.target.value = line_value;
+
+                    /* Recreate the label */
+                    var new_label = '';
+                    var chunk;
+                    var x = 0;
+                    while (chunk = $(row_id.prefix + x)) {
+                        if (x > 0) {
+                            new_label += ' ' + chunk.value;
+                        } else {
+                            new_label = chunk.value;
+                        }
+                        x++;
+                    }
+                    generate({"acn": row_id.acn, "label": new_label});
+                    $(row_id.prefix + row_id.spine).focus();
+                    break;
+                }
+
+                case dojo.keys.BACKSPACE : {
+                    /* Delete line if at the start of an input box */
+                    if (sel_start == 0 && sel_end == sel_start) {
+                        var new_label = '';
+                        var chunk;
+                        var x = 0;
+                        while (x <= (row_id.spine - 1) && (chunk = $(row_id.prefix + x))) {
+                            if (x > 0) {
+                                new_label += ' ' + chunk.value;
+                            } else {
+                                new_label = chunk.value;
                             }
-                            if ($('author').checked && $('author_line').value == j + 1 && instanceOf(g.volumes[i].record(),mvr)) {
-                                if (g.volumes[i].record().author()) {
-                                    tb2.value = g.volumes[i].record().author().substr(0,plw);
-                                } else {
-                                    tb2.value = '';
-                                }
+                            x++;
+                        }
+
+                        if (chunk = $(row_id.prefix + x)) {
+                            new_label += chunk.value;
+                            x++;
+                        }
+
+                        while (chunk = $(row_id.prefix + x)) {
+                            new_label += ' ' + chunk.value;
+                            x++;
+                        }
+                        generate({"acn": row_id.acn, "label": new_label});
+                        $(row_id.prefix + row_id.spine).focus();
+                    }
+                    if (sel_start == 0) {
+                        /* Move to the previous row */
+                        var prev_row = $(row_id.prefix + (parseInt(row_id.spine) - 1));
+                        if (prev_row) {
+                            prev_row.focus();
+                        }
+                    }
+                    break;
+                }
+
+                case dojo.keys.DELETE : {
+                    /* Delete line if at the end of an input box */
+                    if (sel_start == event.target.textLength) {
+                        var new_label = '';
+                        var chunk;
+                        var x = 0;
+                        while (x <= row_id.spine && (chunk = $(row_id.prefix + x))) {
+                            if (x > 0) {
+                                new_label += ' ' + chunk.value;
+                            } else {
+                                new_label = chunk.value;
                             }
-                            if ($('call_number').checked && $('call_number_line').value == j + 1) {
-                                tb2.value = g.volumes[i].label().substr(0,plw);
-                            }
-                            if ($('owning_lib_shortname').checked && $('owning_lib_shortname_line').value == j + 1) {
-                                var lib = g.volumes[i].owning_lib();
-                                if (!instanceOf(lib,aou)) lib = g.data.hash.aou[ lib ];
-                                tb2.value = lib.shortname().substr(0,plw);
-                            }
-                            if ($('owning_lib').checked && $('owning_lib_line').value == j + 1) {
-                                var lib = g.volumes[i].owning_lib();
-                                if (!instanceOf(lib,aou)) lib = g.data.hash.aou[ lib ];
-                                tb2.value = lib.name().substr(0,plw);
-                            }
-                            if ($('shelving_location').checked && $('shelving_location_line').value == j + 1) {
-                                tb2.value = '%location%';
-                            }
-                            if ($('barcode').checked && $('barcode_line').value == j + 1) {
-                                tb2.value = '%barcode%';
-                            }
-                            if ($('custom1').checked && $('custom1_line').value == j + 1) {
-                                tb2.value = $('custom1_tb').value;
-                            }
-                            if ($('custom2').checked && $('custom2_line').value == j + 1) {
-                                tb2.value = $('custom2_tb').value;
-                            }
-                            if ($('custom3').checked && $('custom3_line').value == j + 1) {
-                                tb2.value = $('custom3_tb').value;
-                            }
-                            if ($('custom4').checked && $('custom4_line').value == j + 1) {
-                                tb2.value = $('custom4_tb').value;
-                            }
+                            x++;
                         }
 
-                        j++;
+                        if (chunk = $(row_id.prefix + x)) {
+                            new_label += chunk.value;
+                            x++;
+                        }
+
+                        while (chunk = $(row_id.prefix + x)) {
+                            new_label += ' ' + chunk.value;
+                            x++;
+                        }
+                        generate({"acn": row_id.acn, "label": new_label});
+                        $(row_id.prefix + row_id.spine).focus();
                     }
+                    break;
+                }
 
-                    idx++;
+                case dojo.keys.UP_ARROW : {
+                    /* Move to the previous row */
+                    var prev_row = $(row_id.prefix + (parseInt(row_id.spine) - 1));
+                    if (prev_row) {
+                        prev_row.focus();
+                    }
+                    break;
                 }
-            } catch(E) {
-                g.error.standard_unexpected_error_alert($("catStrings").getString('staff.cat.spine_labels.generate.std_unexpeceted_err'),E);
+
+                case dojo.keys.DOWN_ARROW : {
+                    /* Move to the next row */
+                    var next_row = $(row_id.prefix + (parseInt(row_id.spine) + 1));
+                    if (next_row) {
+                        next_row.focus();
+                    }
+                    break;
+                }
+
+                default : {
+                    break;
+                }
             }
         }
 
@@ -225,14 +488,35 @@
         function preview(idx) {
             try {
                     netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
-                    var pt = Number( $('pt').value ) || 10;  /* font size */
-                    var lm = Number($('lm').value); if (lm == NaN) lm = 11; /* left margin */
+                    var pt = Number( $('pt').value );  /* font size */
+                    if (!pt) {
+                        pt = g.data.hash.aous['cat.label.font.size'] || 10;
+                        $('pt').value = pt;
+                    }
+                    var ff = g.data.hash.aous['cat.label.font.family'] || 'monospace';
+                    var fw = $('font_weight').value;  /* font weight */
+                    if (!fw) {
+                        fw = g.data.hash.aous['cat.label.font.weight'] || 'normal';
+                    }
+                    var lm = Number($('lm').value); /* left margin */
+                    if (!lm) {
+                        lm = g.data.hash.aous['cat.spine.line.margin'] || 0;
+                    }
                     var mm = Number($('mm').value); if (mm == NaN) mm = 2; /* middle margin */
-                    var lw = Number($('lw').value) || 8; var ll = Number($('ll').value) || 9; /* spine label width and length */
+                    var lw = Number($('lw').value); /* spine label width */
+                    if (!lw) {
+                        lw = g.data.hash.aous['cat.spine.line.width'] || 8;
+                        $('lw').value = lw;
+                    }
+                    var ll = Number($('ll').value); /* spine label length */
+                    if (!ll) {
+                        ll = g.data.hash.aous['cat.spine.line.height'] || 9;
+                        $('ll').value = ll;
+                    }
                     var plw = Number($('plw').value) || 28; var pll = Number($('pll').value) || 9; /* pocket label width and length */
                     var html = "<html><head>";
                     html += "<link type='text/css' rel='stylesheet' href='" + xulG.url_prefix('/xul/server/skin/print.css') + "'></link>"
-                    html += "<link type='text/css' rel='stylesheet' href='data:text/css,pre{font-size:" + pt + "pt;}'></link>";
+                    html += "<link type='text/css' rel='stylesheet' href='data:text/css,pre{font-family:" + ff + ";font-size:" + pt + "pt; font-weight: " + fw + ";}'></link>";
                     html += "<title>Spine Labels</title></head><body>\n";
                     var nl = document.getElementsByAttribute('name','template');
                     for (var i = 0; i < nl.length; i++) {
@@ -267,22 +551,65 @@
                         }
                     }
                     html += '</body></html>';
-                    var loc = ( urls.XUL_BROWSER );
-                    xulG.new_tab(
-                        loc,
-                        {
-                            'tab_name' : $("catStrings").getString('staff.cat.spine_labels.preview.title')
-                        },
-                        { 
-                            'url' : 'data:text/html;charset=utf-8,'+window.escape(html),
-                            'html_source' : html,
-                            'show_print_button' : 1,
-                            'no_xulG' : 1
-                        }
-                    );
+
+                    /* From https://developer.mozilla.org/en/Using_nsIXULAppInfo */
+                    var appInfo = Components.classes["@mozilla.org/xre/app-info;1"]
+                                            .getService(Components.interfaces.nsIXULAppInfo);
+                    var platformVer = appInfo.platformVersion;
+
+                    /* We need to use different print strategies for different
+                     * XUL versions, apparently
+                     */
+                    if (platformVer.substr(0, 5) == '1.9.0') {
+                        preview_xul_190(html);
+                    } else {
+                        preview_xul_192(html);
+                    }
+
+
             } catch(E) {
                 g.error.standard_unexpected_error_alert($("catStrings").getString('staff.cat.spine_labels.preview.std_unexpected_err'),E);
             }
         }
 
+        function preview_xul_190(html) {
+            JSAN.use('util.window'); var win = new util.window();
+            var loc = ( urls.XUL_REMOTE_BROWSER );
+            //+ '?url=' + window.escape('about:blank') + '&show_print_button=1&alternate_print=1&no_xulG=1&title=' + window.escape('Spine Labels');
+            var w = win.open( loc, 'spine_preview', 'chrome,resizable,width=750,height=550');
+            w.xulG = { 
+                'url' : 'about:blank',
+                'show_print_button' : 1,
+                'alternate_print' : 1,
+                'no_xulG' : 1,
+                'title' : $("catStrings").getString('staff.cat.spine_labels.preview.title'),
+                'on_url_load' : function(b) { 
+                    try { 
+                        netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
+                        if (typeof w.xulG.written == 'undefined') {
+                            w.xulG.written = true;
+                            w.g.browser.get_content().document.write(html);
+                            w.g.browser.get_content().document.close();
+                        }
+                    } catch(E) {
+                        alert(E);
+                    }
+                }
+            };
+        }
 
+        function preview_xul_192(html) {
+            var loc = ( urls.XUL_BROWSER );
+            xulG.new_tab(
+                loc,
+                {
+                    'tab_name' : $("catStrings").getString('staff.cat.spine_labels.preview.title')
+                },
+                { 
+                    'url' : 'data:text/html;charset=utf-8,'+window.escape(html),
+                    'html_source' : html,
+                    'show_print_button' : 1,
+                    'no_xulG' : 1
+                }
+            );
+        }

Modified: branches/serials-integration/Open-ILS/xul/staff_client/server/cat/spine_labels.xul
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/server/cat/spine_labels.xul	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/xul/staff_client/server/cat/spine_labels.xul	2010-10-18 13:46:56 UTC (rev 18371)
@@ -47,16 +47,22 @@
                     accesskey="&staff.cat.spine_labels.close_window.accesskey;" oncommand="window.close()"/>
             </hbox>
 
-            <hbox>
-                <label value="&staff.cat.spine_labels.font_size.label;" control="pt"/>
-                <textbox id="pt" value="10" onchange="this.setAttribute('value',this.value)" oils_persist="value" context="clipboard"/>
-            </hbox>
+            <grid><columns><column/><column/></columns><rows>
+                <row>
+                    <label value="&staff.cat.spine_labels.font_size.label;" control="pt"/>
+                    <textbox id="pt" value="" onchange="this.setAttribute('value',this.value)" oils_persist="value" context="clipboard"/>
+                </row>
+                <row>
+                    <label value="&staff.cat.spine_labels.font_weight.label;" control="font_weight"/>
+                    <textbox id="font_weight" value="" onchange="this.setAttribute('value',this.value)" oils_persist="value" context="clipboard"/>
+                </row>
+            </rows></grid>
             <grid><columns><column/><column/><column/><column/></columns><rows>
                 <row> <label class="header" value="&staff.cat.spine_labels.spine_label.label;"/><spacer/> </row>
-                <row> <label value="&staff.cat.spine_labels.spine_label.left_margin.label;" control="lm"/><textbox id="lm" value="0" onchange="this.setAttribute('value',this.value)" oils_persist="value" context="clipboard"/> </row>
-                <row> <label value="&staff.cat.spine_labels.spine_label.label_width.label;" control="lw"/><textbox id="lw" value="8" onchange="this.setAttribute('value',this.value)" oils_persist="value" context="clipboard"/> </row>
-                <row> <label value="&staff.cat.spine_labels.spine_label.label_length.label;" control="ll"/><textbox id="ll" value="9" onchange="this.setAttribute('value',this.value)" oils_persist="value" context="clipboard"/> </row>
-                <row> <label class="header" value="&staff.cat.spine_labels.pocket_label.label;"/><checkbox id="pl" checked="false" oils_persist="checked" label="Enabled"/> </row>
+                <row> <label value="&staff.cat.spine_labels.spine_label.left_margin.label;" control="lm"/><textbox id="lm" value="" onchange="this.setAttribute('value',this.value)" oils_persist="value" context="clipboard"/> </row>
+                <row> <label value="&staff.cat.spine_labels.spine_label.label_width.label;" control="lw"/><textbox id="lw" value="" onchange="this.setAttribute('value',this.value)" oils_persist="value" context="clipboard"/> </row>
+                <row> <label value="&staff.cat.spine_labels.spine_label.label_length.label;" control="ll"/><textbox id="ll" value="" onchange="this.setAttribute('value',this.value)" oils_persist="value" context="clipboard"/> </row>
+                <row> <label class="header" value="&staff.cat.spine_labels.pocket_label.label;"/><checkbox id="pl" checked="false" oils_persist="checked" label="&staff.cat.spine_labels.pocket_label.enabled.label;"/> </row>
                 <row> <label value="&staff.cat.spine_labels.pocket_label.middle_margin.label;" control="mm"/><textbox id="mm" value="2" onchange="this.setAttribute('value',this.value)" oils_persist="value" context="clipboard"/> </row>
                 <row> <label value="&staff.cat.spine_labels.pocket_label.label_width.label;" control="plw"/><textbox id="plw" value="28" onchange="this.setAttribute('value',this.value)" oils_persist="value" context="clipboard"/> </row>
                 <row> <label value="&staff.cat.spine_labels.pocket_label.label_length.label;" control="pll"/><textbox id="pll" value="9" onchange="this.setAttribute('value',this.value)" oils_persist="value" context="clipboard"/> </row>
@@ -76,7 +82,7 @@
                 </row>
                 <row> <spacer/><checkbox id="title_r_indent" checked="true" oils_persist="checked" label="&staff.cat.spine_labels.indent_title.label;"/> </row>
                 <row>
-                    <checkbox id="author" checked="true" oils_persist="checked" label="Include Author"/>
+                    <checkbox id="author" checked="true" oils_persist="checked" label="&staff.cat.spine_labels.pocket_label.include_author.label;"/>
                     <hbox>
                         <label value="&staff.cat.spine_labels.on_line.label;"/>
                         <textbox id="author_line" value="3" oils_persist="value" onchange="this.setAttribute('value',this.value)" context="clipboard"/>

Modified: branches/serials-integration/Open-ILS/xul/staff_client/server/cat/volume_copy_creator.js
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/server/cat/volume_copy_creator.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/xul/staff_client/server/cat/volume_copy_creator.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -29,16 +29,25 @@
         // g.existing_copies = [ copy1, copy2, ... ]
         g.existing_copies = xul_param('existing_copies') || [];
 
+        function set_attr(id,attr,msgcat_key) {
+            var x = $(id);
+            if (x) {
+                x.setAttribute(
+                    attr,
+                    $('catStrings').getString(msgcat_key)
+                );
+            }
+        }
         if (g.existing_copies.length > 0) {
-            document.getElementById('EditThenCreate').setAttribute('label',$('catStrings').getString('staff.cat.volume_copy_creator.edit_then_rebarcode.btn.label'));
-            document.getElementById('EditThenCreate').setAttribute('accesskey',$('catStrings').getString('staff.cat.volume_copy_creator.edit_then_rebarcode.btn.accesskey'));
-            document.getElementById('CreateWithDefaults').setAttribute('label',$('catStrings').getString('staff.cat.volume_copy_creator.rebarcode.btn.label'));
-            document.getElementById('CreateWithDefaults').setAttribute('accesskey',$('catStrings').getString('staff.cat.volume_copy_creator.rebarcode.btn.accesskey'));
+            set_attr('EditThenCreate','label','staff.cat.volume_copy_creator.edit_then_rebarcode.btn.label');
+            set_attr('EditThenCreate','accesskey','staff.cat.volume_copy_creator.edit_then_rebarcode.btn.accesskey');
+            set_attr('CreateWithDefaults','label','staff.cat.volume_copy_creator.rebarcode.btn.label');
+            set_attr('CreateWithDefaults','accesskey','staff.cat.volume_copy_creator.rebarcode.btn.accesskey');
         } else {
-            document.getElementById('EditThenCreate').setAttribute('label',$('catStrings').getString('staff.cat.volume_copy_creator.edit_then_create.btn.label'));
-            document.getElementById('EditThenCreate').setAttribute('accesskey',$('catStrings').getString('staff.cat.volume_copy_creator.edit_then_create.btn.accesskey'));
-            document.getElementById('CreateWithDefaults').setAttribute('label',$('catStrings').getString('staff.cat.volume_copy_creator.create_with_defaults.btn.label'));
-            document.getElementById('CreateWithDefaults').setAttribute('accesskey',$('catStrings').getString('staff.cat.volume_copy_creator.create_with_defaults.btn.accesskey'));
+            set_attr('EditThenCreate','label','staff.cat.volume_copy_creator.edit_then_create.btn.label');
+            set_attr('EditThenCreate','accesskey','staff.cat.volume_copy_creator.edit_then_create.btn.accesskey');
+            set_attr('CreateWithDefaults','label','staff.cat.volume_copy_creator.create_with_defaults.btn.label');
+            set_attr('CreateWithDefaults','accesskey','staff.cat.volume_copy_creator.create_with_defaults.btn.accesskey');
         }
 
         //g.error.sdump('D_ERROR','location.href = ' + location.href + '\n\ncopy_short cut = ' + g.copy_shortcut + '\n\nou_ids = ' + xul_param('ou_ids'));
@@ -47,11 +56,11 @@
 
         // Get the default callnumber classification scheme from OU settings
         dojo.require('fieldmapper.OrgUtils');
-        var label_class = fieldmapper.aou.fetchOrgSettingDefault(ses('ws_ou'), 'cat.default_classification_scheme');
+        var label_class = g.data.hash.aous['cat.default_classification_scheme']; //fieldmapper.aou.fetchOrgSettingDefault(ses('ws_ou'), 'cat.default_classification_scheme');
 
         // Assign a default value if none was returned 
         if (!label_class) {
-            label_class = { "value": 1 };
+            label_class = 1;
         }
 
         /***********************************************************************************************************/
@@ -97,8 +106,8 @@
         /***********************************************************************************************************/
         /* For the call number drop down */
 
-        if (!g.copy_shortcut) {
-            g.list_callnumbers(g.doc_id, label_class.value);
+        if (g.existing_copies.length > 0 || !g.copy_shortcut) {
+            g.list_callnumbers(g.doc_id, label_class);
         }
 
         /***********************************************************************************************************/
@@ -205,14 +214,16 @@
             return;
         }
 
-        //if (call_number_column_textbox.disabled || number_of_copies_column_textbox.disabled) return;
+        while (barcode_column_box.childNodes.length > Number(number_of_copies_column_textbox.value)) {
+            barcode_column_box.removeChild( barcode_column_box.lastChild );
+        }
+        g.render_barcode_entry(
+            barcode_column_box,
+            call_number_column_textbox.value,
+            Number(number_of_copies_column_textbox.value),
+            ou_id
+        );
 
-        //call_number_column_textbox.disabled = true;
-        //number_of_copies_column_textbox.disabled = true;
-
-        util.widgets.remove_children(barcode_column_box);
-
-        g.render_barcode_entry(barcode_column_box,call_number_column_textbox.value,Number(number_of_copies_column_textbox.value),ou_id);
         document.getElementById("EditThenCreate").disabled = false;
         document.getElementById("CreateWithDefaults").disabled = false;
     }
@@ -283,7 +294,9 @@
                             }
                             call_number_column_textbox.value = label; 
                             handle_change_call_number_column_textbox({'target':call_number_column_textbox});
-                            call_number_column_textbox.disabled = true;
+                            if (g.existing_copies.length < 1) {
+                                call_number_column_textbox.disabled = true;
+                            }
                         }
                     } catch(E) {
                         alert(E);
@@ -306,32 +319,40 @@
         JSAN.use('util.barcode'); 
 
         for (var i = 0; i < count; i++) {
-            var tb = document.createElement('textbox'); node.appendChild(tb);
+            var tb; var set_handlers = false;
+            if (typeof node.childNodes[i] == 'undefined') {
+                tb = document.createElement('textbox'); node.appendChild(tb);
+                set_handlers = true;
+            } else {
+                tb = node.childNodes[i];
+            }
             tb.setAttribute('ou_id',ou_id);
             tb.setAttribute('callnumber',callnumber);
             tb.setAttribute('rel_vert_pos','4');
-            if (g.org_label_existing_copy_map[ ou_id ]) {
+            if (!tb.value && g.org_label_existing_copy_map[ ou_id ]) {
                 tb.value = g.org_label_existing_copy_map[ ou_id ][ callnumber ][i].barcode();
                 tb.setAttribute('acp_id', g.org_label_existing_copy_map[ ou_id ][ callnumber ][i].id());
                 tb.select();
                 if (! g.first_focus) { g.first_focus = tb; }
             }
-            util.widgets.apply_vertical_tab_on_enter_handler( 
-                tb, 
-                function() { ready_to_create({'target':tb}); setTimeout(function(){util.widgets.vertical_tab(tb);},0); }
-            );
-            tb.addEventListener('change', function(ev) {
-                var barcode = String( ev.target.value ).replace(/\s/g,'');
-                if (barcode != ev.target.value) ev.target.value = barcode;
-                if ($('check_barcodes').checked && ! util.barcode.check(barcode) ) {
-                    g.error.yns_alert($("catStrings").getFormattedString('staff.cat.volume_copy_creator.render_barcode_entry.alert_message', [barcode]),
-                        $("catStrings").getString('staff.cat.volume_copy_creator.render_barcode_entry.alert_title'),
-                        $("catStrings").getString('staff.cat.volume_copy_creator.render_barcode_entry.alert_ok_button'),null,null,
-                        $("catStrings").getString('staff.cat.volume_copy_creator.render_barcode_entry.alert_confirm'));
-                    setTimeout( function() { ev.target.select(); ev.target.focus(); }, 0);
-                }
-            }, false);
-            tb.addEventListener( 'focus', function(ev) { g.last_focus = ev.target; }, false );
+            if (set_handlers) {
+                util.widgets.apply_vertical_tab_on_enter_handler( 
+                    tb, 
+                    function() { ready_to_create({'target':tb}); setTimeout(function(){util.widgets.vertical_tab(tb);},0); }
+                );
+                tb.addEventListener('change', function(ev) {
+                    var barcode = String( ev.target.value ).replace(/\s/g,'');
+                    if (barcode != ev.target.value) ev.target.value = barcode;
+                    if ($('check_barcodes').checked && ! util.barcode.check(barcode) ) {
+                        g.error.yns_alert($("catStrings").getFormattedString('staff.cat.volume_copy_creator.render_barcode_entry.alert_message', [barcode]),
+                            $("catStrings").getString('staff.cat.volume_copy_creator.render_barcode_entry.alert_title'),
+                            $("catStrings").getString('staff.cat.volume_copy_creator.render_barcode_entry.alert_ok_button'),null,null,
+                            $("catStrings").getString('staff.cat.volume_copy_creator.render_barcode_entry.alert_confirm'));
+                        setTimeout( function() { ev.target.select(); ev.target.focus(); }, 0);
+                    }
+                }, false);
+                tb.addEventListener( 'focus', function(ev) { g.last_focus = ev.target; }, false );
+            }
         }
         
         setTimeout( function() { if (g.first_focus) { g.first_focus.focus(); } }, 0 ); 
@@ -457,7 +478,7 @@
                     } else {
                         copy = g.id_copy_map[ acp_id ];
                         copy.barcode( barcode );
-                        copy.call_number( copy.call_number().id() );
+                        copy.call_number( acn_id );
                         copy.ischanged('1');
                     }
                     copies.push( copy );
@@ -574,17 +595,6 @@
                     return [ o[i], i ];
                 }
             }
-        ).sort(
-            function(a,b) {
-                a = a[1]; b = b[1];
-                if (a == '082') return -1; 
-                if (b == '082') return 1; 
-                if (a == '092')  return -1; 
-                if (b == '092')  return 1; 
-                if (a < b) return -1; 
-                if (a > b) return 1; 
-                return 0;
-            }
         )
     ); hbox.appendChild(ml);
     ml.setAttribute('editable','true');
@@ -600,7 +610,11 @@
             var nl = document.getElementsByTagName('textbox');
             for (var i = 0; i < nl.length; i++) {
                 if (nl[i].getAttribute('rel_vert_pos')==2 
-                    && !nl[i].disabled) nl[i].value = ml.value;
+                    && !nl[i].disabled) 
+                {
+                    nl[i].value = ml.value;
+                    util.widgets.dispatch('change',nl[i]);
+                }
             }
             if (g.last_focus) setTimeout( function() { g.last_focus.focus(); }, 0 );
         }, 

Modified: branches/serials-integration/Open-ILS/xul/staff_client/server/cat/z3950.js
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/server/cat/z3950.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/xul/staff_client/server/cat/z3950.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -709,7 +709,7 @@
             xulG.url_prefix(urls.XUL_MARC_EDIT), 
             { 'tab_name' : 'MARC Editor' }, 
             { 
-                'record' : { 'marc' : my_marcxml },
+                'record' : { 'marc' : my_marcxml, "rtype": "bre" },
                 'fast_add_item' : function(doc_id,cn_label,cp_barcode) {
                     try {
                         JSAN.use('cat.util'); return cat.util.fast_item_add(doc_id,cn_label,cp_barcode);

Modified: branches/serials-integration/Open-ILS/xul/staff_client/server/circ/alternate_copy_summary.js
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/server/circ/alternate_copy_summary.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/xul/staff_client/server/circ/alternate_copy_summary.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -168,7 +168,8 @@
             set("circ_as_type", details.copy.circ_as_type()); 
             set("copy_circ_lib" , typeof details.copy.circ_lib() == 'object' ? details.copy.circ_lib().shortname() : data.hash.aou[ details.copy.circ_lib() ].shortname()); 
             set_tooltip("copy_circ_lib" , typeof details.copy.circ_lib() == 'object' ? details.copy.circ_lib().name() : data.hash.aou[ details.copy.circ_lib() ].name()); 
-            set("circ_modifier", details.copy.circ_modifier()); 
+            var cm = details.copy.circ_modifier();
+            set("circ_modifier", document.getElementById('commonStrings').getFormattedString('staff.circ_modifier.display',[cm,data.hash.ccm[cm].name(),data.hash.ccm[cm].description()])); 
             set("circulate", get_localized_bool( details.copy.circulate() )); 
             set("copy_number", details.copy.copy_number()); 
             set("copy_create_date", util.date.formatted_date( details.copy.create_date(), '%{localized}' )); 

Modified: branches/serials-integration/Open-ILS/xul/staff_client/server/circ/alternate_copy_summary.xul
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/server/circ/alternate_copy_summary.xul	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/xul/staff_client/server/circ/alternate_copy_summary.xul	2010-10-18 13:46:56 UTC (rev 18371)
@@ -42,9 +42,15 @@
         <!-- Most of this gets filled in by bib_brief_overlay.xul -->
         <grid id="bib_brief_grid"> 
             <rows id="bib_brief_grid_rows">
-                <row>
-                    <label value="&staff.circ.alternate_copy_summary.Call_Number.label;" accesskey="&staff.circ.alternate_copy_summary.call_number.accesskey;" control="call_number"/>
-                    <textbox name="call_number" readonly="true" context="clipboard"/>
+                <row id="bib_brief_grid_row3">
+                    <label id="bib_call_number_label"/>
+                    <textbox id="bib_call_number"/>
+                    <hbox id="placeholder1" flex="1">
+                        <label value="&staff.circ.alternate_copy_summary.Call_Number.label;" accesskey="&staff.circ.alternate_copy_summary.Call_Number.accesskey;" control="call_number" class="emphasis"/>
+                    </hbox>
+                    <hbox id="placeholder2" flex="1">
+                        <textbox name="call_number" readonly="true" context="clipboard" class="plain"/>
+                    </hbox>
                 </row>
             </rows>
         </grid>

Modified: branches/serials-integration/Open-ILS/xul/staff_client/server/circ/checkin.js
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/server/circ/checkin.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/xul/staff_client/server/circ/checkin.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -314,6 +314,7 @@
                         ['command'],
                         function() {
                             var p = { 
+                                'printer_context' : 'receipt',
                                 'template' : 'checkin'
                             };
                             obj.list.print(p);

Modified: branches/serials-integration/Open-ILS/xul/staff_client/server/circ/checkout.js
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/server/circ/checkout.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/xul/staff_client/server/circ/checkout.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -307,6 +307,7 @@
                 'data' : {
                     'balance_owed' : util.money.sanitize( obj.most_recent_balance_owed ),
                 },
+                'printer_context' : 'receipt',
                 'template' : 'checkout',
                 'callback' : function() {
                     setTimeout(
@@ -639,7 +640,11 @@
                             return document.getElementById('circStrings').getString('staff.circ.checkout.override.item_rental_fee_required.warning');
                         },
                         '7004' : function(r) {
-                            return r.payload.status().name();
+                            try {
+                                return r.payload.status().name();
+                            } catch (E) {
+                                return "copy not available: (Unexpected error: payload not available)";  // XXX
+                            }
                         },
                         '7010' : function(r) {
                             return r.payload;

Modified: branches/serials-integration/Open-ILS/xul/staff_client/server/circ/pre_cat_fields.xul
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/server/circ/pre_cat_fields.xul	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/xul/staff_client/server/circ/pre_cat_fields.xul	2010-10-18 13:46:56 UTC (rev 18371)
@@ -56,7 +56,15 @@
             JSAN.use('util.widgets'); JSAN.use('util.functional');
             var x = util.widgets.make_menulist( 
                 [ [ $("catStrings").getString("staff.cat.copy_editor.field.unset_or_null"), "<HACK:KLUDGE:NULL>" ] ].concat( 
-                    util.functional.map_list( g.data.list.circ_modifier, function(obj) { return [ obj, obj ]; } ).sort() 
+                    util.functional.map_list(
+                        g.data.list.ccm,
+                        function(obj) {
+                            return [
+                                document.getElementById('commonStrings').getFormattedString('staff.circ_modifier.display',[obj.code(),obj.name(),obj.description()]),
+                                obj.code()
+                            ];
+                        }
+                    ).sort() 
                 ) 
             );
             x.setAttribute('id','dummy_circ_modifier');

Modified: branches/serials-integration/Open-ILS/xul/staff_client/server/circ/util.js
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/server/circ/util.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/xul/staff_client/server/circ/util.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -875,7 +875,7 @@
             'flex' : 1,
             'primary' : false,
             'hidden' : true,
-            'editable' : false, 'render' : function(my) { return my.acp.circ_modifier(); }
+            'editable' : false, 'render' : function(my) { var cm = my.acp.circ_modifier(); return document.getElementById('commonStrings').getFormattedString('staff.circ_modifier.display',[cm,data.hash.ccm[cm].name(),data.hash.ccm[cm].description()]); }
         },
         {
             'id' : 'status_changed_time',
@@ -1237,6 +1237,16 @@
         {
             'persist' : 'hidden width ordinal',
             'fm_class' : 'bre',
+            'id' : 'owner',
+            'label' : document.getElementById('circStrings').getString('staff.circ.utils.owner'),
+            'flex' : 1,
+            'primary' : false,
+            'hidden' : true,
+            'editable' : false, 'render' : function(my) { return my.bre ? (typeof my.bre.owner() == 'object' ? my.bre.owner().shortname() : data.hash.aou[my.bre.owner()].shortname() ) : ''; }
+        },
+        {
+            'persist' : 'hidden width ordinal',
+            'fm_class' : 'bre',
             'id' : 'creator',
             'label' : document.getElementById('circStrings').getString('staff.circ.utils.creator'),
             'flex' : 1,
@@ -2428,7 +2438,9 @@
             'request_date' : '',
             'request_date_msg' : '',
             'slip_date' : '',
-            'slip_date_msg' : ''
+            'slip_date_msg' : '',
+            'user' : '',
+            'user_stat_cat_entries' : ''
         };
 
         if (check.payload && check.payload.cancelled_hold_transit) {
@@ -2531,6 +2543,26 @@
                         msg += '\n';
                         var au_obj = patron.util.retrieve_fleshed_au_via_id( session, check.payload.hold.usr() );
                         print_data.user = au_obj;
+                        print_data.user_stat_cat_entries = [];
+                        var entries = au_obj.stat_cat_entries();
+                        for (var i = 0; i < entries.length; i++) {
+                            var stat_cat = data.hash.my_actsc[ entries[i].stat_cat() ];
+                            if (!stat_cat) {
+                                stat_cat = data.lookup('actsc', entries[i].stat_cat());
+                            }
+                            print_data.user_stat_cat_entries.push( { 
+                                'id' : entries[i].id(),
+                                'stat_cat' : {
+                                    'id' : stat_cat.id(),
+                                    'name' : stat_cat.name(),
+                                    'opac_visible' : stat_cat.opac_visible(),
+                                    'owner' : stat_cat.owner(),
+                                    'usr_summary' : stat_cat.usr_summary()
+                                },
+                                'stat_cat_entry' : entries[i].stat_cat_entry(),
+                                'target_usr' : entries[i].target_usr() 
+                            } );
+                        }
                         msg += '\n';
                         if (au_obj.alias()) {
                             print_data.hold_for_msg = document.getElementById('circStrings').getFormattedString('staff.circ.utils.payload.hold.patron_alias',  [au_obj.alias()]);
@@ -2692,6 +2724,87 @@
                         document.getElementById('no_change_label').setAttribute('hidden','false');
                     }
                 break;
+                case 15: // ON_RESERVATION_SHELF
+                    check.route_to = 'RESERVATION SHELF';
+                    check.what_happened = "reservation_shelf";
+                    if (check.payload.reservation) {
+                        if (check.payload.reservation.pickup_lib() != data.list.au[0].ws_ou()) {
+                            msg += document.getElementById('commonStrings').getString('common.error');
+                            msg += '\nFIXME: ';
+                            msg += document.getElementById('circStrings').getString('staff.circ.utils.route_item_error');
+                            msg += '\n';
+                        } else {
+                            msg += document.getElementById('circStrings').getFormattedString('staff.circ.utils.route_to.msg', [check.route_to]);
+                            msg += '.\n';
+                        }
+                    } else {
+                        msg += document.getElementById('commonStrings').getString('common.error');
+                        msg += '\nFIXME: ';
+                        msg += document.getElementById('circStrings').getString('staff.circ.utils.reservation_status_error');
+                        msg += '\n';
+                    }
+                    JSAN.use('util.date');
+                    if (check.payload.reservation) {
+                        JSAN.use('patron.util');
+                        msg += '\n';
+                        msg += document.getElementById('circStrings').getFormattedString('staff.circ.utils.payload.reservation.barcode', [check.payload.copy.barcode()]);
+                        msg += '\n';
+                        var payload_title  = (check.payload.record ? check.payload.record.title() : check.payload.copy.dummy_title() );
+                        msg += document.getElementById('circStrings').getFormattedString('staff.circ.utils.payload.reservation.title', [payload_title]);
+                        msg += '\n';
+                        var au_obj =
+                            typeof(check.payload.reservation.usr().card) == "function" ?
+                                check.payload.reservation.usr() :
+                                patron.util.retrieve_fleshed_au_via_id(session, check.payload.reservation.usr());
+                        msg += '\n';
+                        if (au_obj.alias()) {
+                            msg += document.getElementById('circStrings').getFormattedString('staff.circ.utils.payload.reservation.patron_alias',  [au_obj.alias()]);
+                        } else {
+                            msg += document.getElementById('circStrings').getFormattedString('staff.circ.utils.payload.reservation.patron',  [au_obj.family_name() || "", au_obj.first_given_name() || "", au_obj.second_given_name() || ""]);
+                        }
+                        msg += '\n';
+                        msg += document.getElementById('circStrings').getFormattedString('staff.circ.utils.payload.reservation.barcode', [au_obj.card().barcode()]);
+                        msg += '\n';
+                        msg += document.getElementById('circStrings').getFormattedString('staff.circ.utils.payload.reservation.request_date', [util.date.formatted_date(check.payload.reservation.request_time(),'%F %H:%M')]);
+                        msg += '\n';
+
+                        msg += document.getElementById('circStrings').getFormattedString('staff.circ.utils.payload.reservation.start_date', [util.date.formatted_date(check.payload.reservation.start_time(),'%F %H:%M')]);
+                        msg += '\n';
+                    }
+                    var rv = 0;
+                    msg += document.getElementById('circStrings').getFormattedString('staff.circ.utils.payload.reservation.slip_date', [util.date.formatted_date(new Date(),'%F')]);
+                    msg += '\n';
+                    if (!auto_print) {
+                        rv = error.yns_alert_formatted(
+                            msg,
+                            document.getElementById('circStrings').getString('staff.circ.utils.reservation_slip'),
+                            document.getElementById('circStrings').getString('staff.circ.utils.reservation_slip.print.yes'),
+                            document.getElementById('circStrings').getString('staff.circ.utils.reservation_slip.print.no'),
+                            null,
+                            document.getElementById('circStrings').getString('staff.circ.confirm.msg'),
+                            '/xul/server/skin/media/images/turtle.gif'
+                        );
+                    }
+                    if (rv == 0) {
+                        try {
+                            JSAN.use('util.print'); var print = new util.print();
+                            msg = msg.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/\n/g,'<br/>');
+                            print.simple( msg , { 'no_prompt' : true, 'content_type' : 'text/html' } );
+                        } catch(E) {
+                            var err_msg = document.getElementById('commonStrings').getString('common.error');
+                            err_msg += '\nFIXME: ' + E + '\n';
+                            dump(err_msg);
+                            alert(err_msg);
+                        }
+                    }
+                    msg = '';
+                    if (document.getElementById('no_change_label')) {
+                        var m = document.getElementById('no_change_label').getAttribute('value');
+                        m += document.getElementById('circStrings').getFormattedString('staff.circ.utils.reservation_capture', [params.barcode]);
+                        document.getElementById('no_change_label').setAttribute('value', m);
+                        document.getElementById('no_change_label').setAttribute('hidden','false');
+                    }
+                break;
                 default:
                     check.what_happened = 'error';
                     msg += document.getElementById('commonStrings').getString('common.error');

Modified: branches/serials-integration/Open-ILS/xul/staff_client/server/locale/en-US/cat.properties
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/server/locale/en-US/cat.properties	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/xul/staff_client/server/locale/en-US/cat.properties	2010-10-18 13:46:56 UTC (rev 18371)
@@ -243,6 +243,12 @@
 staff.cat.marcedit.not_authority_field.label=Not a controlled subfield
 staff.cat.marcedit.apply_selected.label=Apply Selected
 staff.cat.marcedit.no_authority_match.label=No matching authority records found
+staff.cat.marcedit.next_page.label=Next page
+staff.cat.marcedit.previous_page.label=Previous page
+staff.cat.marcedit.create_authority.label=Create New Authority from this Field
+staff.cat.marcedit.create_authority_now.label=Create Immediately
+staff.cat.marcedit.create_authority_success.label=Created new authority record
+staff.cat.marcedit.create_authority_edit.label=Create and Edit...
 staff.cat.marc_new.tab_name=MARC Template
 staff.cat.marc_new.create_record.label=Create Record
 staff.cat.marc_new.system_local.label=System Local

Modified: branches/serials-integration/Open-ILS/xul/staff_client/server/locale/en-US/circ.properties
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/server/locale/en-US/circ.properties	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/xul/staff_client/server/locale/en-US/circ.properties	2010-10-18 13:46:56 UTC (rev 18371)
@@ -276,6 +276,7 @@
 staff.circ.utils.pubdate=Publication Date
 staff.circ.utils.publisher=Publisher
 staff.circ.utils.creator=Created By
+staff.circ.utils.owner=Owned By
 staff.circ.utils.editor=Edited By
 # TCN is an acronym for Title Control Number
 staff.circ.utils.tcn=TCN
@@ -341,6 +342,7 @@
 staff.circ.utils.route_to.msg=This item needs to be routed to %1$s
 staff.circ.utils.route_item_error=We should have received a ROUTE_ITEM
 staff.circ.utils.route_item_status_error=status of Holds Shelf, but no actual hold found.
+staff.circ.utils.reservation_status_error=status of Reservation Shelf, but no actual hold found.
 staff.circ.utils.payload.hold.barcode=Barcode: %1$s
 staff.circ.utils.payload.hold.title=Title: %1$s
 staff.circ.utils.ahr_mint_condition=Copy Quality
@@ -360,6 +362,17 @@
 staff.circ.utils.hold_slip=Hold Slip
 staff.circ.utils.hold_slip.print.yes=Print
 staff.circ.utils.hold_slip.print.no=Do Not Print
+staff.circ.utils.payload.reservation.barcode=Barcode: %1$s
+staff.circ.utils.payload.reservation.title=Title: %1$s
+# Hold for patron familyName, firstName secondName
+staff.circ.utils.payload.reservation.patron=Reservation for patron %1$s, %2$s %3$s
+staff.circ.utils.payload.reservation.patron_alias=Reservation for patron %1$s
+staff.circ.utils.payload.reservation.request_date=Request Date: %1$s
+staff.circ.utils.payload.reservation.start_date=Start Date: %1$s
+staff.circ.utils.payload.reservation.slip_date=Slip Date: %1$s
+staff.circ.utils.reservation_slip=Reservation Slip
+staff.circ.utils.reservation_slip.print.yes=Print
+staff.circ.utils.reservation_slip.print.no=Do Not Print
 staff.circ.utils.transit_slip=Transit Slip
 staff.circ.utils.transit_slip.print.yes=Print
 staff.circ.utils.transit_slip.print.no=Do Not Print
@@ -367,6 +380,7 @@
 staff.circ.utils.hold_capture_delayed.titlebar=Hold Capture Delayed
 staff.circ.utils.hold_capture_delayed.prompt_for_nocapture=Do Not Capture 
 staff.circ.utils.hold_capture_delayed.prompt_for_capture=Capture
+staff.circ.utils.reservation_capture=%1$s has been captured for a reservation.
 staff.circ.utils.capture=%1$s has been captured for a hold.
 staff.circ.utils.needs_cataloging=%1$s needs to be cataloged.
 staff.circ.utils.copy_status.error=FIXME -- this case "%1$s" is unhandled.
@@ -400,6 +414,8 @@
 # 1 - Staff Username  2 - Patron Family  3 - Patron Barcode  4 - Item Barcode  5 - Route To text
 staff.circ.work_log_checkin_attempt.hold_shelf.message=%1$s attempted checkin of %4$s, which routed the item to the Holds Shelf.  Route To = %5$s
 # 1 - Staff Username  2 - Patron Family  3 - Patron Barcode  4 - Item Barcode  5 - Route To text
+staff.circ.work_log_checkin_attempt.reservation_shelf.message=%1$s attempted checkin of %4$s, which routed the item to the Reservations Shelf.  Route To = %5$s
+# 1 - Staff Username  2 - Patron Family  3 - Patron Barcode  4 - Item Barcode  5 - Route To text
 staff.circ.work_log_checkin_attempt.cataloging.message=%1$s attempted checkin of %4$s, which is a pre-cat and was routed to Cataloging.  Route To = %5$s
 # 1 - Staff Username  2 - Patron Family  3 - Patron Barcode  4 - Item Barcode  5 - Route To text
 staff.circ.work_log_checkin_attempt.cataloging.message=%1$s attempted checkin of %4$s, which was not found, and so was routed to Cataloging.  Route To = %5$s

Modified: branches/serials-integration/Open-ILS/xul/staff_client/server/locale/en-US/common.properties
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/server/locale/en-US/common.properties	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/xul/staff_client/server/locale/en-US/common.properties	2010-10-18 13:46:56 UTC (rev 18371)
@@ -34,6 +34,7 @@
 staff.acp_label_circ_as_type=Circulate As Type
 staff.acp_label_circ_lib=Circulation Library
 staff.acp_label_circ_modifier=Circulation Modifier
+staff.circ_modifier.display=%1$s : %2$s : %3$s
 staff.acp_label_copy_number=Copy Number
 staff.acp_label_deposit_amount=Deposit Amount
 staff.acp_label_fine_level=Fine Level

Copied: branches/serials-integration/Open-ILS/xul/staff_client/server/locale/en-US/marcedit-tooltips-authority.xml (from rev 17886, trunk/Open-ILS/xul/staff_client/server/locale/en-US/marcedit-tooltips-authority.xml)
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/server/locale/en-US/marcedit-tooltips-authority.xml	                        (rev 0)
+++ branches/serials-integration/Open-ILS/xul/staff_client/server/locale/en-US/marcedit-tooltips-authority.xml	2010-10-18 13:46:56 UTC (rev 18371)
@@ -0,0 +1,5433 @@
+<?xml version="1.0"?>
+<fields>
+  <field tag="001" repeatable="false">
+    <name>Control Number</name>
+    <description>Control number assigned by the organization creating, using, or distributing the record.</description>
+  </field>
+  <field tag="003" repeatable="false">
+    <name>Control Number Identifier</name>
+    <description>MARC code for the agency whose system control number is contained in field 001 (Control Number).</description>
+  </field>
+  <field tag="005" repeatable="false">
+    <name>Date and Time of Latest Transaction</name>
+    <description>Sixteen characters that specify the date and time of the latest record transaction and serve as a version identifier for the record. The data and time are recorded according to (ISO 8601) in the pattern and .</description>
+  </field>
+  <field tag="008" repeatable="false">
+    <name>Fixed-Length Data Elements</name>
+    <description>Forty character positions (00-39) that contain positionally-defined data elements that provide coded information about the record as a whole or about special aspects of the 1XX heading or 4XX/5XX tracing fields. Undefined character positions contain a blank (#). All defined character positions must contain a defined code; for some 008 positions, this may be the fill character (|). The fill character may be used (in certain character positions) when a cataloging organization makes no attempt to code the character position. Field 008 is not repeatable.</description>
+  </field>
+  <field tag="010" repeatable="false">
+    <name>Library of Congress Control Number</name>
+    <description>Unique number assigned to a record by the Library of Congress (LC) or a cooperative cataloging partner contributing authority records to the Name Authority Cooperative Program (NACO) database. The field is also assigned to records created by LC for the Library of Congress Subject Headings (LCSH).</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>LC control number</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Canceled/invalid LC control number</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="014" repeatable="true">
+    <name>Link to Bibliographic Record for Serial or Multipart Item</name>
+    <description>Control number from field 001 of a MARC 21 bibliographic record for a serial or a multipart item that is cataloged as a set.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Control number of related bibliographic record</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="016" repeatable="true">
+    <name>National Bibliographic Agency Control Number</name>
+    <description>Unique numbers that have been assigned to a record by a national bibliographic agency other than the Library of Congress (Library of Congress control numbers are recorded in ).</description>
+    <indicator position="1" value="#">
+      <description>Library and Archives Canada</description>
+    </indicator>
+    <indicator position="1" value="7">
+      <description>Source specified in subfield $2</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Record control number</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Canceled or invalid record control number</description>
+    </subfield>
+    <subfield code="2" repeatable="false">
+      <description>Source</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="020" repeatable="true">
+    <name>International Standard Book Number</name>
+    <description>International Standard Book Number (ISBN), terms of availability, and any canceled/invalid ISBN copied from field 020 of a MARC bibliographic record for a multipart item that is cataloged as a set.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>International Standard Book Number</description>
+    </subfield>
+    <subfield code="c" repeatable="false">
+      <description>Terms of availability</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Canceled/invalid ISBN</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="022" repeatable="true">
+    <name>International Standard Serial Number</name>
+    <description>International Standard Serial Number (ISSN) and/or any incorrect and canceled ISSNs copied from field 022 of a MARC 21 bibliographic record for a continuing resource.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>International Standard Serial Number</description>
+    </subfield>
+    <subfield code="l" repeatable="false">
+      <description>ISSN-L</description>
+    </subfield>
+    <subfield code="m" repeatable="true">
+      <description>Canceled ISSN-L</description>
+    </subfield>
+    <subfield code="y" repeatable="true">
+      <description>Incorrect ISSN</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Canceled ISSN</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="024" repeatable="true">
+    <name>Other Standard Identifier</name>
+    <description>Standard number or code associated with the entity named in the 1XX field which cannot be accommodated in another field (e.g., fields 020 (International Standard Book Number) and 022 (International Standard Serial Number)). The source of the standard number or code is identified in subfield $2 (Source of number or code).</description>
+    <indicator position="1" value="7">
+      <description>Source specified in subfield $2</description>
+    </indicator>
+    <indicator position="1" value="8">
+      <description>Unspecified type of standard number or code</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Standard number or code</description>
+    </subfield>
+    <subfield code="c" repeatable="false">
+      <description>Terms of availability</description>
+    </subfield>
+    <subfield code="d" repeatable="false">
+      <description>Additional codes following the standard number or code</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Canceled/invalid standard number or code</description>
+    </subfield>
+    <subfield code="2" repeatable="false">
+      <description>Source of number or code</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="031" repeatable="true">
+    <name>Musical Incipits Information</name>
+    <description>Coded data representing the musical incipit for music using established notation schemes that employ ordinary ASCII symbols. Used in an established heading record primarily to identify music manuscripts, but can be applied to any material containing music.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="b" repeatable="false">
+      <description>Number of movement</description>
+    </subfield>
+    <subfield code="c" repeatable="false">
+      <description>Number of excerpt</description>
+    </subfield>
+    <subfield code="d" repeatable="true">
+      <description>Caption or heading</description>
+    </subfield>
+    <subfield code="e" repeatable="false">
+      <description>Role</description>
+    </subfield>
+    <subfield code="g" repeatable="false">
+      <description>Clef</description>
+    </subfield>
+    <subfield code="m" repeatable="false">
+      <description>Voice/instrument</description>
+    </subfield>
+    <subfield code="n" repeatable="false">
+      <description>Key signature</description>
+    </subfield>
+    <subfield code="o" repeatable="false">
+      <description>Time signature</description>
+    </subfield>
+    <subfield code="p" repeatable="false">
+      <description>Musical notation</description>
+    </subfield>
+    <subfield code="q" repeatable="true">
+      <description>General note</description>
+    </subfield>
+    <subfield code="r" repeatable="false">
+      <description>Key or mode</description>
+    </subfield>
+    <subfield code="s" repeatable="true">
+      <description>Coded validity note</description>
+    </subfield>
+    <subfield code="t" repeatable="true">
+      <description>Text incipit</description>
+    </subfield>
+    <subfield code="u" repeatable="true">
+      <description>Uniform Resource Identifier</description>
+    </subfield>
+    <subfield code="y" repeatable="true">
+      <description>Link text</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Public note</description>
+    </subfield>
+    <subfield code="2" repeatable="false">
+      <description>System code</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="034" repeatable="true">
+    <name>Coded Cartographic Mathematical Data</name>
+    <description>Coded form of the cartographic mathematical data relevant to the entity described in the authority record. The data that is recorded usually derives from authoritative sources.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Not applicable</description>
+    </indicator>
+    <indicator position="2" value="0">
+      <description>Outer ring</description>
+    </indicator>
+    <indicator position="2" value="1">
+      <description>Exclusion ring</description>
+    </indicator>
+    <subfield code="d" repeatable="true">
+      <description>Coordinates</description>
+    </subfield>
+    <subfield code="e" repeatable="true">
+      <description>Coordinates</description>
+    </subfield>
+    <subfield code="f" repeatable="true">
+      <description>Coordinates</description>
+    </subfield>
+    <subfield code="g" repeatable="true">
+      <description>Coordinates</description>
+    </subfield>
+    <subfield code="j" repeatable="true">
+      <description>Declination</description>
+    </subfield>
+    <subfield code="k" repeatable="true">
+      <description>Declination</description>
+    </subfield>
+    <subfield code="m" repeatable="true">
+      <description>Right ascension</description>
+    </subfield>
+    <subfield code="n" repeatable="true">
+      <description>Right ascension</description>
+    </subfield>
+    <subfield code="p" repeatable="false">
+      <description>Equinox</description>
+    </subfield>
+    <subfield code="r" repeatable="false">
+      <description>Distance from earth</description>
+    </subfield>
+    <subfield code="s" repeatable="true">
+      <description>G-ring latitude</description>
+    </subfield>
+    <subfield code="t" repeatable="true">
+      <description>G-ring longitude</description>
+    </subfield>
+    <subfield code="x" repeatable="false">
+      <description>Beginning date</description>
+    </subfield>
+    <subfield code="y" repeatable="false">
+      <description>Ending date</description>
+    </subfield>
+    <subfield code="z" repeatable="false">
+      <description>Name of extraterrestrial body</description>
+    </subfield>
+    <subfield code="2" repeatable="false">
+      <description>Source</description>
+    </subfield>
+    <subfield code="3" repeatable="false">
+      <description>Materials specified</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="035" repeatable="true">
+    <name>System Control Number</name>
+    <description>Control number for the record in a system other than the one whose control number is contained in (Control Number), (Library of Congress Control Number), or (National Bibliographic Agency Control Number).</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>System control number</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Canceled/invalid system control number</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="040" repeatable="false">
+    <name>Cataloging Source</name>
+    <description>MARC code or the name of the organization(s) that created the original authority record, assigned MARC content designation and transcribed the record into machine-readable form, or modified an existing MARC record. These MARC codes and the code in 008/39 (Cataloging source) specify the parties responsible for content, content designation, and transcription of an the authority record. See: .</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Original cataloging agency</description>
+    </subfield>
+    <subfield code="b" repeatable="false">
+      <description>Language of cataloging</description>
+    </subfield>
+    <subfield code="c" repeatable="false">
+      <description>Transcribing agency</description>
+    </subfield>
+    <subfield code="d" repeatable="true">
+      <description>Modifying agency</description>
+    </subfield>
+    <subfield code="e" repeatable="true">
+      <description>Description conventions</description>
+    </subfield>
+    <subfield code="f" repeatable="false">
+      <description>Subject heading/thesaurus conventions</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="042" repeatable="false">
+    <name>Authentication Code</name>
+    <description>One or more authentication codes indicating that the record, existing in a national database, has been reviewed in a specific way. The codes are associated with specifically designated authentication agencies.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="true">
+      <description>Authentication code</description>
+    </subfield>
+  </field>
+  <field tag="043" repeatable="false">
+    <name>Geographic Area Code</name>
+    <description>Geographic area codes (GAC) associated with the 1XX heading in an established heading record or a subdivision record. Source of the code in subfield $a is . The source of a local code in subfield $b is indicated in subfield $2. The source of codes in subfield $c is , .</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="true">
+      <description>Geographic area code</description>
+    </subfield>
+    <subfield code="b" repeatable="true">
+      <description>Local GAC code</description>
+    </subfield>
+    <subfield code="c" repeatable="true">
+      <description>ISO code</description>
+    </subfield>
+    <subfield code="2" repeatable="true">
+      <description>Source of local code</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="045" repeatable="false">
+    <name>Time Period of Heading</name>
+    <description>Time period code (subfield $a) and/or a formatted time period (subfield $b or $c) associated with a 15X heading in an established heading record or a 18X heading in a subdivision record.</description>
+    <indicator position="1" value="#">
+      <description>Subfield $b or $c not present</description>
+    </indicator>
+    <indicator position="1" value="0">
+      <description>Single date/time</description>
+    </indicator>
+    <indicator position="1" value="1">
+      <description>Multiple single dates/times</description>
+    </indicator>
+    <indicator position="1" value="2">
+      <description>Range of dates/times</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="true">
+      <description>Time period code</description>
+    </subfield>
+    <subfield code="b" repeatable="true">
+      <description>Formatted 9999 B.C. through C.E. time period</description>
+    </subfield>
+    <subfield code="c" repeatable="true">
+      <description>Formatted pre-9999 B.C. time period</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="046" repeatable="true">
+    <name>Special Coded Dates</name>
+    <description>Dates that are associated with the entity described in the record. These include:</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="f" repeatable="false">
+      <description>Birth date</description>
+    </subfield>
+    <subfield code="g" repeatable="false">
+      <description>Death date</description>
+    </subfield>
+    <subfield code="k" repeatable="false">
+      <description>Beginning or single date created</description>
+    </subfield>
+    <subfield code="l" repeatable="false">
+      <description>Ending date created</description>
+    </subfield>
+    <subfield code="s" repeatable="false">
+      <description>Start period</description>
+    </subfield>
+    <subfield code="t" repeatable="false">
+      <description>End period</description>
+    </subfield>
+    <subfield code="u" repeatable="true">
+      <description>Uniform Resource Identifier</description>
+    </subfield>
+    <subfield code="v" repeatable="true">
+      <description>Source of information</description>
+    </subfield>
+    <subfield code="2" repeatable="false">
+      <description>Source of date scheme</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="050" repeatable="true">
+    <name>Library of Congress Call Number</name>
+    <description>Call/and or class number for a series when all or part of the series is classified as a collected set or with the main series (646, Series Classification Practice, subfield $a, code c or m). The classification number is taken from the and/or the that are maintained by the Library of Congress.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="0">
+      <description>Assigned by LC</description>
+    </indicator>
+    <indicator position="2" value="4">
+      <description>Assigned by agency other than LC</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Classification number</description>
+    </subfield>
+    <subfield code="b" repeatable="false">
+      <description>Item number</description>
+    </subfield>
+    <subfield code="d" repeatable="false">
+      <description>Volumes/dates to which call number applies</description>
+    </subfield>
+    <subfield code="5" repeatable="true">
+      <description>Institution to which field applies</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="052" repeatable="true">
+    <name>Geographic Classification</name>
+    <description>Classification code for a geographic area associated with the 151 field in an established heading record or 181 field in a subdivision record for a geographic name.</description>
+    <indicator position="1" value="#">
+      <description>Library of Congress Classification</description>
+    </indicator>
+    <indicator position="1" value="1">
+      <description>U.S. Dept. of Defense Classification</description>
+    </indicator>
+    <indicator position="1" value="7">
+      <description>Source specified in subfield $2</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Geographic classification area code</description>
+    </subfield>
+    <subfield code="b" repeatable="true">
+      <description>Geographic classification subarea code</description>
+    </subfield>
+    <subfield code="d" repeatable="true">
+      <description>Populated place name</description>
+    </subfield>
+    <subfield code="2" repeatable="false">
+      <description>Code source</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="053" repeatable="true">
+    <name>LC Classification Number</name>
+    <description>Single LC classification number or a number span associated with a 1XX heading in an established heading record or a subdivision record. Source of the classification number is and/or the that are maintained by the Library of Congress. The hyphen (-) between the two class numbers in a range of numbers may be generated based on the presence of both subfields $a and $b.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="0">
+      <description>Assigned by LC</description>
+    </indicator>
+    <indicator position="2" value="4">
+      <description>Assigned by agency other than LC</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Classification number element-single number or beginning number of span</description>
+    </subfield>
+    <subfield code="b" repeatable="false">
+      <description>Classification number element-ending number of span</description>
+    </subfield>
+    <subfield code="c" repeatable="false">
+      <description>Explanatory term</description>
+    </subfield>
+    <subfield code="5" repeatable="true">
+      <description>Institution to which field applies</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="055" repeatable="true">
+    <name>Library and Archives Canada Call Number</name>
+    <description>Call number for a series assigned in Canada if the institution has classified all of part of the series as a collected set.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="0">
+      <description>Assigned by LAC</description>
+    </indicator>
+    <indicator position="2" value="4">
+      <description>Assigned by agency other than LAC</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Classification number</description>
+    </subfield>
+    <subfield code="b" repeatable="false">
+      <description>Item number</description>
+    </subfield>
+    <subfield code="d" repeatable="false">
+      <description>Volumes/dates to which call number applies</description>
+    </subfield>
+    <subfield code="5" repeatable="true">
+      <description>Institution to which field applies</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="060" repeatable="true">
+    <name>National Library of Medicine Call Number</name>
+    <description>National Library of Medicine (NLM) call number for a series when all or part of the series is classified as a collected set or with the main series (646, Series Classification Practice, subfield $a, code c or m).</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="0">
+      <description>Assigned by NLM</description>
+    </indicator>
+    <indicator position="2" value="4">
+      <description>Assigned by agency other than NLM</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Classification number</description>
+    </subfield>
+    <subfield code="b" repeatable="false">
+      <description>Item number</description>
+    </subfield>
+    <subfield code="d" repeatable="false">
+      <description>Volumes/dates to which call number applies</description>
+    </subfield>
+    <subfield code="5" repeatable="true">
+      <description>Institution to which field applies</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="065" repeatable="true">
+    <name>Other Classification Number</name>
+    <description>Single classification number, number stem, or a number span associated with a 1XX heading in an established heading record or subdivision record. It is used for all classification schemes except those already accommodated in other fields of this type in the format: 053 (LC Classification Number), 083 (Dewey Decimal Classification number), and 087 (Government Document Classification Number). The classification number(s) may be qualified by explanatory information when the heading is represented in more than one place in the same classification scheme. Each classification number or number span associated with a heading is contained in separate field 065.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Classification number element-single number or beginning of span</description>
+    </subfield>
+    <subfield code="b" repeatable="false">
+      <description>Classification number element-ending number of span</description>
+    </subfield>
+    <subfield code="c" repeatable="false">
+      <description>Explanatory term</description>
+    </subfield>
+    <subfield code="2" repeatable="false">
+      <description>Number source</description>
+    </subfield>
+    <subfield code="5" repeatable="true">
+      <description>Institution to which field applies</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="066" repeatable="false">
+    <name>Character Sets Present</name>
+    <description>Used in records encoded with characters from sets other than ISO 10646 (or ) to specify the character sets for data content that are present in the record. The field alerts users that special processing may be required. A detailed description of the standard escape sequences used in MARC records is provided in</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Primary G0 character set</description>
+    </subfield>
+    <subfield code="b" repeatable="false">
+      <description>Primary G1 character set</description>
+    </subfield>
+    <subfield code="c" repeatable="true">
+      <description>Alternate G0 or G1 character set</description>
+    </subfield>
+  </field>
+  <field tag="070" repeatable="true">
+    <name>National Agricultural Library Call Number</name>
+    <description>Call number assigned by the National Agricultural Library (NAL) to a series when all or part of the series is classified as a collected set or with the main series (646, Series Classification Practice, subfield $a, code c or m).</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Classification number</description>
+    </subfield>
+    <subfield code="b" repeatable="false">
+      <description>Item number</description>
+    </subfield>
+    <subfield code="d" repeatable="false">
+      <description>Volumes/dates to which call number applies</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="072" repeatable="true">
+    <name>Subject Category Code</name>
+    <description>Code for the subject category that is associated with the 1XX field in an established heading record or a node label record.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>No information provided</description>
+    </indicator>
+    <indicator position="2" value="0">
+      <description>NAL subject category code list</description>
+    </indicator>
+    <indicator position="2" value="7">
+      <description>Source specified in subfield $2</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Subject category code</description>
+    </subfield>
+    <subfield code="x" repeatable="true">
+      <description>Subject category code subdivision</description>
+    </subfield>
+    <subfield code="2" repeatable="false">
+      <description>Code source</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="073" repeatable="false">
+    <name>Subdivision Usage</name>
+    <description>Code specifying the topical term or geographic name with which the 1XX heading in a subdivision record may be used in a particular thesaurus.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="true">
+      <description>Subdivision usage</description>
+    </subfield>
+    <subfield code="z" repeatable="false">
+      <description>Code source</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="080" repeatable="true">
+    <name>Universal Decimal Classification Number</name>
+    <description>Classification number associated with a 1XX heading in an established heading record. Number is taken from the Universal Decimal Classification scheme.</description>
+    <indicator position="1" value="#">
+      <description>No information provided</description>
+    </indicator>
+    <indicator position="1" value="0">
+      <description>Full</description>
+    </indicator>
+    <indicator position="1" value="1">
+      <description>Abridged</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Universal Decimal Classification number</description>
+    </subfield>
+    <subfield code="b" repeatable="false">
+      <description>Item number</description>
+    </subfield>
+    <subfield code="x" repeatable="true">
+      <description>Common auxiliary subdivision</description>
+    </subfield>
+    <subfield code="2" repeatable="false">
+      <description>Edition identifier</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="082" repeatable="true">
+    <name>Dewey Decimal Call Number</name>
+    <description>Call number for a series when all or part of the series is classified as a collected set or with the main series (646, Series Classification Practice, subfield $a, code c or m). Source of the classification number is the the the and electronic updates to either edition. Through 1997, updates were issued in the</description>
+    <indicator position="1" value="0">
+      <description>Full</description>
+    </indicator>
+    <indicator position="1" value="1">
+      <description>Abridged</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>No information provided</description>
+    </indicator>
+    <indicator position="2" value="0">
+      <description>Assigned by LC</description>
+    </indicator>
+    <indicator position="2" value="4">
+      <description>Assigned by agency other than LC</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Classification number</description>
+    </subfield>
+    <subfield code="b" repeatable="false">
+      <description>Item number</description>
+    </subfield>
+    <subfield code="d" repeatable="false">
+      <description>Volumes/dates to which call number applies</description>
+    </subfield>
+    <subfield code="2" repeatable="false">
+      <description>Edition number</description>
+    </subfield>
+    <subfield code="5" repeatable="true">
+      <description>Institution to which field applies</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="083" repeatable="true">
+    <name>Dewey Decimal Classification Number</name>
+    <description>Single Dewey classification number or a a number span associated with a 1XX heading in an established heading record or a subdivision record. Source of the classification number is the the and electronic updates to either edition. Through 1997, updates were issued in the .</description>
+    <indicator position="1" value="0">
+      <description>Full</description>
+    </indicator>
+    <indicator position="1" value="1">
+      <description>Abridged</description>
+    </indicator>
+    <indicator position="2" value="0">
+      <description>Assigned by LC</description>
+    </indicator>
+    <indicator position="2" value="4">
+      <description>Assigned by agency other than LC</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Classification number element-single number or beginning number of span</description>
+    </subfield>
+    <subfield code="b" repeatable="false">
+      <description>Classification number element-ending number of span</description>
+    </subfield>
+    <subfield code="c" repeatable="false">
+      <description>Explanatory term</description>
+    </subfield>
+    <subfield code="y" repeatable="true">
+      <description>Table sequence number for internal subarrangement or add table</description>
+    </subfield>
+    <subfield code="z" repeatable="false">
+      <description>Table identification-table number</description>
+    </subfield>
+    <subfield code="2" repeatable="false">
+      <description>Edition number</description>
+    </subfield>
+    <subfield code="5" repeatable="true">
+      <description>Institution to which field applies</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="086" repeatable="true">
+    <name>Government Document Call Number</name>
+    <description>Government document call number for a series when all or part of the series is classified as a collected set or with a main series (646, Series Classification Practice, subfield $a, code c or m). The organization assigning the number may be identified in subfield $5.</description>
+    <indicator position="1" value="#">
+      <description>Source specified in subfield $2</description>
+    </indicator>
+    <indicator position="1" value="0">
+      <description>Superintendent of Documents Classification System</description>
+    </indicator>
+    <indicator position="1" value="1">
+      <description>Government of Canada Publications: Outline of Classification</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Call number</description>
+    </subfield>
+    <subfield code="d" repeatable="false">
+      <description>Volumes/dates to which call number applies</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Canceled/invalid call number</description>
+    </subfield>
+    <subfield code="2" repeatable="false">
+      <description>Number source</description>
+    </subfield>
+    <subfield code="5" repeatable="true">
+      <description>Institution to which field applies</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="087" repeatable="true">
+    <name>Government Document Classification Number</name>
+    <description>Single government document classification number, number stem, or a number span associated with a 1XX heading in an established heading record. The classification number(s) may be qualified by explanatory information when the heading is represented by more than one number in the same classification scheme.</description>
+    <indicator position="1" value="#">
+      <description>Source specified in subfield $2</description>
+    </indicator>
+    <indicator position="1" value="0">
+      <description>Superintendent of Documents Classification System</description>
+    </indicator>
+    <indicator position="1" value="1">
+      <description>Government of Canada Publications: Outline of Classification</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Classification number element-Single number of beginning number of span</description>
+    </subfield>
+    <subfield code="b" repeatable="false">
+      <description>Classification number element-Ending number of span</description>
+    </subfield>
+    <subfield code="c" repeatable="false">
+      <description>Explanatory information</description>
+    </subfield>
+    <subfield code="2" repeatable="false">
+      <description>Number source</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="09X" repeatable="true">
+    <name>Local Call Numbers</name>
+    <description>090-099 fields are reserved for a locally-assigned call number for a series when all or part of the series is classified as a collected set or with the main series (646, Series Classification Practice, subfield $a, code c or m).</description>
+  </field>
+  <field tag="100" repeatable="false">
+    <name>Heading-Personal Name</name>
+    <description>Established personal name used in a name, name/title, or extended subject heading established heading records or an unestablished personal name used in these types of headings a traced or an untraced reference record.</description>
+    <indicator position="1" value="0">
+      <description>Forename</description>
+    </indicator>
+    <indicator position="1" value="1">
+      <description>Surname</description>
+    </indicator>
+    <indicator position="1" value="3">
+      <description>Family name</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Personal name</description>
+    </subfield>
+    <subfield code="b" repeatable="false">
+      <description>Numeration</description>
+    </subfield>
+    <subfield code="c" repeatable="true">
+      <description>Titles and other words associated with a name</description>
+    </subfield>
+    <subfield code="d" repeatable="false">
+      <description>Dates associated with a name</description>
+    </subfield>
+    <subfield code="e" repeatable="true">
+      <description>Relator term</description>
+    </subfield>
+    <subfield code="f" repeatable="false">
+      <description>Date of a work</description>
+    </subfield>
+    <subfield code="g" repeatable="false">
+      <description>Miscellaneous information</description>
+    </subfield>
+    <subfield code="h" repeatable="false">
+      <description>Medium</description>
+    </subfield>
+    <subfield code="j" repeatable="true">
+      <description>Attribution qualifier</description>
+    </subfield>
+    <subfield code="k" repeatable="true">
+      <description>Form subheading</description>
+    </subfield>
+    <subfield code="l" repeatable="false">
+      <description>Language of a work</description>
+    </subfield>
+    <subfield code="m" repeatable="true">
+      <description>Medium of performance for music</description>
+    </subfield>
+    <subfield code="n" repeatable="true">
+      <description>Number of part/section of a work</description>
+    </subfield>
+    <subfield code="o" repeatable="false">
+      <description>Arranged statement for music</description>
+    </subfield>
+    <subfield code="p" repeatable="true">
+      <description>Name of part/section of a work</description>
+    </subfield>
+    <subfield code="q" repeatable="false">
+      <description>Fuller form of name</description>
+    </subfield>
+    <subfield code="r" repeatable="false">
+      <description>Key for music</description>
+    </subfield>
+    <subfield code="s" repeatable="false">
+      <description>Version</description>
+    </subfield>
+    <subfield code="t" repeatable="false">
+      <description>Title of a work</description>
+    </subfield>
+    <subfield code="v" repeatable="true">
+      <description>Form subdivision</description>
+    </subfield>
+    <subfield code="x" repeatable="true">
+      <description>General subdivision</description>
+    </subfield>
+    <subfield code="y" repeatable="true">
+      <description>Chronological subdivision</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Geographic subdivision</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="110" repeatable="false">
+    <name>Heading-Corporate Name</name>
+    <description>Corporate name used in a name, name/title, or extended subject heading in established heading records or an unestablished corporate name used in a traced or an untraced reference record.</description>
+    <indicator position="1" value="0">
+      <description>Inverted name</description>
+    </indicator>
+    <indicator position="1" value="1">
+      <description>Jurisdiction name</description>
+    </indicator>
+    <indicator position="1" value="2">
+      <description>Name in direct order</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Corporate name or jurisdiction name as entry element</description>
+    </subfield>
+    <subfield code="b" repeatable="true">
+      <description>Subordinate unit</description>
+    </subfield>
+    <subfield code="c" repeatable="false">
+      <description>Location of meeting</description>
+    </subfield>
+    <subfield code="d" repeatable="true">
+      <description>Date of meeting or treaty signing</description>
+    </subfield>
+    <subfield code="e" repeatable="true">
+      <description>Relator term</description>
+    </subfield>
+    <subfield code="f" repeatable="false">
+      <description>Date of a work</description>
+    </subfield>
+    <subfield code="g" repeatable="false">
+      <description>Miscellaneous information</description>
+    </subfield>
+    <subfield code="h" repeatable="false">
+      <description>Medium</description>
+    </subfield>
+    <subfield code="k" repeatable="true">
+      <description>Form subheading</description>
+    </subfield>
+    <subfield code="l" repeatable="false">
+      <description>Language of a work</description>
+    </subfield>
+    <subfield code="m" repeatable="true">
+      <description>Medium of performance for music</description>
+    </subfield>
+    <subfield code="n" repeatable="true">
+      <description>Number of part/section/meeting</description>
+    </subfield>
+    <subfield code="o" repeatable="false">
+      <description>Arranged statement for music</description>
+    </subfield>
+    <subfield code="p" repeatable="true">
+      <description>Name of part/section of a work</description>
+    </subfield>
+    <subfield code="r" repeatable="false">
+      <description>Key for music</description>
+    </subfield>
+    <subfield code="s" repeatable="false">
+      <description>Version</description>
+    </subfield>
+    <subfield code="t" repeatable="false">
+      <description>Title of a work</description>
+    </subfield>
+    <subfield code="v" repeatable="true">
+      <description>Form subdivision</description>
+    </subfield>
+    <subfield code="x" repeatable="true">
+      <description>General subdivision</description>
+    </subfield>
+    <subfield code="y" repeatable="true">
+      <description>Chronological subdivision</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Geographic subdivision</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="111" repeatable="false">
+    <name>Heading-Meeting Name</name>
+    <description>Established meeting name used in a name or name/title heading in established heading records or an unestablished meeting name used in these types of headings in traced or untraced reference records.</description>
+    <indicator position="1" value="0">
+      <description>Inverted name</description>
+    </indicator>
+    <indicator position="1" value="1">
+      <description>Jurisdiction name</description>
+    </indicator>
+    <indicator position="1" value="2">
+      <description>Name in direct order</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Meeting name or jurisdiction name as entry element</description>
+    </subfield>
+    <subfield code="c" repeatable="false">
+      <description>Location of meeting</description>
+    </subfield>
+    <subfield code="d" repeatable="false">
+      <description>Date of meeting</description>
+    </subfield>
+    <subfield code="e" repeatable="true">
+      <description>Subordinate unit</description>
+    </subfield>
+    <subfield code="f" repeatable="false">
+      <description>Date of a work</description>
+    </subfield>
+    <subfield code="g" repeatable="false">
+      <description>Miscellaneous information</description>
+    </subfield>
+    <subfield code="h" repeatable="false">
+      <description>Medium</description>
+    </subfield>
+    <subfield code="j" repeatable="true">
+      <description>Relator term</description>
+    </subfield>
+    <subfield code="k" repeatable="true">
+      <description>Form subheading</description>
+    </subfield>
+    <subfield code="l" repeatable="false">
+      <description>Language of a work</description>
+    </subfield>
+    <subfield code="n" repeatable="true">
+      <description>Number of part/section/meeting</description>
+    </subfield>
+    <subfield code="p" repeatable="true">
+      <description>Name of part/section of a work</description>
+    </subfield>
+    <subfield code="q" repeatable="false">
+      <description>Name of meeting following jurisdiction name entry element</description>
+    </subfield>
+    <subfield code="s" repeatable="false">
+      <description>Version</description>
+    </subfield>
+    <subfield code="t" repeatable="false">
+      <description>Title of a work</description>
+    </subfield>
+    <subfield code="v" repeatable="true">
+      <description>Form subdivision</description>
+    </subfield>
+    <subfield code="x" repeatable="true">
+      <description>General subdivision</description>
+    </subfield>
+    <subfield code="y" repeatable="true">
+      <description>Chronological subdivision</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Geographic subdivision</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="130" repeatable="false">
+    <name>Heading-Uniform Title</name>
+    <description>Uniform title used in a title or extended subject heading in established heading records or an unestablished uniform title used in a traced or untraced reference record.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="0">
+      <description>No nonfiling characters</description>
+    </indicator>
+    <indicator position="2" value="1">
+      <description>Number of nonfiling characters - 1</description>
+    </indicator>
+    <indicator position="2" value="2">
+      <description>Number of nonfiling characters - 2</description>
+    </indicator>
+    <indicator position="2" value="3">
+      <description>Number of nonfiling characters - 3</description>
+    </indicator>
+    <indicator position="2" value="4">
+      <description>Number of nonfiling characters - 4</description>
+    </indicator>
+    <indicator position="2" value="5">
+      <description>Number of nonfiling characters - 5</description>
+    </indicator>
+    <indicator position="2" value="6">
+      <description>Number of nonfiling characters - 6</description>
+    </indicator>
+    <indicator position="2" value="7">
+      <description>Number of nonfiling characters - 7</description>
+    </indicator>
+    <indicator position="2" value="8">
+      <description>Number of nonfiling characters - 8</description>
+    </indicator>
+    <indicator position="2" value="9">
+      <description>Number of nonfiling characters - 9</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Uniform title</description>
+    </subfield>
+    <subfield code="d" repeatable="true">
+      <description>Date of treaty signing</description>
+    </subfield>
+    <subfield code="f" repeatable="false">
+      <description>Date of a work</description>
+    </subfield>
+    <subfield code="g" repeatable="false">
+      <description>Miscellaneous information</description>
+    </subfield>
+    <subfield code="h" repeatable="false">
+      <description>Medium</description>
+    </subfield>
+    <subfield code="k" repeatable="true">
+      <description>Form subheading</description>
+    </subfield>
+    <subfield code="l" repeatable="false">
+      <description>Language of a work</description>
+    </subfield>
+    <subfield code="m" repeatable="true">
+      <description>Medium of performance for music</description>
+    </subfield>
+    <subfield code="n" repeatable="true">
+      <description>Number of part/section of a work</description>
+    </subfield>
+    <subfield code="o" repeatable="false">
+      <description>Arranged statement for music</description>
+    </subfield>
+    <subfield code="p" repeatable="true">
+      <description>Name of part/section of a work</description>
+    </subfield>
+    <subfield code="r" repeatable="false">
+      <description>Key for music</description>
+    </subfield>
+    <subfield code="s" repeatable="false">
+      <description>Version</description>
+    </subfield>
+    <subfield code="t" repeatable="false">
+      <description>Title of a work</description>
+    </subfield>
+    <subfield code="v" repeatable="true">
+      <description>Form subdivision</description>
+    </subfield>
+    <subfield code="x" repeatable="true">
+      <description>General subdivision</description>
+    </subfield>
+    <subfield code="y" repeatable="true">
+      <description>Chronological subdivision</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Geographic subdivision</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="148" repeatable="false">
+    <name>Heading-Chronological Term</name>
+    <description>Chronological term used as a heading in an established heading record, an established heading and subdivision record, a traced or untraced reference record, or a reference and subdivision record.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Chronological term</description>
+    </subfield>
+    <subfield code="v" repeatable="true">
+      <description>Form subdivision</description>
+    </subfield>
+    <subfield code="x" repeatable="true">
+      <description>General subdivision</description>
+    </subfield>
+    <subfield code="y" repeatable="true">
+      <description>Chronological subdivision</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Geographic subdivision</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="150" repeatable="false">
+    <name>Heading-Topical Term</name>
+    <description>Topical term used as a heading in an established heading record, an established heading and subdivision record, a traced or an untraced reference record, a reference and subdivision record, or a node label record.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Topical term or geographic name entry element</description>
+    </subfield>
+    <subfield code="b" repeatable="false">
+      <description>Topical term following geographic name entry element</description>
+    </subfield>
+    <subfield code="v" repeatable="true">
+      <description>Form subdivision</description>
+    </subfield>
+    <subfield code="x" repeatable="true">
+      <description>General subdivision</description>
+    </subfield>
+    <subfield code="y" repeatable="true">
+      <description>Chronological subdivision</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Geographic subdivision</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="151" repeatable="false">
+    <name>Heading-Geographic Name</name>
+    <description>Geographic name used as a heading in an established heading record, an established heading and subdivision record, a traced or an untraced reference record, or a reference and subdivision record.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Geographic name</description>
+    </subfield>
+    <subfield code="v" repeatable="true">
+      <description>Form subdivision</description>
+    </subfield>
+    <subfield code="x" repeatable="true">
+      <description>General subdivision</description>
+    </subfield>
+    <subfield code="y" repeatable="true">
+      <description>Chronological subdivision</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Geographic subdivision</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="155" repeatable="false">
+    <name>Heading-Genre/Form Term</name>
+    <description>Genre or form term used as a heading in an established heading record, an established heading and subdivision record, a traced or an untraced reference record, or a reference and subdivision record. The term may consist of more than one word.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Genre/form term</description>
+    </subfield>
+    <subfield code="v" repeatable="true">
+      <description>Form subdivision</description>
+    </subfield>
+    <subfield code="x" repeatable="true">
+      <description>General subdivision</description>
+    </subfield>
+    <subfield code="y" repeatable="true">
+      <description>Chronological subdivision</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Geographic subdivision</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="180" repeatable="false">
+    <name>Heading-General Subdivision</name>
+    <description>Topical, form, or language term used as a heading in a subdivision record.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="v" repeatable="true">
+      <description>Form subdivision</description>
+    </subfield>
+    <subfield code="x" repeatable="true">
+      <description>General subdivision</description>
+    </subfield>
+    <subfield code="y" repeatable="true">
+      <description>Chronological subdivision</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Geographic subdivision</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="181" repeatable="false">
+    <name>Heading-Geographic Subdivision</name>
+    <description>Geographic name or term used as a heading in a subdivision record.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="v" repeatable="true">
+      <description>Form subdivision</description>
+    </subfield>
+    <subfield code="x" repeatable="true">
+      <description>General subdivision</description>
+    </subfield>
+    <subfield code="y" repeatable="true">
+      <description>Chronological subdivision</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Geographic subdivision</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="182" repeatable="false">
+    <name>Heading-Chronological Subdivision</name>
+    <description>Chronological term used as a heading in a subdivision record.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="v" repeatable="true">
+      <description>Form subdivision</description>
+    </subfield>
+    <subfield code="x" repeatable="true">
+      <description>General subdivision</description>
+    </subfield>
+    <subfield code="y" repeatable="true">
+      <description>Chronological subdivision</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Geographic subdivision</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="185" repeatable="false">
+    <name>Heading-Form Subdivision</name>
+    <description>Form or genre term used as a heading in a subdivision record.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="v" repeatable="true">
+      <description>Form subdivision</description>
+    </subfield>
+    <subfield code="x" repeatable="true">
+      <description>General subdivision</description>
+    </subfield>
+    <subfield code="y" repeatable="true">
+      <description>Chronological subdivision</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Geographic subdivision</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="260" repeatable="true">
+    <name>Complex See Reference-Subject</name>
+    <description>and that are required when relationships exist between unestablished and established subjects that cannot be adequately conveyed by one or more simple cross references generated from 4XX See From Tracing fields in the established heading record. A phrase such as may be generated for display.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="true">
+      <description>Heading referred to</description>
+    </subfield>
+    <subfield code="i" repeatable="true">
+      <description>Explanatory text</description>
+    </subfield>
+    <subfield code="0" repeatable="true">
+      <description>Authority record control number</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="336" repeatable="true">
+    <name>Content Type</name>
+    <description>The form of communication through which a work is expressed. Field 336 information enables expression of content types from various lists when the authority is for a title or name/title.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="true">
+      <description>Content type term</description>
+    </subfield>
+    <subfield code="b" repeatable="true">
+      <description>Content type code</description>
+    </subfield>
+    <subfield code="2" repeatable="false">
+      <description>Source</description>
+    </subfield>
+    <subfield code="3" repeatable="false">
+      <description>Materials specified</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="360" repeatable="true">
+    <name>Complex See Also Reference-Subject</name>
+    <description>and the that are required when relationships exist between established subjects that cannot be adequately conveyed by one or more simple cross references generated from 5XX See Also From Tracing fields. A phrase such as may be generated for display.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="true">
+      <description>Heading referred to</description>
+    </subfield>
+    <subfield code="i" repeatable="true">
+      <description>Explanatory text</description>
+    </subfield>
+    <subfield code="0" repeatable="true">
+      <description>Authority record control number</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="370" repeatable="true">
+    <name>Associated Place</name>
+    <description>A town, city, province, state, and/or country associated with persons, corporate bodies, families, works, and expressions.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Place of birth</description>
+    </subfield>
+    <subfield code="b" repeatable="false">
+      <description>Place of death</description>
+    </subfield>
+    <subfield code="c" repeatable="true">
+      <description>Associated country</description>
+    </subfield>
+    <subfield code="e" repeatable="true">
+      <description>Place of residence/headquarters</description>
+    </subfield>
+    <subfield code="f" repeatable="true">
+      <description>Other associated place</description>
+    </subfield>
+    <subfield code="g" repeatable="true">
+      <description>Place of origin of work</description>
+    </subfield>
+    <subfield code="s" repeatable="false">
+      <description>Start period</description>
+    </subfield>
+    <subfield code="t" repeatable="false">
+      <description>End period</description>
+    </subfield>
+    <subfield code="u" repeatable="true">
+      <description>Uniform Resource Identifier</description>
+    </subfield>
+    <subfield code="v" repeatable="true">
+      <description>Source of information</description>
+    </subfield>
+    <subfield code="0" repeatable="true">
+      <description>Record control number</description>
+    </subfield>
+    <subfield code="2" repeatable="true">
+      <description>Source of term</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="371" repeatable="true">
+    <name>Address</name>
+    <description>An address (as well as electronic access information such as email, telephone, fax, TTY, etc. numbers) associated with the entity described in the record. Multiple addresses, such as mailing addresses and addresses corresponding to the physical location of an item or facilities, are recorded in separate occurrences of field 371.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="true">
+      <description>Address</description>
+    </subfield>
+    <subfield code="b" repeatable="false">
+      <description>City</description>
+    </subfield>
+    <subfield code="c" repeatable="false">
+      <description>Intermediate jurisdiction</description>
+    </subfield>
+    <subfield code="d" repeatable="false">
+      <description>Country</description>
+    </subfield>
+    <subfield code="e" repeatable="false">
+      <description>Postal Code</description>
+    </subfield>
+    <subfield code="m" repeatable="true">
+      <description>Electronic mail address</description>
+    </subfield>
+    <subfield code="s" repeatable="false">
+      <description>Start period</description>
+    </subfield>
+    <subfield code="t" repeatable="false">
+      <description>End period</description>
+    </subfield>
+    <subfield code="u" repeatable="true">
+      <description>Uniform Resource Identifier</description>
+    </subfield>
+    <subfield code="v" repeatable="true">
+      <description>Source of information</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Public note</description>
+    </subfield>
+    <subfield code="4" repeatable="true">
+      <description>Relator code</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="372" repeatable="true">
+    <name>Field of Activity</name>
+    <description>: a field of endeavor, area of expertise, etc., in which the person is engaged or was engaged</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="true">
+      <description>Field of activity</description>
+    </subfield>
+    <subfield code="s" repeatable="false">
+      <description>Start period</description>
+    </subfield>
+    <subfield code="t" repeatable="false">
+      <description>End period</description>
+    </subfield>
+    <subfield code="u" repeatable="true">
+      <description>Uniform Resource Identifier</description>
+    </subfield>
+    <subfield code="v" repeatable="true">
+      <description>Source of information</description>
+    </subfield>
+    <subfield code="0" repeatable="true">
+      <description>Record control number</description>
+    </subfield>
+    <subfield code="2" repeatable="false">
+      <description>Source of term</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="373" repeatable="true">
+    <name>Affiliation</name>
+    <description>Information about a group with which a person is or has been affiliated, including dates of affiliation.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="true">
+      <description>Affiliation</description>
+    </subfield>
+    <subfield code="s" repeatable="false">
+      <description>Start period</description>
+    </subfield>
+    <subfield code="t" repeatable="false">
+      <description>End period</description>
+    </subfield>
+    <subfield code="u" repeatable="true">
+      <description>Uniform Resource Identifier</description>
+    </subfield>
+    <subfield code="v" repeatable="true">
+      <description>Source of information</description>
+    </subfield>
+    <subfield code="0" repeatable="true">
+      <description>Record control number</description>
+    </subfield>
+    <subfield code="2" repeatable="false">
+      <description>Source of term</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="374" repeatable="true">
+    <name>Occupation</name>
+    <description>Information about profession or occupation in which a person works or has worked, including dates applicable.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="true">
+      <description>Occupation</description>
+    </subfield>
+    <subfield code="s" repeatable="false">
+      <description>Start period</description>
+    </subfield>
+    <subfield code="t" repeatable="false">
+      <description>End period</description>
+    </subfield>
+    <subfield code="u" repeatable="true">
+      <description>Uniform Resource Identifier</description>
+    </subfield>
+    <subfield code="v" repeatable="true">
+      <description>Source of information</description>
+    </subfield>
+    <subfield code="0" repeatable="true">
+      <description>Record control number</description>
+    </subfield>
+    <subfield code="2" repeatable="false">
+      <description>Source of term</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="375" repeatable="true">
+    <name>Gender</name>
+    <description>Information about gender of a person, including dates applicable.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="true">
+      <description>Gender</description>
+    </subfield>
+    <subfield code="s" repeatable="false">
+      <description>Start period</description>
+    </subfield>
+    <subfield code="t" repeatable="false">
+      <description>End period</description>
+    </subfield>
+    <subfield code="u" repeatable="true">
+      <description>Uniform Resource Identifier</description>
+    </subfield>
+    <subfield code="v" repeatable="true">
+      <description>Source of information</description>
+    </subfield>
+    <subfield code="2" repeatable="false">
+      <description>Source of term</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="376" repeatable="true">
+    <name>Family Information</name>
+    <description>Additional information about families, including type of family, prominent member of the family, and hereditary title.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="true">
+      <description>Type of family</description>
+    </subfield>
+    <subfield code="b" repeatable="true">
+      <description>Name of prominent member</description>
+    </subfield>
+    <subfield code="c" repeatable="true">
+      <description>Hereditary title</description>
+    </subfield>
+    <subfield code="s" repeatable="false">
+      <description>Start period</description>
+    </subfield>
+    <subfield code="t" repeatable="false">
+      <description>End period</description>
+    </subfield>
+    <subfield code="u" repeatable="true">
+      <description>Uniform Resource Identifier</description>
+    </subfield>
+    <subfield code="v" repeatable="true">
+      <description>Source of information</description>
+    </subfield>
+    <subfield code="0" repeatable="true">
+      <description>Record control number</description>
+    </subfield>
+    <subfield code="2" repeatable="false">
+      <description>Source of term</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="377" repeatable="true">
+    <name>Associated Language</name>
+    <description>: the language a person uses when writing for publication, broadcasting, etc.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>MARC language code</description>
+    </indicator>
+    <indicator position="2" value="7">
+      <description>Source specified in $2</description>
+    </indicator>
+    <subfield code="a" repeatable="true">
+      <description>Language code</description>
+    </subfield>
+    <subfield code="2" repeatable="false">
+      <description>Source of term</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="380" repeatable="true">
+    <name>Form of Work</name>
+    <description>A class or genre to which a work belongs. May be used to differentiate a work from another work with the same title.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="true">
+      <description>Form of work</description>
+    </subfield>
+    <subfield code="0" repeatable="true">
+      <description>Record control number</description>
+    </subfield>
+    <subfield code="2" repeatable="false">
+      <description>Source of term</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="381" repeatable="true">
+    <name>Other Distinguishing Characteristics of Work or Expression</name>
+    <description>Any characteristic that is not accommodated in a special field that serves to characterize a work or expression. Examples are an issuing body, arranged statement of music, version, or a geographic term. May be used to differentiate a work from another work with the same title.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="true">
+      <description>Other distinguishing characteristic</description>
+    </subfield>
+    <subfield code="u" repeatable="true">
+      <description>Uniform Resource Identifier</description>
+    </subfield>
+    <subfield code="v" repeatable="true">
+      <description>Source of information</description>
+    </subfield>
+    <subfield code="0" repeatable="true">
+      <description>Record control number</description>
+    </subfield>
+    <subfield code="2" repeatable="false">
+      <description>Source of term</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="382" repeatable="true">
+    <name>Medium of Performance</name>
+    <description>The instrumental, vocal, and/or other medium of performance for which a musical work was originally conceived or for which a musical expression is written or performed. May be used to differentiate a musical work or expression from another with the same title.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="true">
+      <description>Medium of performance</description>
+    </subfield>
+    <subfield code="0" repeatable="true">
+      <description>Record control number</description>
+    </subfield>
+    <subfield code="2" repeatable="false">
+      <description>Source of term</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="383" repeatable="true">
+    <name>Numeric Designation of Musical Work</name>
+    <description>A serial number, opus number, or thematic index number assigned to a musical work by the composer, publisher, or a musicologist. May be used to differentiate a musical work from another with the same title.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="true">
+      <description>Serial number</description>
+    </subfield>
+    <subfield code="b" repeatable="true">
+      <description>Opus number</description>
+    </subfield>
+    <subfield code="c" repeatable="true">
+      <description>Thematic index number</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="384" repeatable="false">
+    <name>Key</name>
+    <description>The set of pitch relationships that establishes a single pitch class as a tonal centre for a musical work or expression. May be used to differentiate a musical work or expression from another with the same title.</description>
+    <indicator position="1" value="#">
+      <description>Relationship to original unknown</description>
+    </indicator>
+    <indicator position="1" value="0">
+      <description>Original key</description>
+    </indicator>
+    <indicator position="1" value="1">
+      <description>Transposed key</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Key</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="400" repeatable="true">
+    <name>See From Tracing-Personal Name</name>
+    <description>Tracing for a personal name reference.</description>
+    <indicator position="1" value="0">
+      <description>Forename</description>
+    </indicator>
+    <indicator position="1" value="1">
+      <description>Surname</description>
+    </indicator>
+    <indicator position="1" value="3">
+      <description>Family name</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Personal name</description>
+    </subfield>
+    <subfield code="b" repeatable="false">
+      <description>Numeration</description>
+    </subfield>
+    <subfield code="c" repeatable="true">
+      <description>Titles and other words associated with a name</description>
+    </subfield>
+    <subfield code="d" repeatable="false">
+      <description>Dates associated with a name</description>
+    </subfield>
+    <subfield code="e" repeatable="true">
+      <description>Relator term</description>
+    </subfield>
+    <subfield code="f" repeatable="false">
+      <description>Date of a work</description>
+    </subfield>
+    <subfield code="g" repeatable="false">
+      <description>Miscellaneous information</description>
+    </subfield>
+    <subfield code="h" repeatable="false">
+      <description>Medium</description>
+    </subfield>
+    <subfield code="i" repeatable="true">
+      <description>Relationship information</description>
+    </subfield>
+    <subfield code="j" repeatable="true">
+      <description>Attribution qualifier</description>
+    </subfield>
+    <subfield code="k" repeatable="true">
+      <description>Form subheading</description>
+    </subfield>
+    <subfield code="l" repeatable="false">
+      <description>Language of a work</description>
+    </subfield>
+    <subfield code="m" repeatable="true">
+      <description>Medium of performance for music</description>
+    </subfield>
+    <subfield code="n" repeatable="true">
+      <description>Number of part/section of a work</description>
+    </subfield>
+    <subfield code="o" repeatable="false">
+      <description>Arranged statement for music</description>
+    </subfield>
+    <subfield code="p" repeatable="true">
+      <description>Name of part/section of a work</description>
+    </subfield>
+    <subfield code="q" repeatable="false">
+      <description>Fuller form of name</description>
+    </subfield>
+    <subfield code="r" repeatable="false">
+      <description>Key for music</description>
+    </subfield>
+    <subfield code="s" repeatable="false">
+      <description>Version</description>
+    </subfield>
+    <subfield code="t" repeatable="false">
+      <description>Title of a work</description>
+    </subfield>
+    <subfield code="v" repeatable="true">
+      <description>Form subdivision</description>
+    </subfield>
+    <subfield code="w" repeatable="false">
+      <description>Control subfield</description>
+    </subfield>
+    <subfield code="x" repeatable="true">
+      <description>General subdivision</description>
+    </subfield>
+    <subfield code="y" repeatable="true">
+      <description>Chronological subdivision</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Geographic subdivision</description>
+    </subfield>
+    <subfield code="4" repeatable="true">
+      <description>Relationship code</description>
+    </subfield>
+    <subfield code="5" repeatable="true">
+      <description>Institution to which field applies</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="410" repeatable="true">
+    <name>See From Tracing-Corporate Name</name>
+    <description>Tracing for a corporate name reference.</description>
+    <indicator position="1" value="0">
+      <description>Inverted name</description>
+    </indicator>
+    <indicator position="1" value="1">
+      <description>Jurisdiction name</description>
+    </indicator>
+    <indicator position="1" value="2">
+      <description>Name in direct order</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Corporate name or jurisdiction name as entry element</description>
+    </subfield>
+    <subfield code="b" repeatable="true">
+      <description>Subordinate unit</description>
+    </subfield>
+    <subfield code="c" repeatable="false">
+      <description>Location of meeting</description>
+    </subfield>
+    <subfield code="d" repeatable="true">
+      <description>Date of meeting or treaty signing</description>
+    </subfield>
+    <subfield code="e" repeatable="true">
+      <description>Relator term</description>
+    </subfield>
+    <subfield code="f" repeatable="false">
+      <description>Date of a work</description>
+    </subfield>
+    <subfield code="g" repeatable="false">
+      <description>Miscellaneous information</description>
+    </subfield>
+    <subfield code="h" repeatable="false">
+      <description>Medium</description>
+    </subfield>
+    <subfield code="i" repeatable="true">
+      <description>Relationship information</description>
+    </subfield>
+    <subfield code="k" repeatable="true">
+      <description>Form subheading</description>
+    </subfield>
+    <subfield code="l" repeatable="false">
+      <description>Language of a work</description>
+    </subfield>
+    <subfield code="m" repeatable="true">
+      <description>Medium of performance for music</description>
+    </subfield>
+    <subfield code="n" repeatable="true">
+      <description>Number of part/section/meeting</description>
+    </subfield>
+    <subfield code="o" repeatable="false">
+      <description>Arranged statement for music</description>
+    </subfield>
+    <subfield code="p" repeatable="true">
+      <description>Name of part/section of a work</description>
+    </subfield>
+    <subfield code="r" repeatable="false">
+      <description>Key for music</description>
+    </subfield>
+    <subfield code="s" repeatable="false">
+      <description>Version</description>
+    </subfield>
+    <subfield code="t" repeatable="false">
+      <description>Title of a work</description>
+    </subfield>
+    <subfield code="v" repeatable="true">
+      <description>Form subdivision</description>
+    </subfield>
+    <subfield code="w" repeatable="false">
+      <description>Control subfield</description>
+    </subfield>
+    <subfield code="x" repeatable="true">
+      <description>General subdivision</description>
+    </subfield>
+    <subfield code="y" repeatable="true">
+      <description>Chronological subdivision</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Geographic subdivision</description>
+    </subfield>
+    <subfield code="4" repeatable="true">
+      <description>Relationship code</description>
+    </subfield>
+    <subfield code="5" repeatable="true">
+      <description>Institution to which field applies</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="411" repeatable="true">
+    <name>See From Tracing-Meeting Name</name>
+    <description>Tracing for a meeting name reference. It is used in an established heading record or an established heading and subdivision record to trace a see from reference from a meeting name not used to an established heading.</description>
+    <indicator position="1" value="0">
+      <description>Inverted name</description>
+    </indicator>
+    <indicator position="1" value="1">
+      <description>Jurisdiction name</description>
+    </indicator>
+    <indicator position="1" value="2">
+      <description>Name in direct order</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Meeting name or jurisdiction name as entry element</description>
+    </subfield>
+    <subfield code="c" repeatable="false">
+      <description>Location of meeting</description>
+    </subfield>
+    <subfield code="d" repeatable="false">
+      <description>Date of meeting</description>
+    </subfield>
+    <subfield code="e" repeatable="true">
+      <description>Subordinate unit</description>
+    </subfield>
+    <subfield code="f" repeatable="false">
+      <description>Date of a work</description>
+    </subfield>
+    <subfield code="g" repeatable="false">
+      <description>Miscellaneous information</description>
+    </subfield>
+    <subfield code="h" repeatable="false">
+      <description>Medium</description>
+    </subfield>
+    <subfield code="i" repeatable="true">
+      <description>Relationship information</description>
+    </subfield>
+    <subfield code="j" repeatable="true">
+      <description>Relator term</description>
+    </subfield>
+    <subfield code="k" repeatable="true">
+      <description>Form subheading</description>
+    </subfield>
+    <subfield code="l" repeatable="false">
+      <description>Language of a work</description>
+    </subfield>
+    <subfield code="n" repeatable="true">
+      <description>Number of part/section/meeting</description>
+    </subfield>
+    <subfield code="p" repeatable="true">
+      <description>Name of part/section of a work</description>
+    </subfield>
+    <subfield code="q" repeatable="false">
+      <description>Name of meeting following jurisdiction name entry element</description>
+    </subfield>
+    <subfield code="s" repeatable="false">
+      <description>Version</description>
+    </subfield>
+    <subfield code="t" repeatable="false">
+      <description>Title of a work</description>
+    </subfield>
+    <subfield code="v" repeatable="true">
+      <description>Form subdivision</description>
+    </subfield>
+    <subfield code="w" repeatable="false">
+      <description>Control subfield</description>
+    </subfield>
+    <subfield code="x" repeatable="true">
+      <description>General subdivision</description>
+    </subfield>
+    <subfield code="y" repeatable="true">
+      <description>Chronological subdivision</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Geographic subdivision</description>
+    </subfield>
+    <subfield code="4" repeatable="true">
+      <description>Relationship code</description>
+    </subfield>
+    <subfield code="5" repeatable="true">
+      <description>Institution to which field applies</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="430" repeatable="true">
+    <name>See From Tracing-Uniform Title</name>
+    <description>Tracing for a uniform title reference.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="0">
+      <description>No nonfiling characters</description>
+    </indicator>
+    <indicator position="2" value="1">
+      <description>Number of nonfiling characters - 1</description>
+    </indicator>
+    <indicator position="2" value="2">
+      <description>Number of nonfiling characters - 2</description>
+    </indicator>
+    <indicator position="2" value="3">
+      <description>Number of nonfiling characters - 3</description>
+    </indicator>
+    <indicator position="2" value="4">
+      <description>Number of nonfiling characters - 4</description>
+    </indicator>
+    <indicator position="2" value="5">
+      <description>Number of nonfiling characters - 5</description>
+    </indicator>
+    <indicator position="2" value="6">
+      <description>Number of nonfiling characters - 6</description>
+    </indicator>
+    <indicator position="2" value="7">
+      <description>Number of nonfiling characters - 7</description>
+    </indicator>
+    <indicator position="2" value="8">
+      <description>Number of nonfiling characters - 8</description>
+    </indicator>
+    <indicator position="2" value="9">
+      <description>Number of nonfiling characters - 9</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Uniform title</description>
+    </subfield>
+    <subfield code="d" repeatable="true">
+      <description>Date of treaty signing</description>
+    </subfield>
+    <subfield code="f" repeatable="false">
+      <description>Date of a work</description>
+    </subfield>
+    <subfield code="g" repeatable="false">
+      <description>Miscellaneous information</description>
+    </subfield>
+    <subfield code="h" repeatable="false">
+      <description>Medium</description>
+    </subfield>
+    <subfield code="i" repeatable="true">
+      <description>Relationship information</description>
+    </subfield>
+    <subfield code="k" repeatable="true">
+      <description>Form subheading</description>
+    </subfield>
+    <subfield code="l" repeatable="false">
+      <description>Language of a work</description>
+    </subfield>
+    <subfield code="m" repeatable="true">
+      <description>Medium of performance for music</description>
+    </subfield>
+    <subfield code="n" repeatable="true">
+      <description>Number of part/section of a work</description>
+    </subfield>
+    <subfield code="o" repeatable="false">
+      <description>Arranged statement for music</description>
+    </subfield>
+    <subfield code="p" repeatable="true">
+      <description>Name of part/section of a work</description>
+    </subfield>
+    <subfield code="r" repeatable="false">
+      <description>Key for music</description>
+    </subfield>
+    <subfield code="s" repeatable="false">
+      <description>Version</description>
+    </subfield>
+    <subfield code="t" repeatable="false">
+      <description>Title of a work</description>
+    </subfield>
+    <subfield code="v" repeatable="true">
+      <description>Form subdivision</description>
+    </subfield>
+    <subfield code="w" repeatable="false">
+      <description>Control subfield</description>
+    </subfield>
+    <subfield code="x" repeatable="true">
+      <description>General subdivision</description>
+    </subfield>
+    <subfield code="y" repeatable="true">
+      <description>Chronological subdivision</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Geographic subdivision</description>
+    </subfield>
+    <subfield code="4" repeatable="true">
+      <description>Relationship code</description>
+    </subfield>
+    <subfield code="5" repeatable="true">
+      <description>Institution to which field applies</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="448" repeatable="true">
+    <name>See From Tracing-Chronological Term</name>
+    <description>Tracing for a chronological term reference.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Chronological term</description>
+    </subfield>
+    <subfield code="i" repeatable="true">
+      <description>Relationship information</description>
+    </subfield>
+    <subfield code="v" repeatable="true">
+      <description>Form subdivision</description>
+    </subfield>
+    <subfield code="w" repeatable="false">
+      <description>Control subfield</description>
+    </subfield>
+    <subfield code="x" repeatable="true">
+      <description>General subdivision</description>
+    </subfield>
+    <subfield code="y" repeatable="true">
+      <description>Chronological subdivision</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Geographic subdivision</description>
+    </subfield>
+    <subfield code="4" repeatable="true">
+      <description>Relationship code</description>
+    </subfield>
+    <subfield code="5" repeatable="true">
+      <description>Institution to which field applies</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="450" repeatable="true">
+    <name>See From Tracing-Topical Term</name>
+    <description>Tracing for a topical term reference.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Topical term or geographic name entry element</description>
+    </subfield>
+    <subfield code="b" repeatable="false">
+      <description>Topical term following geographic name entry element</description>
+    </subfield>
+    <subfield code="i" repeatable="true">
+      <description>Relationship information</description>
+    </subfield>
+    <subfield code="v" repeatable="true">
+      <description>Form subdivision</description>
+    </subfield>
+    <subfield code="w" repeatable="false">
+      <description>Control subfield</description>
+    </subfield>
+    <subfield code="x" repeatable="true">
+      <description>General subdivision</description>
+    </subfield>
+    <subfield code="y" repeatable="true">
+      <description>Chronological subdivision</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Geographic subdivision</description>
+    </subfield>
+    <subfield code="4" repeatable="true">
+      <description>Relationship code</description>
+    </subfield>
+    <subfield code="5" repeatable="true">
+      <description>Institution to which field applies</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="451" repeatable="true">
+    <name>See From Tracing-Geographic Name</name>
+    <description>Tracing for a geographic name reference.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Geographic name</description>
+    </subfield>
+    <subfield code="i" repeatable="true">
+      <description>Relationship information</description>
+    </subfield>
+    <subfield code="v" repeatable="true">
+      <description>Form subdivision</description>
+    </subfield>
+    <subfield code="w" repeatable="false">
+      <description>Control subfield</description>
+    </subfield>
+    <subfield code="x" repeatable="true">
+      <description>General subdivision</description>
+    </subfield>
+    <subfield code="y" repeatable="true">
+      <description>Chronological subdivision</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Geographic subdivision</description>
+    </subfield>
+    <subfield code="4" repeatable="true">
+      <description>Relationship code</description>
+    </subfield>
+    <subfield code="5" repeatable="true">
+      <description>Institution to which field applies</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="455" repeatable="true">
+    <name>See From Tracing-Genre/Form Term</name>
+    <description>Tracing for a genre/form term reference.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Genre/form term</description>
+    </subfield>
+    <subfield code="i" repeatable="true">
+      <description>Relationship information</description>
+    </subfield>
+    <subfield code="v" repeatable="true">
+      <description>Form subdivision</description>
+    </subfield>
+    <subfield code="w" repeatable="false">
+      <description>Control subfield</description>
+    </subfield>
+    <subfield code="x" repeatable="true">
+      <description>General subdivision</description>
+    </subfield>
+    <subfield code="y" repeatable="true">
+      <description>Chronological subdivision</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Geographic subdivision</description>
+    </subfield>
+    <subfield code="4" repeatable="true">
+      <description>Relationship code</description>
+    </subfield>
+    <subfield code="5" repeatable="true">
+      <description>Institution to which field applies</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="480" repeatable="true">
+    <name>See From Tracing-General Subdivision</name>
+    <description>Tracing for a general subdivision reference.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="i" repeatable="true">
+      <description>Relationship information</description>
+    </subfield>
+    <subfield code="v" repeatable="true">
+      <description>Form subdivision</description>
+    </subfield>
+    <subfield code="w" repeatable="false">
+      <description>Control subfield</description>
+    </subfield>
+    <subfield code="x" repeatable="true">
+      <description>General subdivision</description>
+    </subfield>
+    <subfield code="y" repeatable="true">
+      <description>Chronological subdivision</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Geographic subdivision</description>
+    </subfield>
+    <subfield code="4" repeatable="true">
+      <description>Relationship code</description>
+    </subfield>
+    <subfield code="5" repeatable="true">
+      <description>Institution to which field applies</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="481" repeatable="true">
+    <name>See From Tracing-Geographic Subdivision</name>
+    <description>Tracing for a geographic subdivision reference.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="i" repeatable="true">
+      <description>Relationship information</description>
+    </subfield>
+    <subfield code="v" repeatable="true">
+      <description>Form subdivision</description>
+    </subfield>
+    <subfield code="w" repeatable="false">
+      <description>Control subfield</description>
+    </subfield>
+    <subfield code="x" repeatable="true">
+      <description>General subdivision</description>
+    </subfield>
+    <subfield code="y" repeatable="true">
+      <description>Chronological subdivision</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Geographic subdivision</description>
+    </subfield>
+    <subfield code="4" repeatable="true">
+      <description>Relationship code</description>
+    </subfield>
+    <subfield code="5" repeatable="true">
+      <description>Institution to which field applies</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="482" repeatable="true">
+    <name>See From Tracing-Chronological Subdivision</name>
+    <description>Tracing for a chronological subdivision reference.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="i" repeatable="true">
+      <description>Relationship information</description>
+    </subfield>
+    <subfield code="v" repeatable="true">
+      <description>Form subdivision</description>
+    </subfield>
+    <subfield code="w" repeatable="false">
+      <description>Control subfield</description>
+    </subfield>
+    <subfield code="x" repeatable="true">
+      <description>General subdivision</description>
+    </subfield>
+    <subfield code="y" repeatable="true">
+      <description>Chronological subdivision</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Geographic subdivision</description>
+    </subfield>
+    <subfield code="4" repeatable="true">
+      <description>Relationship code</description>
+    </subfield>
+    <subfield code="5" repeatable="true">
+      <description>Institution to which field applies</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="485" repeatable="true">
+    <name>See From Tracing-Form Subdivision</name>
+    <description>Tracing for a form subdivision reference.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="i" repeatable="true">
+      <description>Relationship information</description>
+    </subfield>
+    <subfield code="v" repeatable="true">
+      <description>Form subdivision</description>
+    </subfield>
+    <subfield code="w" repeatable="false">
+      <description>Control subfield</description>
+    </subfield>
+    <subfield code="x" repeatable="true">
+      <description>General subdivision</description>
+    </subfield>
+    <subfield code="y" repeatable="true">
+      <description>Chronological subdivision</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Geographic subdivision</description>
+    </subfield>
+    <subfield code="4" repeatable="true">
+      <description>Relationship code</description>
+    </subfield>
+    <subfield code="5" repeatable="true">
+      <description>Institution to which field applies</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="500" repeatable="true">
+    <name>See Also From Tracing-Personal Name</name>
+    <description>Tracing for a personal name reference.</description>
+    <indicator position="1" value="0">
+      <description>Forename</description>
+    </indicator>
+    <indicator position="1" value="1">
+      <description>Surname</description>
+    </indicator>
+    <indicator position="1" value="3">
+      <description>Family name</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Personal name</description>
+    </subfield>
+    <subfield code="b" repeatable="false">
+      <description>Numeration</description>
+    </subfield>
+    <subfield code="c" repeatable="true">
+      <description>Titles and other words associated with a name</description>
+    </subfield>
+    <subfield code="d" repeatable="false">
+      <description>Dates associated with a name</description>
+    </subfield>
+    <subfield code="e" repeatable="true">
+      <description>Relator term</description>
+    </subfield>
+    <subfield code="f" repeatable="false">
+      <description>Date of a work</description>
+    </subfield>
+    <subfield code="g" repeatable="false">
+      <description>Miscellaneous information</description>
+    </subfield>
+    <subfield code="h" repeatable="false">
+      <description>Medium</description>
+    </subfield>
+    <subfield code="i" repeatable="true">
+      <description>Relationship information</description>
+    </subfield>
+    <subfield code="j" repeatable="true">
+      <description>Attribution qualifier</description>
+    </subfield>
+    <subfield code="k" repeatable="true">
+      <description>Form subheading</description>
+    </subfield>
+    <subfield code="l" repeatable="false">
+      <description>Language of a work</description>
+    </subfield>
+    <subfield code="m" repeatable="true">
+      <description>Medium of performance for music</description>
+    </subfield>
+    <subfield code="n" repeatable="true">
+      <description>Number of part/section of a work</description>
+    </subfield>
+    <subfield code="o" repeatable="false">
+      <description>Arranged statement for music</description>
+    </subfield>
+    <subfield code="p" repeatable="true">
+      <description>Name of part/section of a work</description>
+    </subfield>
+    <subfield code="q" repeatable="false">
+      <description>Fuller form of name</description>
+    </subfield>
+    <subfield code="r" repeatable="false">
+      <description>Key for music</description>
+    </subfield>
+    <subfield code="s" repeatable="false">
+      <description>Version</description>
+    </subfield>
+    <subfield code="t" repeatable="false">
+      <description>Title of a work</description>
+    </subfield>
+    <subfield code="v" repeatable="true">
+      <description>Form subdivision</description>
+    </subfield>
+    <subfield code="w" repeatable="false">
+      <description>Control subfield</description>
+    </subfield>
+    <subfield code="x" repeatable="true">
+      <description>General subdivision</description>
+    </subfield>
+    <subfield code="y" repeatable="true">
+      <description>Chronological subdivision</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Geographic subdivision</description>
+    </subfield>
+    <subfield code="0" repeatable="true">
+      <description>Record control number</description>
+    </subfield>
+    <subfield code="4" repeatable="true">
+      <description>Relationship code</description>
+    </subfield>
+    <subfield code="5" repeatable="true">
+      <description>Institution to which field applies</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="510" repeatable="true">
+    <name>See Also From Tracing-Corporate Name</name>
+    <description>Tracing for a corporate name reference.</description>
+    <indicator position="1" value="0">
+      <description>Inverted name</description>
+    </indicator>
+    <indicator position="1" value="1">
+      <description>Jurisdiction name</description>
+    </indicator>
+    <indicator position="1" value="2">
+      <description>Name in direct order</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Corporate name or jurisdiction name as entry element</description>
+    </subfield>
+    <subfield code="b" repeatable="true">
+      <description>Subordinate unit</description>
+    </subfield>
+    <subfield code="c" repeatable="false">
+      <description>Location of meeting</description>
+    </subfield>
+    <subfield code="d" repeatable="true">
+      <description>Date of meeting or treaty signing</description>
+    </subfield>
+    <subfield code="e" repeatable="true">
+      <description>Relator term</description>
+    </subfield>
+    <subfield code="f" repeatable="false">
+      <description>Date of a work</description>
+    </subfield>
+    <subfield code="g" repeatable="false">
+      <description>Miscellaneous information</description>
+    </subfield>
+    <subfield code="h" repeatable="false">
+      <description>Medium</description>
+    </subfield>
+    <subfield code="i" repeatable="true">
+      <description>Relationship information</description>
+    </subfield>
+    <subfield code="k" repeatable="true">
+      <description>Form subheading</description>
+    </subfield>
+    <subfield code="l" repeatable="false">
+      <description>Language of a work</description>
+    </subfield>
+    <subfield code="m" repeatable="true">
+      <description>Medium of performance for music</description>
+    </subfield>
+    <subfield code="n" repeatable="true">
+      <description>Number of part/section/meeting</description>
+    </subfield>
+    <subfield code="o" repeatable="false">
+      <description>Arranged statement for music</description>
+    </subfield>
+    <subfield code="p" repeatable="true">
+      <description>Name of part/section of a work</description>
+    </subfield>
+    <subfield code="r" repeatable="false">
+      <description>Key for music</description>
+    </subfield>
+    <subfield code="s" repeatable="false">
+      <description>Version</description>
+    </subfield>
+    <subfield code="t" repeatable="false">
+      <description>Title of a work</description>
+    </subfield>
+    <subfield code="v" repeatable="true">
+      <description>Form subdivision</description>
+    </subfield>
+    <subfield code="w" repeatable="false">
+      <description>Control subfield</description>
+    </subfield>
+    <subfield code="x" repeatable="true">
+      <description>General subdivision</description>
+    </subfield>
+    <subfield code="y" repeatable="true">
+      <description>Chronological subdivision</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Geographic subdivision</description>
+    </subfield>
+    <subfield code="0" repeatable="true">
+      <description>Record control number</description>
+    </subfield>
+    <subfield code="4" repeatable="true">
+      <description>Relationship code</description>
+    </subfield>
+    <subfield code="5" repeatable="true">
+      <description>Institution to which field applies</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="511" repeatable="true">
+    <name>See Also From Tracing-Meeting Name</name>
+    <description>Tracing for a meeting name reference. It is used in an established heading record or an established heading and subdivision record to trace a see also from reference from an established meeting name to a related established heading.</description>
+    <indicator position="1" value="0">
+      <description>Inverted name</description>
+    </indicator>
+    <indicator position="1" value="1">
+      <description>Jurisdiction name</description>
+    </indicator>
+    <indicator position="1" value="2">
+      <description>Name in direct order</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Meeting name or jurisdiction name as entry element</description>
+    </subfield>
+    <subfield code="c" repeatable="false">
+      <description>Location of meeting</description>
+    </subfield>
+    <subfield code="d" repeatable="false">
+      <description>Date of meeting</description>
+    </subfield>
+    <subfield code="e" repeatable="true">
+      <description>Subordinate unit</description>
+    </subfield>
+    <subfield code="f" repeatable="false">
+      <description>Date of a work</description>
+    </subfield>
+    <subfield code="g" repeatable="false">
+      <description>Miscellaneous information</description>
+    </subfield>
+    <subfield code="h" repeatable="false">
+      <description>Medium</description>
+    </subfield>
+    <subfield code="i" repeatable="true">
+      <description>Relationship information</description>
+    </subfield>
+    <subfield code="j" repeatable="true">
+      <description>Relator term</description>
+    </subfield>
+    <subfield code="k" repeatable="true">
+      <description>Form subheading</description>
+    </subfield>
+    <subfield code="l" repeatable="false">
+      <description>Language of a work</description>
+    </subfield>
+    <subfield code="n" repeatable="true">
+      <description>Number of part/section/meeting</description>
+    </subfield>
+    <subfield code="p" repeatable="true">
+      <description>Name of part/section of a work</description>
+    </subfield>
+    <subfield code="q" repeatable="false">
+      <description>Name of meeting following jurisdiction name entry element</description>
+    </subfield>
+    <subfield code="s" repeatable="false">
+      <description>Version</description>
+    </subfield>
+    <subfield code="t" repeatable="false">
+      <description>Title of a work</description>
+    </subfield>
+    <subfield code="v" repeatable="true">
+      <description>Form subdivision</description>
+    </subfield>
+    <subfield code="w" repeatable="false">
+      <description>Control subfield</description>
+    </subfield>
+    <subfield code="x" repeatable="true">
+      <description>General subdivision</description>
+    </subfield>
+    <subfield code="y" repeatable="true">
+      <description>Chronological subdivision</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Geographic subdivision</description>
+    </subfield>
+    <subfield code="0" repeatable="true">
+      <description>Record control number</description>
+    </subfield>
+    <subfield code="4" repeatable="true">
+      <description>Relationship code</description>
+    </subfield>
+    <subfield code="5" repeatable="true">
+      <description>Institution to which field applies</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="530" repeatable="true">
+    <name>See Also From Tracing-Uniform Title</name>
+    <description>Tracing for a uniform title reference.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="0">
+      <description>No nonfiling characters</description>
+    </indicator>
+    <indicator position="2" value="1">
+      <description>Number of nonfiling characters - 1</description>
+    </indicator>
+    <indicator position="2" value="2">
+      <description>Number of nonfiling characters - 2</description>
+    </indicator>
+    <indicator position="2" value="3">
+      <description>Number of nonfiling characters - 3</description>
+    </indicator>
+    <indicator position="2" value="4">
+      <description>Number of nonfiling characters - 4</description>
+    </indicator>
+    <indicator position="2" value="5">
+      <description>Number of nonfiling characters - 5</description>
+    </indicator>
+    <indicator position="2" value="6">
+      <description>Number of nonfiling characters - 6</description>
+    </indicator>
+    <indicator position="2" value="7">
+      <description>Number of nonfiling characters - 7</description>
+    </indicator>
+    <indicator position="2" value="8">
+      <description>Number of nonfiling characters - 8</description>
+    </indicator>
+    <indicator position="2" value="9">
+      <description>Number of nonfiling characters - 9</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Uniform title</description>
+    </subfield>
+    <subfield code="d" repeatable="true">
+      <description>Date of treaty signing</description>
+    </subfield>
+    <subfield code="f" repeatable="false">
+      <description>Date of a work</description>
+    </subfield>
+    <subfield code="g" repeatable="false">
+      <description>Miscellaneous information</description>
+    </subfield>
+    <subfield code="h" repeatable="false">
+      <description>Medium</description>
+    </subfield>
+    <subfield code="i" repeatable="true">
+      <description>Relationship information</description>
+    </subfield>
+    <subfield code="k" repeatable="true">
+      <description>Form subheading</description>
+    </subfield>
+    <subfield code="l" repeatable="false">
+      <description>Language of a work</description>
+    </subfield>
+    <subfield code="m" repeatable="true">
+      <description>Medium of performance for music</description>
+    </subfield>
+    <subfield code="n" repeatable="true">
+      <description>Number of part/section of a work</description>
+    </subfield>
+    <subfield code="o" repeatable="false">
+      <description>Arranged statement for music</description>
+    </subfield>
+    <subfield code="p" repeatable="true">
+      <description>Name of part/section of a work</description>
+    </subfield>
+    <subfield code="r" repeatable="false">
+      <description>Key for music</description>
+    </subfield>
+    <subfield code="s" repeatable="false">
+      <description>Version</description>
+    </subfield>
+    <subfield code="t" repeatable="false">
+      <description>Title of a work</description>
+    </subfield>
+    <subfield code="v" repeatable="true">
+      <description>Form subdivision</description>
+    </subfield>
+    <subfield code="w" repeatable="false">
+      <description>Control subfield</description>
+    </subfield>
+    <subfield code="x" repeatable="true">
+      <description>General subdivision</description>
+    </subfield>
+    <subfield code="y" repeatable="true">
+      <description>Chronological subdivision</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Geographic subdivision</description>
+    </subfield>
+    <subfield code="0" repeatable="true">
+      <description>Record control number</description>
+    </subfield>
+    <subfield code="4" repeatable="true">
+      <description>Relationship code</description>
+    </subfield>
+    <subfield code="5" repeatable="true">
+      <description>Institution to which field applies</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="548" repeatable="true">
+    <name>See Also From Tracing-Chronological Term</name>
+    <description>Tracing for a chronological term reference.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Chronological term</description>
+    </subfield>
+    <subfield code="i" repeatable="true">
+      <description>Relationship information</description>
+    </subfield>
+    <subfield code="v" repeatable="true">
+      <description>Form subdivision</description>
+    </subfield>
+    <subfield code="w" repeatable="false">
+      <description>Control subfield</description>
+    </subfield>
+    <subfield code="x" repeatable="true">
+      <description>General subdivision</description>
+    </subfield>
+    <subfield code="y" repeatable="true">
+      <description>Chronological subdivision</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Geographic subdivision</description>
+    </subfield>
+    <subfield code="0" repeatable="true">
+      <description>Record control number</description>
+    </subfield>
+    <subfield code="4" repeatable="true">
+      <description>Relationship code</description>
+    </subfield>
+    <subfield code="5" repeatable="true">
+      <description>Institution to which field applies</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="550" repeatable="true">
+    <name>See Also From Tracing-Topical Term</name>
+    <description>Tracing for a topical term reference.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Topical term or geographic name entry element</description>
+    </subfield>
+    <subfield code="b" repeatable="false">
+      <description>Topical term following geographic name entry element</description>
+    </subfield>
+    <subfield code="i" repeatable="true">
+      <description>Relationship information</description>
+    </subfield>
+    <subfield code="v" repeatable="true">
+      <description>Form subdivision</description>
+    </subfield>
+    <subfield code="w" repeatable="false">
+      <description>Control subfield</description>
+    </subfield>
+    <subfield code="x" repeatable="true">
+      <description>General subdivision</description>
+    </subfield>
+    <subfield code="y" repeatable="true">
+      <description>Chronological subdivision</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Geographic subdivision</description>
+    </subfield>
+    <subfield code="0" repeatable="true">
+      <description>Record control number</description>
+    </subfield>
+    <subfield code="4" repeatable="true">
+      <description>Relationship code</description>
+    </subfield>
+    <subfield code="5" repeatable="true">
+      <description>Institution to which field applies</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="551" repeatable="true">
+    <name>See Also From Tracing-Geographic Name</name>
+    <description>Tracing for a geographic name reference.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Geographic name</description>
+    </subfield>
+    <subfield code="i" repeatable="true">
+      <description>Relationship information</description>
+    </subfield>
+    <subfield code="v" repeatable="true">
+      <description>Form subdivision</description>
+    </subfield>
+    <subfield code="w" repeatable="false">
+      <description>Control subfield</description>
+    </subfield>
+    <subfield code="x" repeatable="true">
+      <description>General subdivision</description>
+    </subfield>
+    <subfield code="y" repeatable="true">
+      <description>Chronological subdivision</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Geographic subdivision</description>
+    </subfield>
+    <subfield code="0" repeatable="true">
+      <description>Record control number</description>
+    </subfield>
+    <subfield code="4" repeatable="true">
+      <description>Relationship code</description>
+    </subfield>
+    <subfield code="5" repeatable="true">
+      <description>Institution to which field applies</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="555" repeatable="true">
+    <name>See Also From Tracing-Genre/Form Term</name>
+    <description>Tracing for a genre/form term reference.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Genre/form term</description>
+    </subfield>
+    <subfield code="i" repeatable="true">
+      <description>Relationship information</description>
+    </subfield>
+    <subfield code="v" repeatable="true">
+      <description>Form subdivision</description>
+    </subfield>
+    <subfield code="w" repeatable="false">
+      <description>Control subfield</description>
+    </subfield>
+    <subfield code="x" repeatable="true">
+      <description>General subdivision</description>
+    </subfield>
+    <subfield code="y" repeatable="true">
+      <description>Chronological subdivision</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Geographic subdivision</description>
+    </subfield>
+    <subfield code="0" repeatable="true">
+      <description>Record control number</description>
+    </subfield>
+    <subfield code="4" repeatable="true">
+      <description>Relationship code</description>
+    </subfield>
+    <subfield code="5" repeatable="true">
+      <description>Institution to which field applies</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="580" repeatable="true">
+    <name>See Also From Tracing-General Subdivision</name>
+    <description>Tracing for a general subdivision reference.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="i" repeatable="true">
+      <description>Relationship information</description>
+    </subfield>
+    <subfield code="v" repeatable="true">
+      <description>Form subdivision</description>
+    </subfield>
+    <subfield code="w" repeatable="false">
+      <description>Control subfield</description>
+    </subfield>
+    <subfield code="x" repeatable="true">
+      <description>General subdivision</description>
+    </subfield>
+    <subfield code="y" repeatable="true">
+      <description>Chronological subdivision</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Geographic subdivision</description>
+    </subfield>
+    <subfield code="0" repeatable="true">
+      <description>Record control number</description>
+    </subfield>
+    <subfield code="4" repeatable="true">
+      <description>Relationship code</description>
+    </subfield>
+    <subfield code="5" repeatable="true">
+      <description>Institution to which field applies</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="581" repeatable="true">
+    <name>See Also From Tracing-Geographic Subdivision</name>
+    <description>Tracing for a geographic subdivision reference.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="i" repeatable="true">
+      <description>Relationship information</description>
+    </subfield>
+    <subfield code="v" repeatable="true">
+      <description>Form subdivision</description>
+    </subfield>
+    <subfield code="w" repeatable="false">
+      <description>Control subfield</description>
+    </subfield>
+    <subfield code="x" repeatable="true">
+      <description>General subdivision</description>
+    </subfield>
+    <subfield code="y" repeatable="true">
+      <description>Chronological subdivision</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Geographic subdivision</description>
+    </subfield>
+    <subfield code="0" repeatable="true">
+      <description>Record control number</description>
+    </subfield>
+    <subfield code="4" repeatable="true">
+      <description>Relationship code</description>
+    </subfield>
+    <subfield code="5" repeatable="true">
+      <description>Institution to which field applies</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="582" repeatable="true">
+    <name>See Also From Tracing-Chronological Subdivision</name>
+    <description>Tracing for a chronological subdivision .</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="i" repeatable="true">
+      <description>Relationship information</description>
+    </subfield>
+    <subfield code="v" repeatable="true">
+      <description>Form subdivision</description>
+    </subfield>
+    <subfield code="w" repeatable="false">
+      <description>Control subfield</description>
+    </subfield>
+    <subfield code="x" repeatable="true">
+      <description>General subdivision</description>
+    </subfield>
+    <subfield code="y" repeatable="true">
+      <description>Chronological subdivision</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Geographic subdivision</description>
+    </subfield>
+    <subfield code="0" repeatable="true">
+      <description>Record control number</description>
+    </subfield>
+    <subfield code="4" repeatable="true">
+      <description>Relationship code</description>
+    </subfield>
+    <subfield code="5" repeatable="true">
+      <description>Institution to which field applies</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="585" repeatable="true">
+    <name>See Also From Tracing-Form Subdivision</name>
+    <description>Tracing for a form subdivision reference.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="i" repeatable="true">
+      <description>Relationship information</description>
+    </subfield>
+    <subfield code="v" repeatable="true">
+      <description>Form subdivision</description>
+    </subfield>
+    <subfield code="w" repeatable="false">
+      <description>Control subfield</description>
+    </subfield>
+    <subfield code="x" repeatable="true">
+      <description>General subdivision</description>
+    </subfield>
+    <subfield code="y" repeatable="true">
+      <description>Chronological subdivision</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Geographic subdivision</description>
+    </subfield>
+    <subfield code="0" repeatable="true">
+      <description>Record control number</description>
+    </subfield>
+    <subfield code="4" repeatable="true">
+      <description>Relationship code</description>
+    </subfield>
+    <subfield code="5" repeatable="true">
+      <description>Institution to which field applies</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="640" repeatable="true">
+    <name>Series Dates of Publication and/or Sequential Designation</name>
+    <description>Beginning/ending date(s) of publication and/or sequential designations used on items in a series named in the 1XX field of an established heading record for a series. May also contain a citation for the source of the information.</description>
+    <indicator position="1" value="0">
+      <description>Formatted style</description>
+    </indicator>
+    <indicator position="1" value="1">
+      <description>Unformatted style</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Dates of publication and/or sequential designation</description>
+    </subfield>
+    <subfield code="z" repeatable="false">
+      <description>Source of information</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="641" repeatable="true">
+    <name>Series Numbering Peculiarities</name>
+    <description>Note that describes irregularities in the report year coverage and/or numbering of a series named in the 1XX field of an established heading record for a series. May also contain a citation for the source of the information.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Numbering peculiarities note</description>
+    </subfield>
+    <subfield code="z" repeatable="false">
+      <description>Source of information</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="642" repeatable="true">
+    <name>Series Numbering Example</name>
+    <description>Series numbering example that is to be followed in the sequential designation portion of a series added entry tracing in bibliographic records for individual issues of the series named in the 1XX field of an established heading record for a series. Different ranges of volumes/dates or different series numbering examples for different organizations and/or different copies or sets within the same organization are also contained in separate 642 fields.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Series numbering example</description>
+    </subfield>
+    <subfield code="d" repeatable="false">
+      <description>Volumes/dates to which series numbering example applies</description>
+    </subfield>
+    <subfield code="5" repeatable="true">
+      <description>Institution/copy to which field applies</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="643" repeatable="true">
+    <name>Series Place and Publisher/Issuing Body</name>
+    <description>Place of publication and the name of the publisher/issuing body of the series named in the 1XX field of an established heading record for a series. May also contain the volumes/dates to which the publication information applies.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="true">
+      <description>Place</description>
+    </subfield>
+    <subfield code="b" repeatable="true">
+      <description>Publisher/issuing body</description>
+    </subfield>
+    <subfield code="d" repeatable="false">
+      <description>Volumes/dates to which place and publisher/issuing body apply</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="644" repeatable="true">
+    <name>Series Analysis Practice</name>
+    <description>One-character alphabetic code that indicates a specific organization's analysis practice for a series named in the 1XX field of an established heading record for a series. May also contain the volumes/dates and/or the institution/copy identification to which the practice applies.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Series analysis practice</description>
+    </subfield>
+    <subfield code="b" repeatable="false">
+      <description>Exceptions to analysis practice</description>
+    </subfield>
+    <subfield code="d" repeatable="false">
+      <description>Volumes/dates to which analysis practice applies</description>
+    </subfield>
+    <subfield code="5" repeatable="true">
+      <description>Institution/copy to which field applies</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="645" repeatable="true">
+    <name>Series Tracing Practice</name>
+    <description>One-character alphabetic code that indicates a specific organization's tracing practice for a series named in the 1XX field of an established heading record for a series. May also contain the volumes/dates and/or the institution/copy identification to which the tracing practice applies.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Series tracing practice</description>
+    </subfield>
+    <subfield code="d" repeatable="false">
+      <description>Volumes/dates to which tracing practice applies</description>
+    </subfield>
+    <subfield code="5" repeatable="true">
+      <description>Institution/copy to which field applies</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="646" repeatable="true">
+    <name>Series Classification Practice</name>
+    <description>One-character alphabetic code that indicates a specific organization's classification practice for a series named in the 1XX field of an established heading record for a series. May also contain the volumes/dates and/or the institution/copy identification to which the classification practice applies.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Series classification practice</description>
+    </subfield>
+    <subfield code="d" repeatable="false">
+      <description>Volumes/dates to which classification practice applies</description>
+    </subfield>
+    <subfield code="5" repeatable="true">
+      <description>Institution to which field applies</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="663" repeatable="false">
+    <name>Complex See Also Reference-Name</name>
+    <description>and the that are required when relationships exist between an established name and other established names that cannot be adequately conveyed by one or more simple cross references generated from 5XX See Also From Tracing fields.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="true">
+      <description>Explanatory text</description>
+    </subfield>
+    <subfield code="b" repeatable="true">
+      <description>Heading referred to</description>
+    </subfield>
+    <subfield code="t" repeatable="true">
+      <description>Title referred to</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="664" repeatable="false">
+    <name>Complex See Reference-Name</name>
+    <description>and the that are required in a reference record for names when relationships exist between an unestablished name and one or more established names that cannot be adequately conveyed by simple cross references generated from 4XX See From Tracing fields in the established heading records.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="true">
+      <description>Explanatory text</description>
+    </subfield>
+    <subfield code="b" repeatable="true">
+      <description>Heading referred to</description>
+    </subfield>
+    <subfield code="t" repeatable="true">
+      <description>Title referred to</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="665" repeatable="false">
+    <name>History Reference</name>
+    <description>Text for reference notes with historical information for names that is used in an established heading record when more information is needed about the relationships that exist among three or more established names (usually corporate names) than can be adequately conveyed by simple cross references generated from 5XX See Also From Tracing fields in the established heading records.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="true">
+      <description>History reference</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="666" repeatable="false">
+    <name>General Explanatory Reference-Name</name>
+    <description>Note in a reference record that explains how names having a common characteristic (e.g., surnames with separately written prefixes) are entered in a file.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="true">
+      <description>General explanatory reference</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="667" repeatable="true">
+    <name>Nonpublic General Note</name>
+    <description>Note that provides general information about a 1XX heading for which a specialized note field has not been defined.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Nonpublic general note</description>
+    </subfield>
+    <subfield code="5" repeatable="true">
+      <description>Institution to which field applies</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="670" repeatable="true">
+    <name>Source Data Found</name>
+    <description>Citation for a consulted source in which information is found about the 1XX heading in an established heading record, an established heading and subdivision record, a subdivision record or a reference record. May also include the information found in the source.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Source citation</description>
+    </subfield>
+    <subfield code="b" repeatable="false">
+      <description>Information found</description>
+    </subfield>
+    <subfield code="u" repeatable="true">
+      <description>Uniform Resource Identifier</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="675" repeatable="false">
+    <name>Source Data Not Found</name>
+    <description>Citation for a consulted source in which no information is found about the 1XX heading in an established heading record, an established heading and subdivision record, or a subdivision record.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="true">
+      <description>Source citation</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="678" repeatable="true">
+    <name>Biographical or Historical Data</name>
+    <description>Summary of the essential biographical, historical, or other information about the 1XX heading in an established heading record, an established heading and subdivision record, or a subdivision record.</description>
+    <indicator position="1" value="#">
+      <description>No information provided</description>
+    </indicator>
+    <indicator position="1" value="0">
+      <description>Biographical sketch</description>
+    </indicator>
+    <indicator position="1" value="1">
+      <description>Administrative history</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="true">
+      <description>Biographical or historical data</description>
+    </subfield>
+    <subfield code="b" repeatable="false">
+      <description>Expansion</description>
+    </subfield>
+    <subfield code="u" repeatable="true">
+      <description>Uniform Resource Identifier</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="680" repeatable="true">
+    <name>Public General Note</name>
+    <description>Note that provides general information about a 1XX heading for which a specialized note field has not been defined. The note is written in a form adequate for public display.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="true">
+      <description>Heading or subdivision term</description>
+    </subfield>
+    <subfield code="i" repeatable="true">
+      <description>Explanatory text</description>
+    </subfield>
+    <subfield code="5" repeatable="true">
+      <description>Institution to which field applies</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="681" repeatable="true">
+    <name>Subject Example Tracing Note</name>
+    <description>Note that documents the use of the 1XX subject or authorized subdivision heading as an example or reference in fields 260 Complex See Reference, 360 Complex See Also Reference, and/or 680 Public General Note in another authority record.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="true">
+      <description>Subject heading or subdivision term</description>
+    </subfield>
+    <subfield code="i" repeatable="true">
+      <description>Explanatory text</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="682" repeatable="false">
+    <name>Deleted Heading Information</name>
+    <description>Explanation for the deletion of an established heading or subdivision record from an authority file. The replacement heading(s) may be contained in subfield(s) $a.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="true">
+      <description>Replacement heading</description>
+    </subfield>
+    <subfield code="i" repeatable="true">
+      <description>Explanatory text</description>
+    </subfield>
+    <subfield code="0" repeatable="true">
+      <description>Replacement authority record control number</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="688" repeatable="true">
+    <name>Application History Note</name>
+    <description>Information that documents changes in the application of a 1XX heading.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Application history note</description>
+    </subfield>
+    <subfield code="5" repeatable="true">
+      <description>Institution to which field applies</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="700" repeatable="true">
+    <name>Established Heading Linking Entry-Personal Name</name>
+    <description>Personal name heading that is equivalent to the heading contained in the 1XX field or the same record. It links headings within a system or from different thesauri or authority files.</description>
+    <indicator position="1" value="0">
+      <description>Forename</description>
+    </indicator>
+    <indicator position="1" value="1">
+      <description>Surname</description>
+    </indicator>
+    <indicator position="1" value="3">
+      <description>Family name</description>
+    </indicator>
+    <indicator position="2" value="0">
+      <description>Library of Congress Subject Headings</description>
+    </indicator>
+    <indicator position="2" value="1">
+      <description>LC subject headings for children's literature</description>
+    </indicator>
+    <indicator position="2" value="2">
+      <description>Medical Subject Headings</description>
+    </indicator>
+    <indicator position="2" value="3">
+      <description>National Agricultural Library subject authority file</description>
+    </indicator>
+    <indicator position="2" value="4">
+      <description>Source not specified</description>
+    </indicator>
+    <indicator position="2" value="5">
+      <description>Canadian Subject Headings</description>
+    </indicator>
+    <indicator position="2" value="6">
+      <description>Répertoire de vedettes-matière</description>
+    </indicator>
+    <indicator position="2" value="7">
+      <description>Source specified in subfield $2</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Personal name</description>
+    </subfield>
+    <subfield code="b" repeatable="false">
+      <description>Numeration</description>
+    </subfield>
+    <subfield code="c" repeatable="true">
+      <description>Titles and other words associated with a name</description>
+    </subfield>
+    <subfield code="d" repeatable="false">
+      <description>Dates associated with a name</description>
+    </subfield>
+    <subfield code="e" repeatable="true">
+      <description>Relator term</description>
+    </subfield>
+    <subfield code="f" repeatable="false">
+      <description>Date of a work</description>
+    </subfield>
+    <subfield code="g" repeatable="false">
+      <description>Miscellaneous information</description>
+    </subfield>
+    <subfield code="h" repeatable="false">
+      <description>Medium</description>
+    </subfield>
+    <subfield code="j" repeatable="true">
+      <description>Attribution qualifier</description>
+    </subfield>
+    <subfield code="k" repeatable="true">
+      <description>Form subheading</description>
+    </subfield>
+    <subfield code="l" repeatable="false">
+      <description>Language of a work</description>
+    </subfield>
+    <subfield code="m" repeatable="true">
+      <description>Medium of performance for music</description>
+    </subfield>
+    <subfield code="n" repeatable="true">
+      <description>Number of part/section of a work</description>
+    </subfield>
+    <subfield code="o" repeatable="false">
+      <description>Arranged statement for music</description>
+    </subfield>
+    <subfield code="p" repeatable="true">
+      <description>Name of part/section of a work</description>
+    </subfield>
+    <subfield code="q" repeatable="false">
+      <description>Fuller form of name</description>
+    </subfield>
+    <subfield code="r" repeatable="false">
+      <description>Key for music</description>
+    </subfield>
+    <subfield code="s" repeatable="false">
+      <description>Version</description>
+    </subfield>
+    <subfield code="t" repeatable="false">
+      <description>Title of a work</description>
+    </subfield>
+    <subfield code="v" repeatable="true">
+      <description>Form subdivision</description>
+    </subfield>
+    <subfield code="w" repeatable="false">
+      <description>Control subfield</description>
+    </subfield>
+    <subfield code="a" repeatable="true">
+      <description>Link not displayed</description>
+    </subfield>
+    <subfield code="b" repeatable="true">
+      <description>Link not displayed, field 788 used</description>
+    </subfield>
+    <subfield code="c" repeatable="true">
+      <description>Link not displayed, non-7XX field used</description>
+    </subfield>
+    <subfield code="n" repeatable="true">
+      <description>Not applicable</description>
+    </subfield>
+    <subfield code="a" repeatable="true">
+      <description>Heading replacement does not require review</description>
+    </subfield>
+    <subfield code="b" repeatable="true">
+      <description>Heading replacement requires review</description>
+    </subfield>
+    <subfield code="n" repeatable="true">
+      <description>Not applicable</description>
+    </subfield>
+    <subfield code="x" repeatable="true">
+      <description>General subdivision</description>
+    </subfield>
+    <subfield code="y" repeatable="true">
+      <description>Chronological subdivision</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Geographic subdivision</description>
+    </subfield>
+    <subfield code="0" repeatable="true">
+      <description>Record control number</description>
+    </subfield>
+    <subfield code="2" repeatable="false">
+      <description>Source of heading or term</description>
+    </subfield>
+    <subfield code="5" repeatable="true">
+      <description>Institution to which field applies</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="710" repeatable="true">
+    <name>Established Heading Linking Entry-Corporate Name</name>
+    <description>Corporate name that is equivalent to the name contained in the 110 field of the same record. It links headings within a system or from different thesauri or authority files.</description>
+    <indicator position="1" value="0">
+      <description>Inverted name</description>
+    </indicator>
+    <indicator position="1" value="1">
+      <description>Jurisdiction name</description>
+    </indicator>
+    <indicator position="1" value="2">
+      <description>Name in direct order</description>
+    </indicator>
+    <indicator position="2" value="0">
+      <description>Library of Congress Subject Headings</description>
+    </indicator>
+    <indicator position="2" value="1">
+      <description>LC subject headings for children's literature</description>
+    </indicator>
+    <indicator position="2" value="2">
+      <description>Medical Subject Headings</description>
+    </indicator>
+    <indicator position="2" value="3">
+      <description>National Agricultural Library subject authority file</description>
+    </indicator>
+    <indicator position="2" value="4">
+      <description>Source not specified</description>
+    </indicator>
+    <indicator position="2" value="5">
+      <description>Canadian Subject Headings</description>
+    </indicator>
+    <indicator position="2" value="6">
+      <description>Répertoire de vedettes-matière</description>
+    </indicator>
+    <indicator position="2" value="7">
+      <description>Source specified in subfield $2</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Corporate name or jurisdiction name as entry element</description>
+    </subfield>
+    <subfield code="b" repeatable="true">
+      <description>Subordinate unit</description>
+    </subfield>
+    <subfield code="c" repeatable="false">
+      <description>Location of meeting</description>
+    </subfield>
+    <subfield code="d" repeatable="true">
+      <description>Date of meeting or treaty signing</description>
+    </subfield>
+    <subfield code="e" repeatable="true">
+      <description>Relator term</description>
+    </subfield>
+    <subfield code="f" repeatable="false">
+      <description>Date of a work</description>
+    </subfield>
+    <subfield code="g" repeatable="false">
+      <description>Miscellaneous information</description>
+    </subfield>
+    <subfield code="h" repeatable="false">
+      <description>Medium</description>
+    </subfield>
+    <subfield code="k" repeatable="true">
+      <description>Form subheading</description>
+    </subfield>
+    <subfield code="l" repeatable="false">
+      <description>Language of a work</description>
+    </subfield>
+    <subfield code="m" repeatable="true">
+      <description>Medium of performance for music</description>
+    </subfield>
+    <subfield code="n" repeatable="true">
+      <description>Number of part/section/meeting</description>
+    </subfield>
+    <subfield code="o" repeatable="false">
+      <description>Arranged statement for music</description>
+    </subfield>
+    <subfield code="p" repeatable="true">
+      <description>Name of part/section of a work</description>
+    </subfield>
+    <subfield code="r" repeatable="false">
+      <description>Key for music</description>
+    </subfield>
+    <subfield code="s" repeatable="false">
+      <description>Version</description>
+    </subfield>
+    <subfield code="t" repeatable="false">
+      <description>Title of a work</description>
+    </subfield>
+    <subfield code="v" repeatable="true">
+      <description>Form subdivision</description>
+    </subfield>
+    <subfield code="w" repeatable="false">
+      <description>Control subfield</description>
+    </subfield>
+    <subfield code="a" repeatable="true">
+      <description>Link not displayed</description>
+    </subfield>
+    <subfield code="b" repeatable="true">
+      <description>Link not displayed, field 788 used</description>
+    </subfield>
+    <subfield code="c" repeatable="true">
+      <description>Link not displayed, non-7XX field used</description>
+    </subfield>
+    <subfield code="n" repeatable="true">
+      <description>Not applicable</description>
+    </subfield>
+    <subfield code="a" repeatable="true">
+      <description>Heading replacement does not require review</description>
+    </subfield>
+    <subfield code="b" repeatable="true">
+      <description>Heading replacement requires review</description>
+    </subfield>
+    <subfield code="n" repeatable="true">
+      <description>Not applicable</description>
+    </subfield>
+    <subfield code="x" repeatable="true">
+      <description>General subdivision</description>
+    </subfield>
+    <subfield code="y" repeatable="true">
+      <description>Chronological subdivision</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Geographic subdivision</description>
+    </subfield>
+    <subfield code="0" repeatable="true">
+      <description>Record control number</description>
+    </subfield>
+    <subfield code="2" repeatable="false">
+      <description>Source of heading or term</description>
+    </subfield>
+    <subfield code="5" repeatable="true">
+      <description>Institution to which field applies</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="711" repeatable="true">
+    <name>Established Heading Linking Entry-Meeting Name</name>
+    <description>Meeting name that is equivalent to the name contained in the 111 field of the same record. It links headings within a system or from different thesauri or authority files.</description>
+    <indicator position="1" value="0">
+      <description>Inverted name</description>
+    </indicator>
+    <indicator position="1" value="1">
+      <description>Jurisdiction name</description>
+    </indicator>
+    <indicator position="1" value="2">
+      <description>Name in direct order</description>
+    </indicator>
+    <indicator position="2" value="0">
+      <description>Library of Congress Subject Headings</description>
+    </indicator>
+    <indicator position="2" value="1">
+      <description>LC subject headings for children's literature</description>
+    </indicator>
+    <indicator position="2" value="2">
+      <description>Medical Subject Headings</description>
+    </indicator>
+    <indicator position="2" value="3">
+      <description>National Agricultural Library subject authority file</description>
+    </indicator>
+    <indicator position="2" value="4">
+      <description>Source not specified</description>
+    </indicator>
+    <indicator position="2" value="5">
+      <description>Canadian Subject Headings</description>
+    </indicator>
+    <indicator position="2" value="6">
+      <description>Répertoire de vedettes-matière</description>
+    </indicator>
+    <indicator position="2" value="7">
+      <description>Source specified in subfield $2</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Meeting name or jurisdiction name as entry element</description>
+    </subfield>
+    <subfield code="c" repeatable="false">
+      <description>Location of meeting</description>
+    </subfield>
+    <subfield code="d" repeatable="false">
+      <description>Date of meeting</description>
+    </subfield>
+    <subfield code="e" repeatable="true">
+      <description>Subordinate unit</description>
+    </subfield>
+    <subfield code="f" repeatable="false">
+      <description>Date of a work</description>
+    </subfield>
+    <subfield code="g" repeatable="false">
+      <description>Miscellaneous information</description>
+    </subfield>
+    <subfield code="h" repeatable="false">
+      <description>Medium</description>
+    </subfield>
+    <subfield code="j" repeatable="true">
+      <description>Relator term</description>
+    </subfield>
+    <subfield code="k" repeatable="true">
+      <description>Form subheading</description>
+    </subfield>
+    <subfield code="l" repeatable="false">
+      <description>Language of a work</description>
+    </subfield>
+    <subfield code="n" repeatable="true">
+      <description>Number of part/section/meeting</description>
+    </subfield>
+    <subfield code="p" repeatable="true">
+      <description>Name of part/section of a work</description>
+    </subfield>
+    <subfield code="q" repeatable="false">
+      <description>Name of meeting following jurisdiction name entry element</description>
+    </subfield>
+    <subfield code="s" repeatable="false">
+      <description>Version</description>
+    </subfield>
+    <subfield code="t" repeatable="false">
+      <description>Title of a work</description>
+    </subfield>
+    <subfield code="v" repeatable="true">
+      <description>Form subdivision</description>
+    </subfield>
+    <subfield code="w" repeatable="false">
+      <description>Control subfield</description>
+    </subfield>
+    <subfield code="a" repeatable="true">
+      <description>Link not displayed</description>
+    </subfield>
+    <subfield code="b" repeatable="true">
+      <description>Link not displayed, field 788 used</description>
+    </subfield>
+    <subfield code="c" repeatable="true">
+      <description>Link not displayed, non-7XX field used</description>
+    </subfield>
+    <subfield code="n" repeatable="true">
+      <description>Not applicable</description>
+    </subfield>
+    <subfield code="a" repeatable="true">
+      <description>Heading replacement does not require review</description>
+    </subfield>
+    <subfield code="b" repeatable="true">
+      <description>Heading replacement requires review</description>
+    </subfield>
+    <subfield code="n" repeatable="true">
+      <description>Not applicable</description>
+    </subfield>
+    <subfield code="x" repeatable="true">
+      <description>General subdivision</description>
+    </subfield>
+    <subfield code="y" repeatable="true">
+      <description>Chronological subdivision</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Geographic subdivision</description>
+    </subfield>
+    <subfield code="0" repeatable="true">
+      <description>Record control number</description>
+    </subfield>
+    <subfield code="2" repeatable="false">
+      <description>Source of heading or term</description>
+    </subfield>
+    <subfield code="5" repeatable="true">
+      <description>Institution to which field applies</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="730" repeatable="true">
+    <name>Established Heading Linking Entry-Uniform Title</name>
+    <description>Uniform title that is equivalent to the title contained in the 130 field of the same record. It links equivalent headings within a system or from different thesauri or authority files.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="0">
+      <description>Library of Congress Subject Headings</description>
+    </indicator>
+    <indicator position="2" value="1">
+      <description>LC subject headings for children's literature</description>
+    </indicator>
+    <indicator position="2" value="2">
+      <description>Medical Subject Headings</description>
+    </indicator>
+    <indicator position="2" value="3">
+      <description>National Agricultural Library subject authority file</description>
+    </indicator>
+    <indicator position="2" value="4">
+      <description>Source not specified</description>
+    </indicator>
+    <indicator position="2" value="5">
+      <description>Canadian Subject Headings</description>
+    </indicator>
+    <indicator position="2" value="6">
+      <description>Répertoire de vedettes-matière</description>
+    </indicator>
+    <indicator position="2" value="7">
+      <description>Source specified in subfield $2</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Uniform title</description>
+    </subfield>
+    <subfield code="d" repeatable="true">
+      <description>Date of treaty signing</description>
+    </subfield>
+    <subfield code="f" repeatable="false">
+      <description>Date of a work</description>
+    </subfield>
+    <subfield code="g" repeatable="false">
+      <description>Miscellaneous information</description>
+    </subfield>
+    <subfield code="h" repeatable="false">
+      <description>Medium</description>
+    </subfield>
+    <subfield code="k" repeatable="true">
+      <description>Form subheading</description>
+    </subfield>
+    <subfield code="l" repeatable="false">
+      <description>Language of a work</description>
+    </subfield>
+    <subfield code="m" repeatable="true">
+      <description>Medium of performance for music</description>
+    </subfield>
+    <subfield code="n" repeatable="true">
+      <description>Number of part/section of a work</description>
+    </subfield>
+    <subfield code="o" repeatable="false">
+      <description>Arranged statement for music</description>
+    </subfield>
+    <subfield code="p" repeatable="true">
+      <description>Name of part/section of a work</description>
+    </subfield>
+    <subfield code="r" repeatable="false">
+      <description>Key for music</description>
+    </subfield>
+    <subfield code="s" repeatable="false">
+      <description>Version</description>
+    </subfield>
+    <subfield code="t" repeatable="false">
+      <description>Title of a work</description>
+    </subfield>
+    <subfield code="v" repeatable="true">
+      <description>Form subdivision</description>
+    </subfield>
+    <subfield code="w" repeatable="false">
+      <description>Control subfield</description>
+    </subfield>
+    <subfield code="a" repeatable="true">
+      <description>Link not displayed</description>
+    </subfield>
+    <subfield code="b" repeatable="true">
+      <description>Link not displayed, field 788 used</description>
+    </subfield>
+    <subfield code="c" repeatable="true">
+      <description>Link not displayed, non-7XX field used</description>
+    </subfield>
+    <subfield code="n" repeatable="true">
+      <description>Not applicable</description>
+    </subfield>
+    <subfield code="a" repeatable="true">
+      <description>Heading replacement does not require review</description>
+    </subfield>
+    <subfield code="b" repeatable="true">
+      <description>Heading replacement requires review</description>
+    </subfield>
+    <subfield code="n" repeatable="true">
+      <description>Not applicable</description>
+    </subfield>
+    <subfield code="x" repeatable="true">
+      <description>General subdivision</description>
+    </subfield>
+    <subfield code="y" repeatable="true">
+      <description>Chronological subdivision</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Geographic subdivision</description>
+    </subfield>
+    <subfield code="0" repeatable="true">
+      <description>Record control number</description>
+    </subfield>
+    <subfield code="2" repeatable="false">
+      <description>Source of heading or term</description>
+    </subfield>
+    <subfield code="5" repeatable="true">
+      <description>Institution to which field applies</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="748" repeatable="true">
+    <name>Established Heading Linking Entry-Chronological Term</name>
+    <description>Chronological term that is equivalent to the 148 chronological term or 182 chronological subdivision heading field of the same record. It links headings within a system or from different thesauri or authority files.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="0">
+      <description>Library of Congress Subject Headings</description>
+    </indicator>
+    <indicator position="2" value="1">
+      <description>LC subject headings for children's literature</description>
+    </indicator>
+    <indicator position="2" value="2">
+      <description>Medical Subject Headings</description>
+    </indicator>
+    <indicator position="2" value="3">
+      <description>National Agricultural Library subject authority file</description>
+    </indicator>
+    <indicator position="2" value="4">
+      <description>Source not specified</description>
+    </indicator>
+    <indicator position="2" value="5">
+      <description>Canadian Subject Headings</description>
+    </indicator>
+    <indicator position="2" value="6">
+      <description>Répertoire de vedettes-matière</description>
+    </indicator>
+    <indicator position="2" value="7">
+      <description>Source specified in subfield $2</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Chronological term</description>
+    </subfield>
+    <subfield code="v" repeatable="true">
+      <description>Form subdivision</description>
+    </subfield>
+    <subfield code="w" repeatable="false">
+      <description>Control subfield</description>
+    </subfield>
+    <subfield code="a" repeatable="true">
+      <description>Link not displayed</description>
+    </subfield>
+    <subfield code="b" repeatable="true">
+      <description>Link not displayed, field 788 used</description>
+    </subfield>
+    <subfield code="c" repeatable="true">
+      <description>Link not displayed, non-7XX field used</description>
+    </subfield>
+    <subfield code="n" repeatable="true">
+      <description>Not applicable</description>
+    </subfield>
+    <subfield code="a" repeatable="true">
+      <description>Heading replacement does not require review</description>
+    </subfield>
+    <subfield code="b" repeatable="true">
+      <description>Heading replacement requires review</description>
+    </subfield>
+    <subfield code="n" repeatable="true">
+      <description>Not applicable</description>
+    </subfield>
+    <subfield code="x" repeatable="true">
+      <description>General subdivision</description>
+    </subfield>
+    <subfield code="y" repeatable="true">
+      <description>Chronological subdivision</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Geographic subdivision</description>
+    </subfield>
+    <subfield code="0" repeatable="true">
+      <description>Record control number</description>
+    </subfield>
+    <subfield code="2" repeatable="false">
+      <description>Source of heading or term</description>
+    </subfield>
+    <subfield code="5" repeatable="true">
+      <description>Institution to which field applies</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="750" repeatable="true">
+    <name>Established Heading Linking Entry-Topical Term</name>
+    <description>Topical term that is equivalent to the 150 topical term or 180 general subdivision heading field of the same record. It links headings within a system or from different thesauri or authority files.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="0">
+      <description>Library of Congress Subject Headings</description>
+    </indicator>
+    <indicator position="2" value="1">
+      <description>LC subject headings for children's literature</description>
+    </indicator>
+    <indicator position="2" value="2">
+      <description>Medical Subject Headings</description>
+    </indicator>
+    <indicator position="2" value="3">
+      <description>National Agricultural Library subject authority file</description>
+    </indicator>
+    <indicator position="2" value="4">
+      <description>Source not specified</description>
+    </indicator>
+    <indicator position="2" value="5">
+      <description>Canadian Subject Headings</description>
+    </indicator>
+    <indicator position="2" value="6">
+      <description>Répertoire de vedettes-matière</description>
+    </indicator>
+    <indicator position="2" value="7">
+      <description>Source specified in subfield $2</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Topical term or geographic name entry element</description>
+    </subfield>
+    <subfield code="b" repeatable="false">
+      <description>Topical term following geographic name entry element</description>
+    </subfield>
+    <subfield code="v" repeatable="true">
+      <description>Form subdivision</description>
+    </subfield>
+    <subfield code="w" repeatable="false">
+      <description>Control subfield</description>
+    </subfield>
+    <subfield code="a" repeatable="true">
+      <description>Link not displayed</description>
+    </subfield>
+    <subfield code="b" repeatable="true">
+      <description>Link not displayed, field 788 used</description>
+    </subfield>
+    <subfield code="c" repeatable="true">
+      <description>Link not displayed, non-7XX field used</description>
+    </subfield>
+    <subfield code="n" repeatable="true">
+      <description>Not applicable</description>
+    </subfield>
+    <subfield code="a" repeatable="true">
+      <description>Heading replacement does not require review</description>
+    </subfield>
+    <subfield code="b" repeatable="true">
+      <description>Heading replacement requires review</description>
+    </subfield>
+    <subfield code="n" repeatable="true">
+      <description>Not applicable</description>
+    </subfield>
+    <subfield code="x" repeatable="true">
+      <description>General subdivision</description>
+    </subfield>
+    <subfield code="y" repeatable="true">
+      <description>Chronological subdivision</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Geographic subdivision</description>
+    </subfield>
+    <subfield code="0" repeatable="true">
+      <description>Record control number</description>
+    </subfield>
+    <subfield code="2" repeatable="false">
+      <description>Source of heading or term</description>
+    </subfield>
+    <subfield code="5" repeatable="true">
+      <description>Institution to which field applies</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="751" repeatable="true">
+    <name>Established Heading Linking Entry-Geographic Name</name>
+    <description>Geographic name that is equivalent to the 151 geographic name or 181 geographic subdivision field of the same record. It links headings within a system or from different thesauri or authority files.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="0">
+      <description>Library of Congress Subject Headings</description>
+    </indicator>
+    <indicator position="2" value="1">
+      <description>LC subject headings for children's literature</description>
+    </indicator>
+    <indicator position="2" value="2">
+      <description>Medical Subject Headings</description>
+    </indicator>
+    <indicator position="2" value="3">
+      <description>National Agricultural Library subject authority file</description>
+    </indicator>
+    <indicator position="2" value="4">
+      <description>Source not specified</description>
+    </indicator>
+    <indicator position="2" value="5">
+      <description>Canadian Subject Headings</description>
+    </indicator>
+    <indicator position="2" value="6">
+      <description>Répertoire de vedettes-matière</description>
+    </indicator>
+    <indicator position="2" value="7">
+      <description>Source specified in subfield $2</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Geographic name</description>
+    </subfield>
+    <subfield code="v" repeatable="true">
+      <description>Form subdivision</description>
+    </subfield>
+    <subfield code="w" repeatable="false">
+      <description>Control subfield</description>
+    </subfield>
+    <subfield code="a" repeatable="true">
+      <description>Link not displayed</description>
+    </subfield>
+    <subfield code="b" repeatable="true">
+      <description>Link not displayed, field 788 used</description>
+    </subfield>
+    <subfield code="c" repeatable="true">
+      <description>Link not displayed, non-7XX field used</description>
+    </subfield>
+    <subfield code="n" repeatable="true">
+      <description>Not applicable</description>
+    </subfield>
+    <subfield code="a" repeatable="true">
+      <description>Heading replacement does not require review</description>
+    </subfield>
+    <subfield code="b" repeatable="true">
+      <description>Heading replacement requires review</description>
+    </subfield>
+    <subfield code="n" repeatable="true">
+      <description>Not applicable</description>
+    </subfield>
+    <subfield code="x" repeatable="true">
+      <description>General subdivision</description>
+    </subfield>
+    <subfield code="y" repeatable="true">
+      <description>Chronological subdivision</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Geographic subdivision</description>
+    </subfield>
+    <subfield code="0" repeatable="true">
+      <description>Record control number</description>
+    </subfield>
+    <subfield code="2" repeatable="false">
+      <description>Source of heading or term</description>
+    </subfield>
+    <subfield code="5" repeatable="true">
+      <description>Institution to which field applies</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="755" repeatable="true">
+    <name>Established Heading Linking Entry-Genre/Form Term</name>
+    <description>Genre/form term that is equivalent to the 155 genre/form term or 185 form subdivision heading field of the same record. It links headings within a system or from different thesauri or authority files.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="0">
+      <description>Library of Congress Subject Headings</description>
+    </indicator>
+    <indicator position="2" value="1">
+      <description>LC subject headings for children's literature</description>
+    </indicator>
+    <indicator position="2" value="2">
+      <description>Medical Subject Headings</description>
+    </indicator>
+    <indicator position="2" value="3">
+      <description>National Agricultural Library subject authority file</description>
+    </indicator>
+    <indicator position="2" value="4">
+      <description>Source not specified</description>
+    </indicator>
+    <indicator position="2" value="5">
+      <description>Canadian Subject Headings</description>
+    </indicator>
+    <indicator position="2" value="6">
+      <description>Répertoire de vedettes-matière</description>
+    </indicator>
+    <indicator position="2" value="7">
+      <description>Source specified in subfield $2</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Genre/form term as entry element</description>
+    </subfield>
+    <subfield code="v" repeatable="true">
+      <description>Form subdivision</description>
+    </subfield>
+    <subfield code="w" repeatable="false">
+      <description>Control subfield</description>
+    </subfield>
+    <subfield code="a" repeatable="true">
+      <description>Link not displayed</description>
+    </subfield>
+    <subfield code="b" repeatable="true">
+      <description>Link not displayed, field 788 used</description>
+    </subfield>
+    <subfield code="c" repeatable="true">
+      <description>Link not displayed, non-7XX field used</description>
+    </subfield>
+    <subfield code="n" repeatable="true">
+      <description>Not applicable</description>
+    </subfield>
+    <subfield code="a" repeatable="true">
+      <description>Heading replacement does not require review</description>
+    </subfield>
+    <subfield code="b" repeatable="true">
+      <description>Heading replacement requires review</description>
+    </subfield>
+    <subfield code="n" repeatable="true">
+      <description>Not applicable</description>
+    </subfield>
+    <subfield code="x" repeatable="true">
+      <description>General subdivision</description>
+    </subfield>
+    <subfield code="y" repeatable="true">
+      <description>Chronological subdivision</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Geographic subdivision</description>
+    </subfield>
+    <subfield code="0" repeatable="true">
+      <description>Record control number</description>
+    </subfield>
+    <subfield code="2" repeatable="false">
+      <description>Source of heading or term</description>
+    </subfield>
+    <subfield code="5" repeatable="true">
+      <description>Institution to which field applies</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="780" repeatable="true">
+    <name>Subdivision Linking Entry-General Subdivision</name>
+    <description>General subdivision term that is equivalent to the 150 topical term or 180 general subdivision field of the same record. It links headings within a system or from different thesauri or authority files.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="0">
+      <description>Library of Congress Subject Headings</description>
+    </indicator>
+    <indicator position="2" value="1">
+      <description>LC subject headings for children's literature</description>
+    </indicator>
+    <indicator position="2" value="2">
+      <description>Medical Subject Headings</description>
+    </indicator>
+    <indicator position="2" value="3">
+      <description>National Agricultural Library subject authority file</description>
+    </indicator>
+    <indicator position="2" value="4">
+      <description>Source not specified</description>
+    </indicator>
+    <indicator position="2" value="5">
+      <description>Canadian Subject Headings</description>
+    </indicator>
+    <indicator position="2" value="6">
+      <description>Répertoire de vedettes-matière</description>
+    </indicator>
+    <indicator position="2" value="7">
+      <description>Source specified in subfield $2</description>
+    </indicator>
+    <subfield code="v" repeatable="true">
+      <description>Form subdivision</description>
+    </subfield>
+    <subfield code="w" repeatable="false">
+      <description>Control subfield</description>
+    </subfield>
+    <subfield code="a" repeatable="true">
+      <description>Link not displayed</description>
+    </subfield>
+    <subfield code="b" repeatable="true">
+      <description>Link not displayed, field 788 used</description>
+    </subfield>
+    <subfield code="c" repeatable="true">
+      <description>Link not displayed, non-7XX field used</description>
+    </subfield>
+    <subfield code="n" repeatable="true">
+      <description>Not applicable</description>
+    </subfield>
+    <subfield code="a" repeatable="true">
+      <description>Heading replacement does not require review</description>
+    </subfield>
+    <subfield code="b" repeatable="true">
+      <description>Heading replacement requires review</description>
+    </subfield>
+    <subfield code="n" repeatable="true">
+      <description>Not applicable</description>
+    </subfield>
+    <subfield code="x" repeatable="true">
+      <description>General subdivision</description>
+    </subfield>
+    <subfield code="y" repeatable="true">
+      <description>Chronological subdivision</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Geographic subdivision</description>
+    </subfield>
+    <subfield code="0" repeatable="true">
+      <description>Record control number</description>
+    </subfield>
+    <subfield code="2" repeatable="false">
+      <description>Source of heading or term</description>
+    </subfield>
+    <subfield code="5" repeatable="true">
+      <description>Institution to which field applies</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="781" repeatable="true">
+    <name>Subdivision Linking Entry-Geographic Subdivision</name>
+    <description>Geographic subdivision name that is equivalent to the 151 geographic name or 181 geographic subdivision field of the same record. It links headings within a system or from different thesauri or authority files.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="0">
+      <description>Library of Congress Subject Headings</description>
+    </indicator>
+    <indicator position="2" value="1">
+      <description>LC subject headings for children's literature</description>
+    </indicator>
+    <indicator position="2" value="2">
+      <description>Medical Subject Headings</description>
+    </indicator>
+    <indicator position="2" value="3">
+      <description>National Agricultural Library subject authority file</description>
+    </indicator>
+    <indicator position="2" value="4">
+      <description>Source not specified</description>
+    </indicator>
+    <indicator position="2" value="5">
+      <description>Canadian Subject Headings</description>
+    </indicator>
+    <indicator position="2" value="6">
+      <description>Répertoire de vedettes-matière</description>
+    </indicator>
+    <indicator position="2" value="7">
+      <description>Source specified in subfield $2</description>
+    </indicator>
+    <subfield code="v" repeatable="true">
+      <description>Form subdivision</description>
+    </subfield>
+    <subfield code="w" repeatable="false">
+      <description>Control subfield</description>
+    </subfield>
+    <subfield code="a" repeatable="true">
+      <description>Link not displayed</description>
+    </subfield>
+    <subfield code="b" repeatable="true">
+      <description>Link not displayed, field 788 used</description>
+    </subfield>
+    <subfield code="c" repeatable="true">
+      <description>Link not displayed, non-7XX field used</description>
+    </subfield>
+    <subfield code="n" repeatable="true">
+      <description>Not applicable</description>
+    </subfield>
+    <subfield code="a" repeatable="true">
+      <description>Heading replacement does not require review</description>
+    </subfield>
+    <subfield code="b" repeatable="true">
+      <description>Heading replacement requires review</description>
+    </subfield>
+    <subfield code="n" repeatable="true">
+      <description>Not applicable</description>
+    </subfield>
+    <subfield code="x" repeatable="true">
+      <description>General subdivision</description>
+    </subfield>
+    <subfield code="y" repeatable="true">
+      <description>Chronological subdivision</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Geographic subdivision</description>
+    </subfield>
+    <subfield code="0" repeatable="true">
+      <description>Record control number</description>
+    </subfield>
+    <subfield code="2" repeatable="false">
+      <description>Source of heading or term</description>
+    </subfield>
+    <subfield code="5" repeatable="true">
+      <description>Institution to which field applies</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="782" repeatable="true">
+    <name>Subdivision Linking Entry-Chronological Subdivision</name>
+    <description>Chronological subdivision term that is equivalent to the 150 topical term or 182 chronological subdivision field of the same record. It links headings within a system or from different thesauri or authority files.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="0">
+      <description>Library of Congress Subject Headings</description>
+    </indicator>
+    <indicator position="2" value="1">
+      <description>LC subject headings for children's literature</description>
+    </indicator>
+    <indicator position="2" value="2">
+      <description>Medical Subject Headings</description>
+    </indicator>
+    <indicator position="2" value="3">
+      <description>National Agricultural Library subject authority file</description>
+    </indicator>
+    <indicator position="2" value="4">
+      <description>Source not specified</description>
+    </indicator>
+    <indicator position="2" value="5">
+      <description>Canadian Subject Headings</description>
+    </indicator>
+    <indicator position="2" value="6">
+      <description>Répertoire de vedettes-matière</description>
+    </indicator>
+    <indicator position="2" value="7">
+      <description>Source specified in subfield $2</description>
+    </indicator>
+    <subfield code="v" repeatable="true">
+      <description>Form subdivision</description>
+    </subfield>
+    <subfield code="w" repeatable="false">
+      <description>Control subfield</description>
+    </subfield>
+    <subfield code="a" repeatable="true">
+      <description>Link not displayed</description>
+    </subfield>
+    <subfield code="b" repeatable="true">
+      <description>Link not displayed, field 788 used</description>
+    </subfield>
+    <subfield code="c" repeatable="true">
+      <description>Link not displayed, non-7XX field used</description>
+    </subfield>
+    <subfield code="n" repeatable="true">
+      <description>Not applicable</description>
+    </subfield>
+    <subfield code="a" repeatable="true">
+      <description>Heading replacement does not require review</description>
+    </subfield>
+    <subfield code="b" repeatable="true">
+      <description>Heading replacement requires review</description>
+    </subfield>
+    <subfield code="n" repeatable="true">
+      <description>Not applicable</description>
+    </subfield>
+    <subfield code="x" repeatable="true">
+      <description>General subdivision</description>
+    </subfield>
+    <subfield code="y" repeatable="true">
+      <description>Chronological subdivision</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Geographic subdivision</description>
+    </subfield>
+    <subfield code="0" repeatable="true">
+      <description>Record control number</description>
+    </subfield>
+    <subfield code="2" repeatable="false">
+      <description>Source of heading or term</description>
+    </subfield>
+    <subfield code="5" repeatable="true">
+      <description>Institution to which field applies</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="785" repeatable="true">
+    <name>Subdivision Linking Entry-Form Subdivision</name>
+    <description>Form subdivision term that is equivalent to the 155 genre/form or 185 form subdivision field of the same record. It links headings within a system or from different thesauri or authority files.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="0">
+      <description>Library of Congress Subject Headings</description>
+    </indicator>
+    <indicator position="2" value="1">
+      <description>LC subject headings for children's literature</description>
+    </indicator>
+    <indicator position="2" value="2">
+      <description>Medical Subject Headings</description>
+    </indicator>
+    <indicator position="2" value="3">
+      <description>National Agricultural Library subject authority file</description>
+    </indicator>
+    <indicator position="2" value="4">
+      <description>Source not specified</description>
+    </indicator>
+    <indicator position="2" value="5">
+      <description>Canadian Subject Headings</description>
+    </indicator>
+    <indicator position="2" value="6">
+      <description>Répertoire de vedettes-matière</description>
+    </indicator>
+    <indicator position="2" value="7">
+      <description>Source specified in subfield $2</description>
+    </indicator>
+    <subfield code="v" repeatable="true">
+      <description>Form subdivision</description>
+    </subfield>
+    <subfield code="w" repeatable="false">
+      <description>Control subfield</description>
+    </subfield>
+    <subfield code="a" repeatable="true">
+      <description>Link not displayed</description>
+    </subfield>
+    <subfield code="b" repeatable="true">
+      <description>Link not displayed, field 788 used</description>
+    </subfield>
+    <subfield code="c" repeatable="true">
+      <description>Link not displayed, non-7XX field used</description>
+    </subfield>
+    <subfield code="n" repeatable="true">
+      <description>Not applicable</description>
+    </subfield>
+    <subfield code="a" repeatable="true">
+      <description>Heading replacement does not require review</description>
+    </subfield>
+    <subfield code="b" repeatable="true">
+      <description>Heading replacement requires review</description>
+    </subfield>
+    <subfield code="n" repeatable="true">
+      <description>Not applicable</description>
+    </subfield>
+    <subfield code="x" repeatable="true">
+      <description>General subdivision</description>
+    </subfield>
+    <subfield code="y" repeatable="true">
+      <description>Chronological subdivision</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Geographic subdivision</description>
+    </subfield>
+    <subfield code="0" repeatable="true">
+      <description>Record control number</description>
+    </subfield>
+    <subfield code="2" repeatable="false">
+      <description>Source of heading or term</description>
+    </subfield>
+    <subfield code="5" repeatable="true">
+      <description>Institution to which field applies</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="788" repeatable="false">
+    <name>Complex Linking Entry Data</name>
+    <description>Explanatory text and the headings referred to when the linking relationship between headings from different subject heading systems or thesauri cannot be adequately conveyed by fields 700-785. No subelements of the are separately subfield coded. Adjacent headings referred to may be contained in a single subfield $a. The heading referred to may be an established heading or a subject subdivision that is not equivalent to but is related to the heading in the 1XX field.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="0">
+      <description>Library of Congress Subject Headings</description>
+    </indicator>
+    <indicator position="2" value="1">
+      <description>LC subject headings for children's literature</description>
+    </indicator>
+    <indicator position="2" value="2">
+      <description>Medical Subject Headings</description>
+    </indicator>
+    <indicator position="2" value="3">
+      <description>National Agricultural Library subject authority file</description>
+    </indicator>
+    <indicator position="2" value="4">
+      <description>Source not specified</description>
+    </indicator>
+    <indicator position="2" value="5">
+      <description>Canadian Subject Headings</description>
+    </indicator>
+    <indicator position="2" value="6">
+      <description>Répertoire de vedettes-matière</description>
+    </indicator>
+    <indicator position="2" value="7">
+      <description>Source specified in subfield $2</description>
+    </indicator>
+    <subfield code="a" repeatable="true">
+      <description>Heading referred to</description>
+    </subfield>
+    <subfield code="i" repeatable="true">
+      <description>Explanatory text</description>
+    </subfield>
+    <subfield code="2" repeatable="false">
+      <description>Source of heading or term</description>
+    </subfield>
+    <subfield code="5" repeatable="true">
+      <description>Institution to which field applies</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="856" repeatable="true">
+    <name>Electronic Location and Access</name>
+    <description>Information needed to locate and access electronic information. The field may be used in an authority record to provide supplementary information available electronically about the entity for which the record was created.</description>
+    <indicator position="1" value="#">
+      <description>No information provided</description>
+    </indicator>
+    <indicator position="1" value="0">
+      <description>Email</description>
+    </indicator>
+    <indicator position="1" value="1">
+      <description>FTP</description>
+    </indicator>
+    <indicator position="1" value="2">
+      <description>Remote login (Telnet)</description>
+    </indicator>
+    <indicator position="1" value="3">
+      <description>Dial-up</description>
+    </indicator>
+    <indicator position="1" value="4">
+      <description>HTTP</description>
+    </indicator>
+    <indicator position="1" value="7">
+      <description>Method specified in subfield $2</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>No information provided</description>
+    </indicator>
+    <indicator position="2" value="0">
+      <description>Resource</description>
+    </indicator>
+    <indicator position="2" value="1">
+      <description>Version of resource</description>
+    </indicator>
+    <indicator position="2" value="2">
+      <description>Related resource</description>
+    </indicator>
+    <indicator position="2" value="8">
+      <description>No display constant generated</description>
+    </indicator>
+    <subfield code="a" repeatable="true">
+      <description>Host name</description>
+    </subfield>
+    <subfield code="b" repeatable="true">
+      <description>Access number</description>
+    </subfield>
+    <subfield code="c" repeatable="true">
+      <description>Compression information</description>
+    </subfield>
+    <subfield code="d" repeatable="true">
+      <description>Path</description>
+    </subfield>
+    <subfield code="f" repeatable="true">
+      <description>Electronic name</description>
+    </subfield>
+    <subfield code="h" repeatable="false">
+      <description>Processor of request</description>
+    </subfield>
+    <subfield code="i" repeatable="true">
+      <description>Instruction</description>
+    </subfield>
+    <subfield code="j" repeatable="false">
+      <description>Bits per second</description>
+    </subfield>
+    <subfield code="k" repeatable="false">
+      <description>Password</description>
+    </subfield>
+    <subfield code="l" repeatable="false">
+      <description>Logon</description>
+    </subfield>
+    <subfield code="m" repeatable="true">
+      <description>Contact for access assistance</description>
+    </subfield>
+    <subfield code="n" repeatable="false">
+      <description>Name of location of host</description>
+    </subfield>
+    <subfield code="o" repeatable="false">
+      <description>Operating system</description>
+    </subfield>
+    <subfield code="p" repeatable="false">
+      <description>Port</description>
+    </subfield>
+    <subfield code="q" repeatable="false">
+      <description>Electronic format type</description>
+    </subfield>
+    <subfield code="r" repeatable="false">
+      <description>Settings</description>
+    </subfield>
+    <subfield code="s" repeatable="true">
+      <description>File size</description>
+    </subfield>
+    <subfield code="t" repeatable="true">
+      <description>Terminal emulation</description>
+    </subfield>
+    <subfield code="u" repeatable="true">
+      <description>Uniform Resource Identifier</description>
+    </subfield>
+    <subfield code="v" repeatable="true">
+      <description>Hours access method available</description>
+    </subfield>
+    <subfield code="w" repeatable="true">
+      <description>Record control number</description>
+    </subfield>
+    <subfield code="x" repeatable="true">
+      <description>Nonpublic note</description>
+    </subfield>
+    <subfield code="y" repeatable="true">
+      <description>Link text</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Public note</description>
+    </subfield>
+    <subfield code="2" repeatable="false">
+      <description>Access method</description>
+    </subfield>
+    <subfield code="3" repeatable="false">
+      <description>Materials specified</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="880" repeatable="true">
+    <name>Alternate Graphic Representation</name>
+    <description>Full content-designated representation, in a different script, of another field in the same record. Field 880 is linked to the associated regular field by subfield $6 (Linkage). A subfield $6 in the associated field also links that field to the 880 field. The data in field 880 may be in more than one script.</description>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+  </field>
+</fields>

Copied: branches/serials-integration/Open-ILS/xul/staff_client/server/locale/en-US/marcedit-tooltips-mfhd.xml (from rev 17886, trunk/Open-ILS/xul/staff_client/server/locale/en-US/marcedit-tooltips-mfhd.xml)
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/server/locale/en-US/marcedit-tooltips-mfhd.xml	                        (rev 0)
+++ branches/serials-integration/Open-ILS/xul/staff_client/server/locale/en-US/marcedit-tooltips-mfhd.xml	2010-10-18 13:46:56 UTC (rev 18371)
@@ -0,0 +1,2063 @@
+<?xml version="1.0"?>
+<fields>
+  <field tag="001" repeatable="false">
+    <name>Control Number</name>
+    <description>System control number assigned to a separate holdings record. For interchange purposes, documentation of the structure of the control number and input conventions are provided to exchange partners by the organization initiating the interchange.</description>
+  </field>
+  <field tag="003" repeatable="false">
+    <name>Control Number Identifier</name>
+    <description>MARC code for the agency whose system control number is present in field 001 (Control Number).</description>
+  </field>
+  <field tag="004" repeatable="false">
+    <name>Control Number for Related Bibliographic Record</name>
+    <description>System control number of the MARC bibliographic record for which a separate holdings record was created.</description>
+  </field>
+  <field tag="005" repeatable="false">
+    <name>Date and Time of Latest Transaction</name>
+    <description>Sixteen characters that specify the date and time of the latest record transaction and serve as a version identifier for the record. They are recorded according to (ISO 8601). The date requires 8 numeric characters in the pattern (4 for the year, 2 for the month, and 2 for the day). The time requires 8 numeric characters in the pattern (2 for the hour, 2 for the minute, 2 for the second, and 2 for a decimal fraction of the second, including the decimal point)expressed in terms of the 24-hour (00-23) clock.</description>
+  </field>
+  <field tag="007" repeatable="false">
+    <name>Physical Description Fixed Field</name>
+    <description>Codes that describe the physical characteristics of the copy of the bibliographic item for which holdings are recorded. See the description of in the for complete character position definitions and the content designators defined for this field. The Category of material code (007/00) may be described textually in field 842 (Textual Physical Form Designator).</description>
+  </field>
+  <field tag="008" repeatable="false">
+    <name>Fixed-Length Data Elements-General Information</name>
+    <description>Thirty-two character positions (00-31) that contain data elements that provide coded information about the record. The data elements are positionally defined. Each defined character position must contain either a defined code or a fill character ( | ). The fill character is used when no attempt is made to supply a defined code for a specific character position.</description>
+  </field>
+  <field tag="010" repeatable="false">
+    <name>Library of Congress Control Number</name>
+    <description>Control number, assigned by the Library of Congress, of the related MARC bibliographic record for which a separate holdings record is made.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>LC control number</description>
+    </subfield>
+    <subfield code="b" repeatable="true">
+      <description>NUCMC control number</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Canceled or invalid LC control number</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="014" repeatable="true">
+    <name>Linkage Number</name>
+    <description>Control number, assigned by a bibliographic network, of a separate holdings record or its related bibliographic record for which a separate holdings record is made.</description>
+    <indicator position="1" value="0">
+      <description>Holdings record number</description>
+    </indicator>
+    <indicator position="1" value="1">
+      <description>Bibliographic record number</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Linkage number</description>
+    </subfield>
+    <subfield code="b" repeatable="false">
+      <description>Source of number</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Canceled or invalid linkage number</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+  </field>
+  <field tag="016" repeatable="true">
+    <name>National Bibliographic Agency Control Number</name>
+    <description>Control number, assigned by a national bibliographic agency other than the Library of Congress, of the related bibliographic record for which a separate holdings record is made.</description>
+    <indicator position="1" value="#">
+      <description>Library and Archives Canada</description>
+    </indicator>
+    <indicator position="1" value="7">
+      <description>Source specified in subfield $2</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Record control number</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Canceled or invalid control number</description>
+    </subfield>
+    <subfield code="2" repeatable="false">
+      <description>Source</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="017" repeatable="true">
+    <name>Copyright or Legal Deposit Number</name>
+    <description>Copyright registration or legal deposit number for an item that was acquired by copyright or legal deposit.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Copyright or legal deposit number</description>
+    </indicator>
+    <indicator position="2" value="8">
+      <description>No display constant generated</description>
+    </indicator>
+    <subfield code="a" repeatable="true">
+      <description>Copyright or legal deposit number</description>
+    </subfield>
+    <subfield code="b" repeatable="false">
+      <description>Assigning agency</description>
+    </subfield>
+    <subfield code="d" repeatable="false">
+      <description>Date</description>
+    </subfield>
+    <subfield code="i" repeatable="false">
+      <description>Display text</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Canceled/invalid copyright or legal deposit number</description>
+    </subfield>
+    <subfield code="2" repeatable="false">
+      <description>Source</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="020" repeatable="true">
+    <name>International Standard Book Number</name>
+    <description>International Standard Book Number (ISBN) copied from subfield $a of field 020 (International Standard Book Number) of the MARC bibliographic record that represents the description of the item for which a separate holdings record is created.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>International Standard Book Number</description>
+    </subfield>
+    <subfield code="c" repeatable="false">
+      <description>Terms of availability</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Canceled/invalid ISBN</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="022" repeatable="true">
+    <name>International Standard Serial Number</name>
+    <description>International Standard Serial Number (ISSN) copied from subfield $a of field 022 (International Standard Serial Number) of the MARC bibliographic record that represents the description of the item for which a separate holdings record is created.</description>
+    <indicator position="1" value="#">
+      <description>No level specified</description>
+    </indicator>
+    <indicator position="1" value="0">
+      <description>Continuing resource of international interest</description>
+    </indicator>
+    <indicator position="1" value="1">
+      <description>Continuing resource not of international interest</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>International Standard Serial Number</description>
+    </subfield>
+    <subfield code="l" repeatable="false">
+      <description>ISSN-L</description>
+    </subfield>
+    <subfield code="m" repeatable="true">
+      <description>Canceled ISSN-L</description>
+    </subfield>
+    <subfield code="y" repeatable="true">
+      <description>Incorrect ISSN</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Canceled ISSN</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="024" repeatable="true">
+    <name>Other Standard Identifier</name>
+    <description>Standard number or code published on an item which cannot be accommodated in another field (e.g., field 020 (International Standard Book Number), 022 (International Standard Serial Number), 027 (Standard Technical Report Number)). The type of standard number or code is identified in the first indicator position or in subfield $2 (Source of number or code).</description>
+    <indicator position="1" value="0">
+      <description>International Standard Recording Code</description>
+    </indicator>
+    <indicator position="1" value="1">
+      <description>Universal Product Code</description>
+    </indicator>
+    <indicator position="1" value="2">
+      <description>International Standard Music Number</description>
+    </indicator>
+    <indicator position="1" value="3">
+      <description>International Article Number</description>
+    </indicator>
+    <indicator position="1" value="4">
+      <description>Serial Item and Contribution Identifier</description>
+    </indicator>
+    <indicator position="1" value="7">
+      <description>Source specified in subfield $2</description>
+    </indicator>
+    <indicator position="1" value="8">
+      <description>Unspecified type of standard number or code</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>No information provided</description>
+    </indicator>
+    <indicator position="2" value="0">
+      <description>No difference</description>
+    </indicator>
+    <indicator position="2" value="1">
+      <description>Difference</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Standard number or code</description>
+    </subfield>
+    <subfield code="c" repeatable="false">
+      <description>Terms of availability</description>
+    </subfield>
+    <subfield code="d" repeatable="false">
+      <description>Additional codes following the standard number or code</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Canceled/invalid standard number or code</description>
+    </subfield>
+    <subfield code="2" repeatable="false">
+      <description>Source of number or code</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="027" repeatable="true">
+    <name>Standard Technical Report Number</name>
+    <description>International Standard Technical Report number (ISRN) or a Standard Technical Report Number (STRN) copied from subfield $a of field 027 of the MARC bibliographic record that represents the description of the item for which a separate holdings record is created.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Standard Technical Report Number</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Canceled/invalid STRN</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="030" repeatable="false">
+    <name>CODEN Designation</name>
+    <description>CODEN designation, a unique identifier for scientific and technical periodical titles, copied from field 030 of the MARC bibliographic record that represents the description of the item for which a separate holdings record is created.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>CODEN</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Canceled/invalid CODEN</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="035" repeatable="true">
+    <name>System Control Number</name>
+    <description>Control number, assigned by any agency, of a holdings record or a related bibliographic record for which a separate holdings record is made.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>System control number</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Canceled or invalid control number</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="040" repeatable="false">
+    <name>Record Source</name>
+    <description>MARC code for or the name of the organization(s) that created the original, assigned MARC content designation and transcribed the record into machine-readable form, or modified an existing MARC record. These data and the code in 008/39 (Cataloging source) specify the parties responsible for the content, content designation, and transcription of the bibliographic record.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Original cataloging agency</description>
+    </subfield>
+    <subfield code="b" repeatable="false">
+      <description>Language of cataloging</description>
+    </subfield>
+    <subfield code="c" repeatable="false">
+      <description>Transcribing agency</description>
+    </subfield>
+    <subfield code="d" repeatable="true">
+      <description>Modifying agency</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="066" repeatable="false">
+    <name>Character Sets Present</name>
+    <description>Used in records encoded with characters from sets other than ISO 10646 (or Unicode) to specify the character sets for data content that are present in the record. A detailed description of the standard escape sequences used in MARC records is provided in .</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Primary G0 character set</description>
+    </subfield>
+    <subfield code="b" repeatable="false">
+      <description>Primary G1 character set</description>
+    </subfield>
+    <subfield code="c" repeatable="true">
+      <description>Alternate G0 or G1 character set</description>
+    </subfield>
+  </field>
+  <field tag="337" repeatable="true">
+    <name>Media Type</name>
+    <description>Media type reflects the general type of intermediation device required to view, play, run, etc., the content of a resource. Used as an alternative to or in addition to the coded expression of Media type in field 007/00 (Category of material). Field 337 information enables indication of more specific media types and media types from various lists.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="true">
+      <description>Media type term</description>
+    </subfield>
+    <subfield code="b" repeatable="true">
+      <description>Media type code</description>
+    </subfield>
+    <subfield code="2" repeatable="false">
+      <description>Source</description>
+    </subfield>
+    <subfield code="3" repeatable="false">
+      <description>Materials specified</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="338" repeatable="true">
+    <name>Carrier Type</name>
+    <description>Carrier type reflects the format of the storage medium and housing of a carrier in combination with the media type (which indicates the intermediation device required to view, play, run, etc., the content of a resource). Used as an alternative to or in addition to the coded expression of carrier type in field 007/01 (Specific material designation). Field 338 information enables indication of more specific carrier types and carrier types from various lists.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="true">
+      <description>Carrier type term</description>
+    </subfield>
+    <subfield code="2" repeatable="false">
+      <description>Source</description>
+    </subfield>
+    <subfield code="3" repeatable="false">
+      <description>Materials specified</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="506" repeatable="true">
+    <name>Restrictions on Access Note</name>
+    <description>Information about restrictions imposed on access to the described materials.</description>
+    <indicator position="1" value="#">
+      <description>No information provided</description>
+    </indicator>
+    <indicator position="1" value="0">
+      <description>No restrictions</description>
+    </indicator>
+    <indicator position="1" value="1">
+      <description>Restrictions apply</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Terms governing access</description>
+    </subfield>
+    <subfield code="b" repeatable="true">
+      <description>Jurisdiction</description>
+    </subfield>
+    <subfield code="c" repeatable="true">
+      <description>Physical access provisions</description>
+    </subfield>
+    <subfield code="d" repeatable="true">
+      <description>Authorized users</description>
+    </subfield>
+    <subfield code="e" repeatable="true">
+      <description>Authorization</description>
+    </subfield>
+    <subfield code="f" repeatable="true">
+      <description>Standardized terminology for access restriction</description>
+    </subfield>
+    <subfield code="u" repeatable="true">
+      <description>Uniform Resource Identifier</description>
+    </subfield>
+    <subfield code="2" repeatable="false">
+      <description>Source of term</description>
+    </subfield>
+    <subfield code="3" repeatable="false">
+      <description>Materials specified</description>
+    </subfield>
+    <subfield code="5" repeatable="false">
+      <description>Institution to which field applies</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="538" repeatable="true">
+    <name>System Details Note</name>
+    <description>Technical information about an item, such as the presence or absence of certain kinds of codes; or the physical characteristics of a computer file, such as recording densities, parity, blocking factors, mode of access, software programming language, computer requirements, peripheral requirements, trade name or recording systems, number of lines of resolution, and modulation frequency. For sound and videorecordings, information about the trade name or recording system(s) (e.g., VHS), modulation frequency and number of lines of resolution may be included.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>System details note</description>
+    </subfield>
+    <subfield code="i" repeatable="false">
+      <description>Display text</description>
+    </subfield>
+    <subfield code="u" repeatable="true">
+      <description>Uniform Resource Identifier</description>
+    </subfield>
+    <subfield code="3" repeatable="false">
+      <description>Materials specified</description>
+    </subfield>
+    <subfield code="5" repeatable="true">
+      <description>Institution to which field applies</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="541" repeatable="true">
+    <name>Immediate Source of Acquisition Note</name>
+    <description>Information on the immediate source of acquisition of the described materials. Used primarily for original or historical items or other archival collections.</description>
+    <indicator position="1" value="#">
+      <description>No information provided</description>
+    </indicator>
+    <indicator position="1" value="0">
+      <description>Private</description>
+    </indicator>
+    <indicator position="1" value="1">
+      <description>Not private</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Source of acquisition</description>
+    </subfield>
+    <subfield code="b" repeatable="false">
+      <description>Address</description>
+    </subfield>
+    <subfield code="c" repeatable="false">
+      <description>Method of acquisition</description>
+    </subfield>
+    <subfield code="d" repeatable="false">
+      <description>Date of acquisition</description>
+    </subfield>
+    <subfield code="e" repeatable="false">
+      <description>Accession number</description>
+    </subfield>
+    <subfield code="f" repeatable="false">
+      <description>Owner</description>
+    </subfield>
+    <subfield code="h" repeatable="false">
+      <description>Purchase price</description>
+    </subfield>
+    <subfield code="n" repeatable="true">
+      <description>Extent</description>
+    </subfield>
+    <subfield code="o" repeatable="true">
+      <description>Type of unit</description>
+    </subfield>
+    <subfield code="3" repeatable="false">
+      <description>Materials specified</description>
+    </subfield>
+    <subfield code="5" repeatable="false">
+      <description>Institution to which field applies</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="561" repeatable="true">
+    <name>Ownership and Custodial History</name>
+    <description>Information concerning the ownership and custodial history of the described materials from the time of their creation to the time of their accessioning, including the time at which individual items or group of items were first brought together in their current arrangement or collation.</description>
+    <indicator position="1" value="#">
+      <description>No information provided</description>
+    </indicator>
+    <indicator position="1" value="0">
+      <description>Private</description>
+    </indicator>
+    <indicator position="1" value="1">
+      <description>Not private</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>History</description>
+    </subfield>
+    <subfield code="3" repeatable="false">
+      <description>Materials specified</description>
+    </subfield>
+    <subfield code="5" repeatable="false">
+      <description>Institution to which field applies</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="562" repeatable="true">
+    <name>Copy and Version Identification Note</name>
+    <description>Information that distinguishes the copy(s) or version(s) of materials held by an archive or manuscript repository when more than one copy or version exists or could exist.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="true">
+      <description>Identifying markings</description>
+    </subfield>
+    <subfield code="b" repeatable="true">
+      <description>Copy identification</description>
+    </subfield>
+    <subfield code="c" repeatable="true">
+      <description>Version identification</description>
+    </subfield>
+    <subfield code="d" repeatable="true">
+      <description>Presentation format</description>
+    </subfield>
+    <subfield code="e" repeatable="true">
+      <description>Number of copies</description>
+    </subfield>
+    <subfield code="3" repeatable="false">
+      <description>Materials specified</description>
+    </subfield>
+    <subfield code="5" repeatable="false">
+      <description>Institution to which field applies</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="563" repeatable="true">
+    <name>Binding Information</name>
+    <description>Binding information intended primarily for use with antiquarian materials, rare books, and other special collections.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Binding note</description>
+    </subfield>
+    <subfield code="u" repeatable="true">
+      <description>Uniform Resource Identifier</description>
+    </subfield>
+    <subfield code="3" repeatable="false">
+      <description>Materials specified</description>
+    </subfield>
+    <subfield code="5" repeatable="false">
+      <description>Institution to which field applies</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="583" repeatable="true">
+    <name>Action Note</name>
+    <description>Information about processing and reference or preservation actions related to the bibliographic item for which a separate holdings record is created. For those using the field to record preservation activities, a list of may be used and the authority for the terminology may be indicated in subfield $2.</description>
+    <indicator position="1" value="#">
+      <description>No information provided</description>
+    </indicator>
+    <indicator position="1" value="0">
+      <description>Private</description>
+    </indicator>
+    <indicator position="1" value="1">
+      <description>Not private</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Action</description>
+    </subfield>
+    <subfield code="b" repeatable="true">
+      <description>Action identification</description>
+    </subfield>
+    <subfield code="c" repeatable="true">
+      <description>Time/date of action</description>
+    </subfield>
+    <subfield code="d" repeatable="true">
+      <description>Action interval</description>
+    </subfield>
+    <subfield code="e" repeatable="true">
+      <description>Contingency for action</description>
+    </subfield>
+    <subfield code="f" repeatable="true">
+      <description>Authorization</description>
+    </subfield>
+    <subfield code="h" repeatable="true">
+      <description>Jurisdiction</description>
+    </subfield>
+    <subfield code="i" repeatable="true">
+      <description>Method of action</description>
+    </subfield>
+    <subfield code="j" repeatable="true">
+      <description>Site of action</description>
+    </subfield>
+    <subfield code="k" repeatable="true">
+      <description>Action agent</description>
+    </subfield>
+    <subfield code="l" repeatable="true">
+      <description>Status</description>
+    </subfield>
+    <subfield code="n" repeatable="true">
+      <description>Extent</description>
+    </subfield>
+    <subfield code="o" repeatable="true">
+      <description>Type of unit</description>
+    </subfield>
+    <subfield code="u" repeatable="true">
+      <description>Uniform Resource Identifier</description>
+    </subfield>
+    <subfield code="x" repeatable="true">
+      <description>Nonpublic note</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Public note</description>
+    </subfield>
+    <subfield code="2" repeatable="false">
+      <description>Source of term</description>
+    </subfield>
+    <subfield code="3" repeatable="false">
+      <description>Materials specified</description>
+    </subfield>
+    <subfield code="5" repeatable="false">
+      <description>Institution to which field applies</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="841" repeatable="false">
+    <name>Holdings Coded Data Values</name>
+    <description>When holdings data are embedded in a bibliographic record, this field contains certain coded information that would apply to the holdings information if it were in a separate holdings record in field 008 (Fixed-Length Data Elements).</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Type of record</description>
+    </subfield>
+    <subfield code="b" repeatable="false">
+      <description>Fixed-length data elements</description>
+    </subfield>
+    <subfield code="e" repeatable="false">
+      <description>Encoding level</description>
+    </subfield>
+  </field>
+  <field tag="842" repeatable="false">
+    <name>Textual Physical Form Designator</name>
+    <description>Designation in textual form of the physical form of the item. The physical form designator specifies the physical medium or form, or type of material of the unit held. The general physical form designator in coded form is recorded in field 007 (Physical Description Fixed Field).</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Textual physical form designator</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="843" repeatable="true">
+    <name>Reproduction Note</name>
+    <description>Description of an item that is a reproduction of original materials. Used when an institution chooses to have the main portion of the bibliographic record description reflect the original and the notes in field 843 reflect information about the copy.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Type of reproduction</description>
+    </subfield>
+    <subfield code="b" repeatable="true">
+      <description>Place of reproduction</description>
+    </subfield>
+    <subfield code="c" repeatable="true">
+      <description>Agency responsible for reproduction</description>
+    </subfield>
+    <subfield code="d" repeatable="false">
+      <description>Date of reproduction</description>
+    </subfield>
+    <subfield code="e" repeatable="false">
+      <description>Physical description of reproduction</description>
+    </subfield>
+    <subfield code="f" repeatable="true">
+      <description>Series statement of reproduction</description>
+    </subfield>
+    <subfield code="m" repeatable="true">
+      <description>Dates of publication and/or sequential designation of issues reproduced</description>
+    </subfield>
+    <subfield code="n" repeatable="true">
+      <description>Note about reproduction</description>
+    </subfield>
+    <subfield code="3" repeatable="false">
+      <description>Materials specified</description>
+    </subfield>
+    <subfield code="5" repeatable="false">
+      <description>Institution to which field applies</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="7" repeatable="false">
+      <description>Fixed-length data elements of reproduction</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="844" repeatable="false">
+    <name>Name of Unit</name>
+    <description>Bibliographic title or a supplied designation describing a basic bibliographic unit, supplementary material, or an index. A supplement or index designation used as a caption is contained in fields 853-855 (Captions and Pattern), subfield $a-$h (Enumeration captions).</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Name of unit</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="845" repeatable="true">
+    <name>Terms Governing Use and Reproduction Note</name>
+    <description>Terms governing the use and reproduction of a bibliographic item when the holding organization will lend (008/20, Lending policy, code a) and reproduce (008/21, Reproduction policy, code a) the item.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Terms governing use and reproduction</description>
+    </subfield>
+    <subfield code="b" repeatable="false">
+      <description>Jurisdiction</description>
+    </subfield>
+    <subfield code="c" repeatable="false">
+      <description>Authorization</description>
+    </subfield>
+    <subfield code="d" repeatable="false">
+      <description>Authorized users</description>
+    </subfield>
+    <subfield code="u" repeatable="true">
+      <description>Uniform Resource Identifier</description>
+    </subfield>
+    <subfield code="3" repeatable="false">
+      <description>Materials specified</description>
+    </subfield>
+    <subfield code="5" repeatable="false">
+      <description>Institution to which field applies</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="852" repeatable="true">
+    <name>Location</name>
+    <description>Organization holding the item or from which it is available. May also contain detailed information about how to locate the item in a collection.</description>
+    <indicator position="1" value="#">
+      <description>No information provided</description>
+    </indicator>
+    <indicator position="1" value="0">
+      <description>Library of Congress classification</description>
+    </indicator>
+    <indicator position="1" value="1">
+      <description>Dewey Decimal classification</description>
+    </indicator>
+    <indicator position="1" value="2">
+      <description>National Library of Medicine classification</description>
+    </indicator>
+    <indicator position="1" value="3">
+      <description>Superintendent of Documents classification</description>
+    </indicator>
+    <indicator position="1" value="4">
+      <description>Shelving control number</description>
+    </indicator>
+    <indicator position="1" value="5">
+      <description>Title</description>
+    </indicator>
+    <indicator position="1" value="6">
+      <description>Shelved separately</description>
+    </indicator>
+    <indicator position="1" value="7">
+      <description>Source specified in subfield $2</description>
+    </indicator>
+    <indicator position="1" value="8">
+      <description>Other scheme</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>No information provided</description>
+    </indicator>
+    <indicator position="2" value="0">
+      <description>Not enumeration</description>
+    </indicator>
+    <indicator position="2" value="1">
+      <description>Primary enumeration</description>
+    </indicator>
+    <indicator position="2" value="2">
+      <description>Alternative enumeration</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Location</description>
+    </subfield>
+    <subfield code="b" repeatable="true">
+      <description>Sublocation or collection</description>
+    </subfield>
+    <subfield code="c" repeatable="true">
+      <description>Shelving location</description>
+    </subfield>
+    <subfield code="d" repeatable="true">
+      <description>Former shelving location</description>
+    </subfield>
+    <subfield code="e" repeatable="true">
+      <description>Address</description>
+    </subfield>
+    <subfield code="f" repeatable="true">
+      <description>Coded location qualifier</description>
+    </subfield>
+    <subfield code="g" repeatable="true">
+      <description>Non-coded location qualifier</description>
+    </subfield>
+    <subfield code="h" repeatable="false">
+      <description>Classification part</description>
+    </subfield>
+    <subfield code="i" repeatable="true">
+      <description>Item part</description>
+    </subfield>
+    <subfield code="j" repeatable="false">
+      <description>Shelving control number</description>
+    </subfield>
+    <subfield code="k" repeatable="true">
+      <description>Call number prefix</description>
+    </subfield>
+    <subfield code="l" repeatable="false">
+      <description>Shelving form of title</description>
+    </subfield>
+    <subfield code="m" repeatable="true">
+      <description>Call number suffix</description>
+    </subfield>
+    <subfield code="n" repeatable="false">
+      <description>Country code</description>
+    </subfield>
+    <subfield code="p" repeatable="false">
+      <description>Piece designation</description>
+    </subfield>
+    <subfield code="q" repeatable="false">
+      <description>Piece physical condition</description>
+    </subfield>
+    <subfield code="s" repeatable="true">
+      <description>Copyright article-fee code</description>
+    </subfield>
+    <subfield code="t" repeatable="false">
+      <description>Copy number</description>
+    </subfield>
+    <subfield code="u" repeatable="true">
+      <description>Uniform Resource Identifier</description>
+    </subfield>
+    <subfield code="x" repeatable="true">
+      <description>Nonpublic note</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Public note</description>
+    </subfield>
+    <subfield code="2" repeatable="false">
+      <description>Source of classification or shelving scheme</description>
+    </subfield>
+    <subfield code="3" repeatable="false">
+      <description>Materials specified</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="false">
+      <description>Sequence number</description>
+    </subfield>
+  </field>
+  <field tag="853" repeatable="true">
+    <name>Captions and Pattern - Basic Bibliographic Unit</name>
+    <description>Captions that identify the enumeration and chronology levels and codes that define the publication pattern of the holdings described in the 863-865 Enumeration and Chronology fields. Any related 853-855 and 863-865 fields are linked by a number in subfield $8 (Field link and sequence number).</description>
+    <indicator position="1" value="0">
+      <description>Cannot compress or expand</description>
+    </indicator>
+    <indicator position="1" value="1">
+      <description>Can compress but not expand</description>
+    </indicator>
+    <indicator position="1" value="2">
+      <description>Can compress or expand</description>
+    </indicator>
+    <indicator position="1" value="3">
+      <description>Unknown</description>
+    </indicator>
+    <indicator position="2" value="0">
+      <description>Captions verified; all levels present</description>
+    </indicator>
+    <indicator position="2" value="1">
+      <description>Captions verified; all levels may not be present</description>
+    </indicator>
+    <indicator position="2" value="2">
+      <description>Captions unverified; all levels present</description>
+    </indicator>
+    <indicator position="2" value="3">
+      <description>Captions unverified; all levels may not be present</description>
+    </indicator>
+    <subfield code="a" repeatable="true">
+      <description>First level of enumeration</description>
+    </subfield>
+    <subfield code="b" repeatable="true">
+      <description>Second level of enumeration</description>
+    </subfield>
+    <subfield code="c" repeatable="true">
+      <description>Third level of enumeration</description>
+    </subfield>
+    <subfield code="d" repeatable="true">
+      <description>Fourth level of enumeration</description>
+    </subfield>
+    <subfield code="e" repeatable="true">
+      <description>Fifth level of enumeration</description>
+    </subfield>
+    <subfield code="f" repeatable="true">
+      <description>Sixth level of enumeration</description>
+    </subfield>
+    <subfield code="g" repeatable="true">
+      <description>Alternative numbering scheme, first level of enumeration</description>
+    </subfield>
+    <subfield code="h" repeatable="true">
+      <description>Alternative numbering scheme, second level of enumeration</description>
+    </subfield>
+    <subfield code="i" repeatable="true">
+      <description>First level of chronology</description>
+    </subfield>
+    <subfield code="j" repeatable="true">
+      <description>Second level of chronology</description>
+    </subfield>
+    <subfield code="k" repeatable="true">
+      <description>Third level of chronology</description>
+    </subfield>
+    <subfield code="l" repeatable="true">
+      <description>Fourth level of chronology</description>
+    </subfield>
+    <subfield code="m" repeatable="true">
+      <description>Alternative numbering scheme, chronology</description>
+    </subfield>
+    <subfield code="n" repeatable="true">
+      <description>Pattern note</description>
+    </subfield>
+    <subfield code="o" repeatable="true">
+      <description>Type of unit</description>
+    </subfield>
+    <subfield code="p" repeatable="true">
+      <description>Number of pieces per issuance</description>
+    </subfield>
+    <subfield code="t" repeatable="true">
+      <description>Copy</description>
+    </subfield>
+    <subfield code="u" repeatable="true">
+      <description>Bibliographic units per next higher level</description>
+    </subfield>
+    <subfield code="v" repeatable="true">
+      <description>Numbering continuity</description>
+    </subfield>
+    <subfield code="w" repeatable="true">
+      <description>Frequency</description>
+    </subfield>
+    <subfield code="x" repeatable="true">
+      <description>Calendar change</description>
+    </subfield>
+    <subfield code="y" repeatable="true">
+      <description>Regularity pattern</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Numbering scheme</description>
+    </subfield>
+    <subfield code="2" repeatable="true">
+      <description>Source of caption abbreviation</description>
+    </subfield>
+    <subfield code="3" repeatable="true">
+      <description>Materials specified</description>
+    </subfield>
+    <subfield code="6" repeatable="true">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="854" repeatable="true">
+    <name>Captions and Pattern - Supplementary Material</name>
+    <description>Captions that identify the enumeration and chronology levels and codes that define the publication pattern of the holdings described in the 863-865 Enumeration and Chronology fields. Any related 853-855 and 863-865 fields are linked by a number in subfield $8 (Field link and sequence number).</description>
+    <indicator position="1" value="0">
+      <description>Cannot compress or expand</description>
+    </indicator>
+    <indicator position="1" value="1">
+      <description>Can compress but not expand</description>
+    </indicator>
+    <indicator position="1" value="2">
+      <description>Can compress or expand</description>
+    </indicator>
+    <indicator position="1" value="3">
+      <description>Unknown</description>
+    </indicator>
+    <indicator position="2" value="0">
+      <description>Captions verified; all levels present</description>
+    </indicator>
+    <indicator position="2" value="1">
+      <description>Captions verified; all levels may not be present</description>
+    </indicator>
+    <indicator position="2" value="2">
+      <description>Captions unverified; all levels present</description>
+    </indicator>
+    <indicator position="2" value="3">
+      <description>Captions unverified; all levels may not be present</description>
+    </indicator>
+    <subfield code="a" repeatable="true">
+      <description>First level of enumeration</description>
+    </subfield>
+    <subfield code="b" repeatable="true">
+      <description>Second level of enumeration</description>
+    </subfield>
+    <subfield code="c" repeatable="true">
+      <description>Third level of enumeration</description>
+    </subfield>
+    <subfield code="d" repeatable="true">
+      <description>Fourth level of enumeration</description>
+    </subfield>
+    <subfield code="e" repeatable="true">
+      <description>Fifth level of enumeration</description>
+    </subfield>
+    <subfield code="f" repeatable="true">
+      <description>Sixth level of enumeration</description>
+    </subfield>
+    <subfield code="g" repeatable="true">
+      <description>Alternative numbering scheme, first level of enumeration</description>
+    </subfield>
+    <subfield code="h" repeatable="true">
+      <description>Alternative numbering scheme, second level of enumeration</description>
+    </subfield>
+    <subfield code="i" repeatable="true">
+      <description>First level of chronology</description>
+    </subfield>
+    <subfield code="j" repeatable="true">
+      <description>Second level of chronology</description>
+    </subfield>
+    <subfield code="k" repeatable="true">
+      <description>Third level of chronology</description>
+    </subfield>
+    <subfield code="l" repeatable="true">
+      <description>Fourth level of chronology</description>
+    </subfield>
+    <subfield code="m" repeatable="true">
+      <description>Alternative numbering scheme, chronology</description>
+    </subfield>
+    <subfield code="n" repeatable="true">
+      <description>Pattern note</description>
+    </subfield>
+    <subfield code="o" repeatable="true">
+      <description>Type of unit</description>
+    </subfield>
+    <subfield code="p" repeatable="true">
+      <description>Number of pieces per issuance</description>
+    </subfield>
+    <subfield code="t" repeatable="true">
+      <description>Copy</description>
+    </subfield>
+    <subfield code="u" repeatable="true">
+      <description>Bibliographic units per next higher level</description>
+    </subfield>
+    <subfield code="v" repeatable="true">
+      <description>Numbering continuity</description>
+    </subfield>
+    <subfield code="w" repeatable="true">
+      <description>Frequency</description>
+    </subfield>
+    <subfield code="x" repeatable="true">
+      <description>Calendar change</description>
+    </subfield>
+    <subfield code="y" repeatable="true">
+      <description>Regularity pattern</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Numbering scheme</description>
+    </subfield>
+    <subfield code="2" repeatable="true">
+      <description>Source of caption abbreviation</description>
+    </subfield>
+    <subfield code="3" repeatable="true">
+      <description>Materials specified</description>
+    </subfield>
+    <subfield code="6" repeatable="true">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="855" repeatable="true">
+    <name>Captions and Pattern - Indexes</name>
+    <description>Captions that identify the enumeration and chronology levels and codes that define the publication pattern of the holdings described in the 863-865 Enumeration and Chronology fields. Any related 853-855 and 863-865 fields are linked by a number in subfield $8 (Field link and sequence number).</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="true">
+      <description>First level of enumeration</description>
+    </subfield>
+    <subfield code="b" repeatable="true">
+      <description>Second level of enumeration</description>
+    </subfield>
+    <subfield code="c" repeatable="true">
+      <description>Third level of enumeration</description>
+    </subfield>
+    <subfield code="d" repeatable="true">
+      <description>Fourth level of enumeration</description>
+    </subfield>
+    <subfield code="e" repeatable="true">
+      <description>Fifth level of enumeration</description>
+    </subfield>
+    <subfield code="f" repeatable="true">
+      <description>Sixth level of enumeration</description>
+    </subfield>
+    <subfield code="g" repeatable="true">
+      <description>Alternative numbering scheme, first level of enumeration</description>
+    </subfield>
+    <subfield code="h" repeatable="true">
+      <description>Alternative numbering scheme, second level of enumeration</description>
+    </subfield>
+    <subfield code="i" repeatable="true">
+      <description>First level of chronology</description>
+    </subfield>
+    <subfield code="j" repeatable="true">
+      <description>Second level of chronology</description>
+    </subfield>
+    <subfield code="k" repeatable="true">
+      <description>Third level of chronology</description>
+    </subfield>
+    <subfield code="l" repeatable="true">
+      <description>Fourth level of chronology</description>
+    </subfield>
+    <subfield code="m" repeatable="true">
+      <description>Alternative numbering scheme, chronology</description>
+    </subfield>
+    <subfield code="n" repeatable="true">
+      <description>Pattern note</description>
+    </subfield>
+    <subfield code="o" repeatable="true">
+      <description>Type of unit</description>
+    </subfield>
+    <subfield code="p" repeatable="true">
+      <description>Number of pieces per issuance</description>
+    </subfield>
+    <subfield code="t" repeatable="true">
+      <description>Copy</description>
+    </subfield>
+    <subfield code="u" repeatable="true">
+      <description>Bibliographic units per next higher level</description>
+    </subfield>
+    <subfield code="v" repeatable="true">
+      <description>Numbering continuity</description>
+    </subfield>
+    <subfield code="w" repeatable="true">
+      <description>Frequency</description>
+    </subfield>
+    <subfield code="x" repeatable="true">
+      <description>Calendar change</description>
+    </subfield>
+    <subfield code="y" repeatable="true">
+      <description>Regularity pattern</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Numbering scheme</description>
+    </subfield>
+    <subfield code="2" repeatable="true">
+      <description>Source of caption abbreviation</description>
+    </subfield>
+    <subfield code="3" repeatable="true">
+      <description>Materials specified</description>
+    </subfield>
+    <subfield code="6" repeatable="true">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="856" repeatable="true">
+    <name>Electronic Location and Access</name>
+    <description>Information required to locate an electronic resource. The information identifies the electronic location containing the resource or from which it is available. It also contains information needed to retrieve the resource by the access method identified in the first indicator position. The relationship of the electronic location and access information in field 856 to the resource identified by the record as a whole is identified by the second indicator. The information contained in this field is sufficient to allow for the electronic transfer of a file, subscription to an electronic journal, or logon to an electronic resource. In some cases, only unique data elements are recorded which allow the user to access a locator table on a remote host containing the remaining information needed to access the resource.</description>
+    <indicator position="1" value="#">
+      <description>No information provided</description>
+    </indicator>
+    <indicator position="1" value="0">
+      <description>Email</description>
+    </indicator>
+    <indicator position="1" value="1">
+      <description>FTP</description>
+    </indicator>
+    <indicator position="1" value="2">
+      <description>Remote login (Telnet)</description>
+    </indicator>
+    <indicator position="1" value="3">
+      <description>Dial-up</description>
+    </indicator>
+    <indicator position="1" value="4">
+      <description>HTTP</description>
+    </indicator>
+    <indicator position="1" value="7">
+      <description>Method specified in subfield $2</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>No information provided</description>
+    </indicator>
+    <indicator position="2" value="0">
+      <description>Resource</description>
+    </indicator>
+    <indicator position="2" value="1">
+      <description>Version of resource</description>
+    </indicator>
+    <indicator position="2" value="2">
+      <description>Related resource</description>
+    </indicator>
+    <indicator position="2" value="8">
+      <description>No display constant generated</description>
+    </indicator>
+    <subfield code="a" repeatable="true">
+      <description>Host name</description>
+    </subfield>
+    <subfield code="b" repeatable="true">
+      <description>Access number</description>
+    </subfield>
+    <subfield code="c" repeatable="true">
+      <description>Compression information</description>
+    </subfield>
+    <subfield code="d" repeatable="true">
+      <description>Path</description>
+    </subfield>
+    <subfield code="f" repeatable="true">
+      <description>Electronic name</description>
+    </subfield>
+    <subfield code="h" repeatable="false">
+      <description>Processor of request</description>
+    </subfield>
+    <subfield code="i" repeatable="true">
+      <description>Instruction</description>
+    </subfield>
+    <subfield code="j" repeatable="false">
+      <description>Bits per second</description>
+    </subfield>
+    <subfield code="k" repeatable="false">
+      <description>Password</description>
+    </subfield>
+    <subfield code="l" repeatable="false">
+      <description>Logon</description>
+    </subfield>
+    <subfield code="m" repeatable="true">
+      <description>Contact for access assistance</description>
+    </subfield>
+    <subfield code="n" repeatable="false">
+      <description>Name of location of host</description>
+    </subfield>
+    <subfield code="o" repeatable="false">
+      <description>Operating system</description>
+    </subfield>
+    <subfield code="p" repeatable="false">
+      <description>Port</description>
+    </subfield>
+    <subfield code="q" repeatable="false">
+      <description>Electronic format type</description>
+    </subfield>
+    <subfield code="r" repeatable="false">
+      <description>Settings</description>
+    </subfield>
+    <subfield code="s" repeatable="true">
+      <description>File size</description>
+    </subfield>
+    <subfield code="t" repeatable="true">
+      <description>Terminal emulation</description>
+    </subfield>
+    <subfield code="u" repeatable="true">
+      <description>Uniform Resource Identifier</description>
+    </subfield>
+    <subfield code="v" repeatable="true">
+      <description>Hours access method available</description>
+    </subfield>
+    <subfield code="w" repeatable="true">
+      <description>Record control number</description>
+    </subfield>
+    <subfield code="x" repeatable="true">
+      <description>Nonpublic note</description>
+    </subfield>
+    <subfield code="y" repeatable="true">
+      <description>Link text</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Public note</description>
+    </subfield>
+    <subfield code="2" repeatable="false">
+      <description>Access method</description>
+    </subfield>
+    <subfield code="3" repeatable="false">
+      <description>Materials specified</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="863" repeatable="true">
+    <name>Enumeration and Chronology - Basic Bibliographic Unit</name>
+    <description>Description of the holdings of a bibliographic item in the collections of the reporting organization. The captions that identify the enumeration and chronology levels and the codes that define the publication pattern of the holdings are contained in the Captions and Pattern fields (853-855) that are linked to the 863-865 fields by a number in subfield $8 (Field link and sequence number).</description>
+    <indicator position="1" value="#">
+      <description>No information provided</description>
+    </indicator>
+    <indicator position="1" value="3">
+      <description>Holdings level 3</description>
+    </indicator>
+    <indicator position="1" value="4">
+      <description>Holdings level 4</description>
+    </indicator>
+    <indicator position="1" value="5">
+      <description>Holdings level 4 with piece designation</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>No information provided</description>
+    </indicator>
+    <indicator position="2" value="0">
+      <description>Compressed</description>
+    </indicator>
+    <indicator position="2" value="1">
+      <description>Uncompressed</description>
+    </indicator>
+    <indicator position="2" value="2">
+      <description>Compressed, use textual display</description>
+    </indicator>
+    <indicator position="2" value="3">
+      <description>Uncompressed, use textual display</description>
+    </indicator>
+    <indicator position="2" value="4">
+      <description>Item(s) not published</description>
+    </indicator>
+    <subfield code="a" repeatable="true">
+      <description>First level of enumeration</description>
+    </subfield>
+    <subfield code="b" repeatable="true">
+      <description>Second level of enumeration</description>
+    </subfield>
+    <subfield code="c" repeatable="true">
+      <description>Third level of enumeration</description>
+    </subfield>
+    <subfield code="d" repeatable="true">
+      <description>Fourth level of enumeration</description>
+    </subfield>
+    <subfield code="e" repeatable="true">
+      <description>Fifth level of enumeration</description>
+    </subfield>
+    <subfield code="f" repeatable="true">
+      <description>Sixth level of enumeration</description>
+    </subfield>
+    <subfield code="g" repeatable="true">
+      <description>Alternative numbering scheme, first level of enumeration</description>
+    </subfield>
+    <subfield code="h" repeatable="true">
+      <description>Alternative numbering scheme, second level of enumeration</description>
+    </subfield>
+    <subfield code="i" repeatable="true">
+      <description>First level of chronology</description>
+    </subfield>
+    <subfield code="j" repeatable="true">
+      <description>Second level of chronology</description>
+    </subfield>
+    <subfield code="k" repeatable="true">
+      <description>Third level of chronology</description>
+    </subfield>
+    <subfield code="l" repeatable="true">
+      <description>Fourth level of chronology</description>
+    </subfield>
+    <subfield code="m" repeatable="true">
+      <description>Alternative numbering scheme, chronology</description>
+    </subfield>
+    <subfield code="n" repeatable="true">
+      <description>Converted Gregorian year</description>
+    </subfield>
+    <subfield code="o" repeatable="true">
+      <description>Type of unit</description>
+    </subfield>
+    <subfield code="p" repeatable="true">
+      <description>Piece designation</description>
+    </subfield>
+    <subfield code="q" repeatable="true">
+      <description>Piece physical condition</description>
+    </subfield>
+    <subfield code="s" repeatable="true">
+      <description>Copyright article-fee code</description>
+    </subfield>
+    <subfield code="t" repeatable="true">
+      <description>Copy number</description>
+    </subfield>
+    <subfield code="v" repeatable="true">
+      <description>Issuing date</description>
+    </subfield>
+    <subfield code="w" repeatable="true">
+      <description>Break indicator</description>
+    </subfield>
+    <subfield code="x" repeatable="true">
+      <description>Nonpublic note</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Public note</description>
+    </subfield>
+    <subfield code="6" repeatable="true">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="864" repeatable="true">
+    <name>Enumeration and Chronology - Supplementary Material</name>
+    <description>Description of the holdings of a bibliographic item in the collections of the reporting organization. The captions that identify the enumeration and chronology levels and the codes that define the publication pattern of the holdings are contained in the Captions and Pattern fields (853-855) that are linked to the 863-865 fields by a number in subfield $8 (Field link and sequence number).</description>
+    <indicator position="1" value="#">
+      <description>No information provided</description>
+    </indicator>
+    <indicator position="1" value="3">
+      <description>Holdings level 3</description>
+    </indicator>
+    <indicator position="1" value="4">
+      <description>Holdings level 4</description>
+    </indicator>
+    <indicator position="1" value="5">
+      <description>Holdings level 4 with piece designation</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>No information provided</description>
+    </indicator>
+    <indicator position="2" value="0">
+      <description>Compressed</description>
+    </indicator>
+    <indicator position="2" value="1">
+      <description>Uncompressed</description>
+    </indicator>
+    <indicator position="2" value="2">
+      <description>Compressed, use textual display</description>
+    </indicator>
+    <indicator position="2" value="3">
+      <description>Uncompressed, use textual display</description>
+    </indicator>
+    <indicator position="2" value="4">
+      <description>Item(s) not published</description>
+    </indicator>
+    <subfield code="a" repeatable="true">
+      <description>First level of enumeration</description>
+    </subfield>
+    <subfield code="b" repeatable="true">
+      <description>Second level of enumeration</description>
+    </subfield>
+    <subfield code="c" repeatable="true">
+      <description>Third level of enumeration</description>
+    </subfield>
+    <subfield code="d" repeatable="true">
+      <description>Fourth level of enumeration</description>
+    </subfield>
+    <subfield code="e" repeatable="true">
+      <description>Fifth level of enumeration</description>
+    </subfield>
+    <subfield code="f" repeatable="true">
+      <description>Sixth level of enumeration</description>
+    </subfield>
+    <subfield code="g" repeatable="true">
+      <description>Alternative numbering scheme, first level of enumeration</description>
+    </subfield>
+    <subfield code="h" repeatable="true">
+      <description>Alternative numbering scheme, second level of enumeration</description>
+    </subfield>
+    <subfield code="i" repeatable="true">
+      <description>First level of chronology</description>
+    </subfield>
+    <subfield code="j" repeatable="true">
+      <description>Second level of chronology</description>
+    </subfield>
+    <subfield code="k" repeatable="true">
+      <description>Third level of chronology</description>
+    </subfield>
+    <subfield code="l" repeatable="true">
+      <description>Fourth level of chronology</description>
+    </subfield>
+    <subfield code="m" repeatable="true">
+      <description>Alternative numbering scheme, chronology</description>
+    </subfield>
+    <subfield code="n" repeatable="true">
+      <description>Converted Gregorian year</description>
+    </subfield>
+    <subfield code="o" repeatable="true">
+      <description>Type of unit</description>
+    </subfield>
+    <subfield code="p" repeatable="true">
+      <description>Piece designation</description>
+    </subfield>
+    <subfield code="q" repeatable="true">
+      <description>Piece physical condition</description>
+    </subfield>
+    <subfield code="s" repeatable="true">
+      <description>Copyright article-fee code</description>
+    </subfield>
+    <subfield code="t" repeatable="true">
+      <description>Copy number</description>
+    </subfield>
+    <subfield code="v" repeatable="true">
+      <description>Issuing date</description>
+    </subfield>
+    <subfield code="w" repeatable="true">
+      <description>Break indicator</description>
+    </subfield>
+    <subfield code="x" repeatable="true">
+      <description>Nonpublic note</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Public note</description>
+    </subfield>
+    <subfield code="6" repeatable="true">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="865" repeatable="true">
+    <name>Enumeration and Chronology - Indexes</name>
+    <description>Description of the holdings of a bibliographic item in the collections of the reporting organization. The captions that identify the enumeration and chronology levels and the codes that define the publication pattern of the holdings are contained in the Captions and Pattern fields (853-855) that are linked to the 863-865 fields by a number in subfield $8 (Field link and sequence number).</description>
+    <indicator position="1" value="#">
+      <description>No information provided</description>
+    </indicator>
+    <indicator position="1" value="4">
+      <description>Holdings level 4</description>
+    </indicator>
+    <indicator position="1" value="5">
+      <description>Holdings level 4 with piece designation</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>No information provided</description>
+    </indicator>
+    <indicator position="2" value="1">
+      <description>Uncompressed</description>
+    </indicator>
+    <indicator position="2" value="3">
+      <description>Uncompressed, use textual display</description>
+    </indicator>
+    <subfield code="a" repeatable="true">
+      <description>First level of enumeration</description>
+    </subfield>
+    <subfield code="b" repeatable="true">
+      <description>Second level of enumeration</description>
+    </subfield>
+    <subfield code="c" repeatable="true">
+      <description>Third level of enumeration</description>
+    </subfield>
+    <subfield code="d" repeatable="true">
+      <description>Fourth level of enumeration</description>
+    </subfield>
+    <subfield code="e" repeatable="true">
+      <description>Fifth level of enumeration</description>
+    </subfield>
+    <subfield code="f" repeatable="true">
+      <description>Sixth level of enumeration</description>
+    </subfield>
+    <subfield code="g" repeatable="true">
+      <description>Alternative numbering scheme, first level of enumeration</description>
+    </subfield>
+    <subfield code="h" repeatable="true">
+      <description>Alternative numbering scheme, second level of enumeration</description>
+    </subfield>
+    <subfield code="i" repeatable="true">
+      <description>First level of chronology</description>
+    </subfield>
+    <subfield code="j" repeatable="true">
+      <description>Second level of chronology</description>
+    </subfield>
+    <subfield code="k" repeatable="true">
+      <description>Third level of chronology</description>
+    </subfield>
+    <subfield code="l" repeatable="true">
+      <description>Fourth level of chronology</description>
+    </subfield>
+    <subfield code="m" repeatable="true">
+      <description>Alternative numbering scheme, chronology</description>
+    </subfield>
+    <subfield code="n" repeatable="true">
+      <description>Converted Gregorian year</description>
+    </subfield>
+    <subfield code="o" repeatable="true">
+      <description>Type of unit</description>
+    </subfield>
+    <subfield code="p" repeatable="true">
+      <description>Piece designation</description>
+    </subfield>
+    <subfield code="q" repeatable="true">
+      <description>Piece physical condition</description>
+    </subfield>
+    <subfield code="s" repeatable="true">
+      <description>Copyright article-fee code</description>
+    </subfield>
+    <subfield code="t" repeatable="true">
+      <description>Copy number</description>
+    </subfield>
+    <subfield code="v" repeatable="true">
+      <description>Issuing date</description>
+    </subfield>
+    <subfield code="w" repeatable="true">
+      <description>Break indicator</description>
+    </subfield>
+    <subfield code="x" repeatable="true">
+      <description>Nonpublic note</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Public note</description>
+    </subfield>
+    <subfield code="6" repeatable="true">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="866" repeatable="true">
+    <name>Textual Holdings - Basic Bibliographic Unit</name>
+    <description>Textual description which may include both the captions and enumeration and chronology for the holdings of a bibliographic item in the collections of the reporting organization. These fields are normally not used in holdings for single-part items. They may be used the coded 853-855 Captions and Pattern and 863-865 Enumeration and Chronology fields for multipart and serial items when those fields cannot be used adequately to describe the holdings. The 866-868 fields may also be used an Enumeration and Chronology field and any related Captions and Pattern field to record and generate an alternative display for all or part of the enumeration and chronology and captions and pattern fields.</description>
+    <indicator position="1" value="#">
+      <description>No information provided</description>
+    </indicator>
+    <indicator position="1" value="3">
+      <description>Holdings level 3</description>
+    </indicator>
+    <indicator position="1" value="4">
+      <description>Holdings level 4</description>
+    </indicator>
+    <indicator position="1" value="5">
+      <description>Holdings level 4 with piece designation</description>
+    </indicator>
+    <indicator position="2" value="0">
+      <description>Non-standard</description>
+    </indicator>
+    <indicator position="2" value="1">
+      <description>ANSI/NISO Z39.71 or ISO 10324</description>
+    </indicator>
+    <indicator position="2" value="2">
+      <description>ANSI Z39.42</description>
+    </indicator>
+    <indicator position="2" value="7">
+      <description>Source specified in subfield $2</description>
+    </indicator>
+    <subfield code="a" repeatable="true">
+      <description>Textual holdings</description>
+    </subfield>
+    <subfield code="x" repeatable="true">
+      <description>Nonpublic note</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Public note</description>
+    </subfield>
+    <subfield code="2" repeatable="true">
+      <description>Source of notation</description>
+    </subfield>
+    <subfield code="6" repeatable="true">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="867" repeatable="true">
+    <name>Textual Holdings - Supplementary Material</name>
+    <description>Textual description which may include both the captions and enumeration and chronology for the holdings of a bibliographic item in the collections of the reporting organization. These fields are normally not used in holdings for single-part items. They may be used the coded 853-855 Captions and Pattern and 863-865 Enumeration and Chronology fields for multipart and serial items when those fields cannot be used adequately to describe the holdings. The 866-868 fields may also be used an Enumeration and Chronology field and any related Captions and Pattern field to record and generate an alternative display for all or part of the enumeration and chronology and captions and pattern fields.</description>
+    <indicator position="1" value="#">
+      <description>No information provided</description>
+    </indicator>
+    <indicator position="1" value="3">
+      <description>Holdings level 3</description>
+    </indicator>
+    <indicator position="1" value="4">
+      <description>Holdings level 4</description>
+    </indicator>
+    <indicator position="1" value="5">
+      <description>Holdings level 4 with piece designation</description>
+    </indicator>
+    <indicator position="2" value="0">
+      <description>Non-standard</description>
+    </indicator>
+    <indicator position="2" value="1">
+      <description>ANSI/NISO Z39.71 or ISO 10324</description>
+    </indicator>
+    <indicator position="2" value="2">
+      <description>ANSI Z39.42</description>
+    </indicator>
+    <indicator position="2" value="7">
+      <description>Source specified in subfield $2</description>
+    </indicator>
+    <subfield code="a" repeatable="true">
+      <description>Textual holdings</description>
+    </subfield>
+    <subfield code="x" repeatable="true">
+      <description>Nonpublic note</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Public note</description>
+    </subfield>
+    <subfield code="2" repeatable="true">
+      <description>Source of notation</description>
+    </subfield>
+    <subfield code="6" repeatable="true">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="868" repeatable="true">
+    <name>Textual Holdings - Indexes</name>
+    <description>Textual description which may include both the captions and enumeration and chronology for the holdings of a bibliographic item in the collections of the reporting organization. These fields are normally not used in holdings for single-part items. They may be used the coded 853-855 Captions and Pattern and 863-865 Enumeration and Chronology fields for multipart and serial items when those fields cannot be used adequately to describe the holdings. The 866-868 fields may also be used an Enumeration and Chronology field and any related Captions and Pattern field to record and generate an alternative display for all or part of the enumeration and chronology and captions and pattern fields.</description>
+    <indicator position="1" value="#">
+      <description>No information provided</description>
+    </indicator>
+    <indicator position="1" value="3">
+      <description>Holdings level 3</description>
+    </indicator>
+    <indicator position="1" value="4">
+      <description>Holdings level 4</description>
+    </indicator>
+    <indicator position="1" value="5">
+      <description>Holdings level 4 with piece designation</description>
+    </indicator>
+    <indicator position="2" value="0">
+      <description>Non-standard</description>
+    </indicator>
+    <indicator position="2" value="1">
+      <description>ANSI/NISO Z39.71 or ISO 10324</description>
+    </indicator>
+    <indicator position="2" value="2">
+      <description>ANSI Z39.42</description>
+    </indicator>
+    <indicator position="2" value="7">
+      <description>Source specified in subfield $2</description>
+    </indicator>
+    <subfield code="a" repeatable="true">
+      <description>Textual holdings</description>
+    </subfield>
+    <subfield code="x" repeatable="true">
+      <description>Nonpublic note</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Public note</description>
+    </subfield>
+    <subfield code="2" repeatable="true">
+      <description>Source of notation</description>
+    </subfield>
+    <subfield code="6" repeatable="true">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="876" repeatable="true">
+    <name>Item Information - Basic Bibliographic Unit</name>
+    <description>Item level information about the pieces to the item specified in the holdings record. They contain various data elements that it may be desirable to record for specific items for use in acquisition or circulation applications, among others.</description>
+    <indicator position="1" value="#">
+        <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+        <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="true">
+      <description>Internal item number</description>
+    </subfield>
+    <subfield code="b" repeatable="true">
+      <description>Invalid or canceled internal item number</description>
+    </subfield>
+    <subfield code="c" repeatable="true">
+      <description>Cost</description>
+    </subfield>
+    <subfield code="d" repeatable="true">
+      <description>Date acquired</description>
+    </subfield>
+    <subfield code="e" repeatable="true">
+      <description>Source of acquisition</description>
+    </subfield>
+    <subfield code="h" repeatable="true">
+      <description>Use restrictions</description>
+    </subfield>
+    <subfield code="j" repeatable="true">
+      <description>Item status</description>
+    </subfield>
+    <subfield code="l" repeatable="true">
+      <description>Temporary location</description>
+    </subfield>
+    <subfield code="p" repeatable="true">
+      <description>Piece designation</description>
+    </subfield>
+    <subfield code="r" repeatable="true">
+      <description>Invalid or canceled piece designation</description>
+    </subfield>
+    <subfield code="t" repeatable="true">
+      <description>Copy number</description>
+    </subfield>
+    <subfield code="x" repeatable="true">
+      <description>Nonpublic note</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Public note</description>
+    </subfield>
+    <subfield code="3" repeatable="true">
+      <description>Materials specified</description>
+    </subfield>
+    <subfield code="6" repeatable="true">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="877" repeatable="true">
+    <name>Item Information - Supplementary Material</name>
+    <description>Item level information about the pieces to the item specified in the holdings record. They contain various data elements that it may be desirable to record for specific items for use in acquisition or circulation applications, among others.</description>
+    <indicator position="1" value="#">
+        <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+        <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="true">
+      <description>Internal item number</description>
+    </subfield>
+    <subfield code="b" repeatable="true">
+      <description>Invalid or canceled internal item number</description>
+    </subfield>
+    <subfield code="c" repeatable="true">
+      <description>Cost</description>
+    </subfield>
+    <subfield code="d" repeatable="true">
+      <description>Date acquired</description>
+    </subfield>
+    <subfield code="e" repeatable="true">
+      <description>Source of acquisition</description>
+    </subfield>
+    <subfield code="h" repeatable="true">
+      <description>Use restrictions</description>
+    </subfield>
+    <subfield code="j" repeatable="true">
+      <description>Item status</description>
+    </subfield>
+    <subfield code="l" repeatable="true">
+      <description>Temporary location</description>
+    </subfield>
+    <subfield code="p" repeatable="true">
+      <description>Piece designation</description>
+    </subfield>
+    <subfield code="r" repeatable="true">
+      <description>Invalid or canceled piece designation</description>
+    </subfield>
+    <subfield code="t" repeatable="true">
+      <description>Copy number</description>
+    </subfield>
+    <subfield code="x" repeatable="true">
+      <description>Nonpublic note</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Public note</description>
+    </subfield>
+    <subfield code="3" repeatable="true">
+      <description>Materials specified</description>
+    </subfield>
+    <subfield code="6" repeatable="true">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="878" repeatable="true">
+    <name>Item Information - Indexes</name>
+    <description>Item level information about the pieces to the item specified in the holdings record. They contain various data elements that it may be desirable to record for specific items for use in acquisition or circulation applications, among others.</description>
+    <indicator position="1" value="#">
+        <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+        <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="true">
+      <description>Internal item number</description>
+    </subfield>
+    <subfield code="b" repeatable="true">
+      <description>Invalid or canceled internal item number</description>
+    </subfield>
+    <subfield code="c" repeatable="true">
+      <description>Cost</description>
+    </subfield>
+    <subfield code="d" repeatable="true">
+      <description>Date acquired</description>
+    </subfield>
+    <subfield code="e" repeatable="true">
+      <description>Source of acquisition</description>
+    </subfield>
+    <subfield code="h" repeatable="true">
+      <description>Use restrictions</description>
+    </subfield>
+    <subfield code="j" repeatable="true">
+      <description>Item status</description>
+    </subfield>
+    <subfield code="l" repeatable="true">
+      <description>Temporary location</description>
+    </subfield>
+    <subfield code="p" repeatable="true">
+      <description>Piece designation</description>
+    </subfield>
+    <subfield code="r" repeatable="true">
+      <description>Invalid or canceled piece designation</description>
+    </subfield>
+    <subfield code="t" repeatable="true">
+      <description>Copy number</description>
+    </subfield>
+    <subfield code="x" repeatable="true">
+      <description>Nonpublic note</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Public note</description>
+    </subfield>
+    <subfield code="3" repeatable="true">
+      <description>Materials specified</description>
+    </subfield>
+    <subfield code="6" repeatable="true">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="880" repeatable="true">
+    <name>Alternate Graphic Representation</name>
+    <description>Fully content-designated, alternate graphic representation of another field in the same record. Field 880 is linked to the associated regular field by subfield $6 (Linkage). A subfield $6 in the associated field links that field to the 880 field. When an associated field does not exist in the record, field 880 is constructed as if it did and a reserved occurrence number (00) is used to indicate the special situation. The data in field 880 may be in more than one script.</description>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+  </field>
+</fields>

Modified: branches/serials-integration/Open-ILS/xul/staff_client/server/locale/en-US/marcedit-tooltips.xml
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/server/locale/en-US/marcedit-tooltips.xml	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/xul/staff_client/server/locale/en-US/marcedit-tooltips.xml	2010-10-18 13:46:56 UTC (rev 18371)
@@ -1,32 +1,38 @@
 <?xml version="1.0"?>
 <fields>
   <field tag="001" repeatable="false">
-    <name>CONTROL NUMBER</name>
-    <description>The control number assigned by the organization creating, using, or distributing the record. The MARC code for the organization is contained in field 003 (Control Number Identifier).</description>
+    <name>Control Number</name>
+    <description>Control number assigned by the organization creating, using, or distributing the record. The MARC code for the organization is contained in field 003 (Control Number Identifier).</description>
   </field>
   <field tag="003" repeatable="false">
-    <name>CONTROL NUMBER IDENTIFIER</name>
-    <description>The MARC code for the organization whose control number is contained in field 001 (Control Number).</description>
+    <name>Control Number Identifier</name>
+    <description>MARC code for the organization whose control number is contained in field 001 (Control Number).</description>
   </field>
   <field tag="005" repeatable="false">
-    <name>DATE AND TIME OF LATEST TRANSACTION</name>
-    <description>Sixteen characters that indicate the date and time of the latest record transaction and serve as a version identifier for the record. They are recorded according to Representation of Dates and Times (ISO 8601). The date requires 8 numeric characters in the pattern yyyymmdd. The time requires 8 numeric characters in the pattern hhmmss.f, expressed in terms of the 24-hour (00-23) clock.</description>
+    <name>Date and Time of Latest Transaction</name>
+    <description>Sixteen characters that indicate the date and time of the latest record transaction and serve as a version identifier for the record. They are recorded according to (ISO 8601). The date requires 8 numeric characters in the pattern . The time requires 8 numeric characters in the pattern expressed in terms of the 24-hour (00-23) clock.</description>
   </field>
   <field tag="006" repeatable="true">
-    <name>FIXED-LENGTH DATA ELEMENTS--ADDITIONAL MATERIAL CHARACTERISTICS--GENERAL INFORMATION</name>
-    <description>This field contains 18 character positions (00-17) that provide for coding information about special aspects of the item being cataloged that cannot be coded in field 008 (Fixed-Length Data Elements). It is used in cases when an item has multiple characteristics. It is also used to record the coded serial aspects of nontextual continuing resources.</description>
+    <name>Fixed-Length Data Elements-Additional Material Characteristics</name>
+    <description>Eighteen character positions (00-17) that provide for coding information about special aspects of the item being cataloged that cannot be coded in field 008 (Fixed-Length Data Elements). It is used in cases when an item has multiple characteristics (e.g., printed material with an accompanying cassette or a map that is issued serially) and to record the coded serial aspects of nontextual continuing resources.</description>
   </field>
   <field tag="007" repeatable="true">
-    <name>PHYSICAL DESCRIPTION FIXED FIELD--GENERAL INFORMATION</name>
-    <description>This field contains special information about the physical characteristics in a coded form. The information may represent the whole item or parts of an item such as accompanying material.</description>
+    <name>Physical Description Fixed Field-General Information</name>
+    <description>Special information about the physical characteristics in a coded form. The information may represent the whole item or parts of an item such as accompanying material.</description>
   </field>
   <field tag="008" repeatable="false">
-    <name>FIXED-LENGTH DATA ELEMENTS--GENERAL INFORMATION</name>
-    <description>This field contains 40 character positions (00-39) that provide coded information about the record as a whole and about special bibliographic aspects of the item being cataloged. These coded data elements are potentially useful for retrieval and data management purposes.</description>
+    <name>Fixed-Length Data Elements-General Information</name>
+    <description>Forty character positions (00-39) that provide coded information about the record as a whole and about special bibliographic aspects of the item being cataloged. These coded data elements are potentially useful for retrieval and data management purposes.</description>
   </field>
   <field tag="010" repeatable="false">
-    <name>LIBRARY OF CONGRESS CONTROL NUMBER</name>
-    <description>A unique number assigned to a MARC record by the Library of Congress. Valid MARC prefixes for LC control numbers are published in MARC 21 Format for Bibliographic Data.</description>
+    <name>Library of Congress Control Number</name>
+    <description>Unique number assigned to a MARC record by the Library of Congress. Valid MARC prefixes for LC control numbers are published in .</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>LC control number</description>
     </subfield>
@@ -41,8 +47,14 @@
     </subfield>
   </field>
   <field tag="013" repeatable="true">
-    <name>PATENT CONTROL INFORMATION</name>
+    <name>Patent Control Information</name>
     <description>Information used to control patent documents. In addition to information about patents, this field may contain information relating to inventors' certificates, utility certificates, utility models, patents or certificates of addition, inventors' certificates of addition, utility certificates of addition, and published applications for any of these.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>Number</description>
     </subfield>
@@ -69,11 +81,20 @@
     </subfield>
   </field>
   <field tag="015" repeatable="true">
-    <name>NATIONAL BIBLIOGRAPHY NUMBER</name>
-    <description>The bibliography entry number for cataloging information that is derived from a national bibliography.</description>
+    <name>National Bibliography Number</name>
+    <description>Bibliography entry number(s) for cataloging information that is derived from a national bibliography.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="true">
       <description>National bibliography number</description>
     </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Canceled/invalid national bibliography number</description>
+    </subfield>
     <subfield code="2" repeatable="false">
       <description>Source</description>
     </subfield>
@@ -85,19 +106,22 @@
     </subfield>
   </field>
   <field tag="016" repeatable="true">
-    <name>NATIONAL BIBLIOGRAPHIC AGENCY CONTROL NUMBER</name>
+    <name>National Bibliographic Agency Control Number</name>
     <description>Unique numbers that have been assigned to a record by a national bibliographic agency other than the Library of Congress. The control number may also appear in field 001 (Control Number) in records distributed by the same national agency. This number is a record control number used in a national bibliographic agency system, rather than a number used for an entry in a national bibliographic, field 015 (National Bibliography Number).</description>
     <indicator position="1" value="#">
       <description>Library and Archives Canada</description>
     </indicator>
     <indicator position="1" value="7">
-      <description>Source specified in subfield $2 Used when the source of the control number is indicated by a code in subfield $2. See Organization Code Sources for a listing of sources used in MARC 21 records.</description>
+      <description>Source specified in subfield $2</description>
     </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>Record control number</description>
     </subfield>
     <subfield code="z" repeatable="true">
-      <description>Canceled or invalid record control number</description>
+      <description>Canceled/invalid control number</description>
     </subfield>
     <subfield code="2" repeatable="false">
       <description>Source</description>
@@ -107,23 +131,35 @@
     </subfield>
   </field>
   <field tag="017" repeatable="true">
-    <name>COPYRIGHT OR LEGAL DEPOSIT NUMBER</name>
-    <description>The copyright registration or legal deposit number for an item that was acquired by copyright or legal deposit.</description>
+    <name>Copyright or Legal Deposit Number</name>
+    <description>Copyright registration or legal deposit number for an item that was acquired by copyright or legal deposit.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
     <indicator position="2" value="#">
       <description>Copyright or legal deposit number</description>
     </indicator>
     <indicator position="2" value="8">
       <description>No display constant generated</description>
     </indicator>
-    <subfield code="a" repeatable="false">
-      <description>International Standard Book Number</description>
+    <subfield code="a" repeatable="true">
+      <description>Copyright or legal deposit number</description>
     </subfield>
-    <subfield code="c" repeatable="false">
-      <description>Terms of availability</description>
+    <subfield code="b" repeatable="false">
+      <description>Assigning agency</description>
     </subfield>
+    <subfield code="d" repeatable="false">
+      <description>Date</description>
+    </subfield>
+    <subfield code="i" repeatable="false">
+      <description>Display text</description>
+    </subfield>
     <subfield code="z" repeatable="true">
-      <description>Canceled/invalid ISBN</description>
+      <description>Canceled/invalid copyright or legal deposit number</description>
     </subfield>
+    <subfield code="2" repeatable="false">
+      <description>Source</description>
+    </subfield>
     <subfield code="6" repeatable="false">
       <description>Linkage</description>
     </subfield>
@@ -132,17 +168,17 @@
     </subfield>
   </field>
   <field tag="018" repeatable="false">
-    <name>COPYRIGHT ARTICLE-FEE CODE</name>
-    <description>A unique identification code for a component part of a monograph or a continuing resource.</description>
+    <name>Copyright Article-Fee Code</name>
+    <description>Unique identification code for component parts appearing in monographs or continuing resources.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
-      <description>International Standard Book Number</description>
+      <description>Copyright article-fee code</description>
     </subfield>
-    <subfield code="c" repeatable="false">
-      <description>Terms of availability</description>
-    </subfield>
-    <subfield code="z" repeatable="true">
-      <description>Canceled/invalid ISBN</description>
-    </subfield>
     <subfield code="6" repeatable="false">
       <description>Linkage</description>
     </subfield>
@@ -151,8 +187,14 @@
     </subfield>
   </field>
   <field tag="020" repeatable="true">
-    <name>INTERNATIONAL STANDARD BOOK NUMBER</name>
-    <description>The ISBN assigned to a monographic publication by designated agencies in each country participating in the program. The field may include terms of availability and canceled or invalid ISBNs. It may be repeated for multiple numbers associated with the item (e.g., ISBNs for the hard bound and paperback manifestations; ISBNs for a set as a whole and for the individual parts in the set).</description>
+    <name>International Standard Book Number</name>
+    <description>International Standard Book Number (ISBN) assigned to a monographic publication by designated agencies in each country participating in the program. The field may include terms of availability and canceled or invalid ISBNs, such as ISBNs with invalid check digits or that are not applicable to the item being cataloged. It may be repeated for multiple numbers associated with the item (e.g., ISBNs for the hard bound and paperback manifestations; ISBNs for a set as a whole and for the individual parts in the set).</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>International Standard Book Number</description>
     </subfield>
@@ -170,8 +212,8 @@
     </subfield>
   </field>
   <field tag="022" repeatable="true">
-    <name>INTERNATIONAL STANDARD SERIAL NUMBER</name>
-    <description>The ISSN, a unique identification number assigned to a continuing resource.</description>
+    <name>International Standard Serial Number</name>
+    <description>International Standard Serial Number (ISSN), a unique identification number assigned to a continuing resource, and/or any incorrect or canceled ISSN.</description>
     <indicator position="1" value="#">
       <description>No level specified</description>
     </indicator>
@@ -181,9 +223,18 @@
     <indicator position="1" value="1">
       <description>Continuing resource not of international interest</description>
     </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>International Standard Serial Number</description>
     </subfield>
+    <subfield code="l" repeatable="false">
+      <description>ISSN-L</description>
+    </subfield>
+    <subfield code="m" repeatable="true">
+      <description>Canceled ISSN-L</description>
+    </subfield>
     <subfield code="y" repeatable="true">
       <description>Incorrect ISSN</description>
     </subfield>
@@ -201,22 +252,22 @@
     </subfield>
   </field>
   <field tag="024" repeatable="true">
-    <name>OTHER STANDARD IDENTIFIER</name>
-    <description>A standard number or code published on an item which cannot be accommodated in another field (e.g., field 020 (International Standard Book Number), 022 (International Standard Serial Number) , and 027 (Standard Technical Report Number)). The type of standard number or code is identified in the first indicator position or in subfield $2 (Source of number or code).</description>
+    <name>Other Standard Identifier</name>
+    <description>Standard number or code published on an item which cannot be accommodated in another field (e.g., field 020 (International Standard Book Number), 022 (International Standard Serial Number) , and 027 (Standard Technical Report Number)). The type of standard number or code is identified in the first indicator position or in subfield $2 (Source of number or code).</description>
     <indicator position="1" value="0">
-      <description>International Standard Recording Code (ISRC)Number Standard: ISO 3901: International Standard Recording Code (Maintenance Agency ) For display, hyphens (-) may be generated to separate subelements of the number, e.g., NL-C01-84-13261</description>
+      <description>International Standard Recording Code</description>
     </indicator>
     <indicator position="1" value="1">
-      <description>Universal Product Code (UPC)</description>
+      <description>Universal Product Code</description>
     </indicator>
     <indicator position="1" value="2">
-      <description>International Standard Music Number (ISMN)Number Standard: ISO 10957: International Standard Music Number (Maintenance Agency ) For display, hyphens (-) or spaces may be generated to separate subelements of the number.</description>
+      <description>International Standard Music Number</description>
     </indicator>
     <indicator position="1" value="3">
-      <description>International Article Number (EAN)</description>
+      <description>International Article Number</description>
     </indicator>
     <indicator position="1" value="4">
-      <description>Serial Item and Contribution Identifier (SICI)Number Standard: ANSI/NISO Z39.56: Serial Item and Contribution Identifier For display, hyphens (-) may be generated to separate subelements of the number, e.g., 8756-2324(198603/04)65:2L.4:QTP:1-P</description>
+      <description>Serial Item and Contribution Identifier</description>
     </indicator>
     <indicator position="1" value="7">
       <description>Source specified in subfield $2</description>
@@ -256,30 +307,51 @@
     </subfield>
   </field>
   <field tag="025" repeatable="true">
-    <name>OVERSEAS ACQUISITION NUMBER</name>
-    <description>A number assigned by the Library of Congress to an item that was acquired through one of its overseas acquisition programs.</description>
-    <subfield code="a" repeatable="false">
-      <description>Standard technical report number</description>
+    <name>Overseas Acquisition Number</name>
+    <description>Number assigned by the Library of Congress to works acquired through one of its overseas acquisition programs.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="true">
+      <description>Overseas acquisition number</description>
     </subfield>
-    <subfield code="z" repeatable="true">
-      <description>Canceled/invalid number</description>
-    </subfield>
-    <subfield code="6" repeatable="false">
-      <description>Linkage</description>
-    </subfield>
     <subfield code="8" repeatable="true">
       <description>Field link and sequence number</description>
     </subfield>
   </field>
   <field tag="026" repeatable="true">
-    <name>FINGERPRINT IDENTIFIER</name>
+    <name>Fingerprint Identifier</name>
     <description>Used to assist in the identification of antiquarian books by recording information comprising groups of characters taken from specified positions on specified pages of the book, in accordance with the principles laid down in various published guidelines.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
-      <description>Standard technical report number</description>
+      <description>First and second groups of characters</description>
     </subfield>
-    <subfield code="z" repeatable="true">
-      <description>Canceled/invalid number</description>
+    <subfield code="b" repeatable="false">
+      <description>Third and fourth groups of characters</description>
     </subfield>
+    <subfield code="c" repeatable="false">
+      <description>Date</description>
+    </subfield>
+    <subfield code="d" repeatable="true">
+      <description>Number of volume or part</description>
+    </subfield>
+    <subfield code="e" repeatable="false">
+      <description>Unparsed fingerprint</description>
+    </subfield>
+    <subfield code="2" repeatable="false">
+      <description>Source</description>
+    </subfield>
+    <subfield code="5" repeatable="true">
+      <description>Institution to which field applies</description>
+    </subfield>
     <subfield code="6" repeatable="false">
       <description>Linkage</description>
     </subfield>
@@ -288,8 +360,14 @@
     </subfield>
   </field>
   <field tag="027" repeatable="true">
-    <name>STANDARD TECHNICAL REPORT NUMBER</name>
-    <description>The STRN assigned to a technical report. The assignment of STRNs is coordinated by the National Technical Information Service (NTIS), which also maintains an assignment registry.</description>
+    <name>Standard Technical Report Number</name>
+    <description>International Standard Technical Report number (ISRN) or a Standard Technical Report Number (STRN)assigned to a technical report. Assignment of STRNs is coordinated by the National Technical Information Service (NTIS), which also maintains an assignment registry.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>Standard technical report number</description>
     </subfield>
@@ -304,16 +382,16 @@
     </subfield>
   </field>
   <field tag="028" repeatable="true">
-    <name>PUBLISHER NUMBER</name>
-    <description>The formatted number used for sound recordings, printed music, and videorecordings. Publisher's numbers that are given in an unformatted form are recorded in field 500 (General Note). A print constant identifying the kind of publisher number may be generated based on the value in the first indicator position.</description>
+    <name>Publisher Number</name>
+    <description>Formatted number used for sound recordings, printed music, and videorecordings. Publisher's numbers that are given in an unformatted form are recorded in field 500 (General Note). A print constant identifying the kind of publisher number may be generated based on the value in the first indicator position.</description>
     <indicator position="1" value="0">
-      <description>Issue number Assigned by the publisher to identify the issue or continuing resource designation.</description>
+      <description>Issue number</description>
     </indicator>
     <indicator position="1" value="1">
-      <description>Matrix number Identifies the master from which the recording was pressed.</description>
+      <description>Matrix number</description>
     </indicator>
     <indicator position="1" value="2">
-      <description>Plate number Assigned by a publisher to a printed music publication.</description>
+      <description>Plate number</description>
     </indicator>
     <indicator position="1" value="3">
       <description>Other music number</description>
@@ -350,8 +428,14 @@
     </subfield>
   </field>
   <field tag="030" repeatable="true">
-    <name>CODEN DESIGNATION</name>
-    <description>The CODEN designation for a bibliographic title. (The CODEN is assigned by the International CODEN Section of Chemical Abstracts Service.)</description>
+    <name>CODEN Designation</name>
+    <description>CODEN designation for a bibliographic title. The CODEN is assigned by the International CODEN Section of Chemical Abstracts Service.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>CODEN</description>
     </subfield>
@@ -366,10 +450,16 @@
     </subfield>
   </field>
   <field tag="031" repeatable="true">
-    <name>MUSICAL INCIPITS INFORMATION</name>
-    <description>Coded data representing the musical incipit for music using established notation schemes that employ ordinary ASCII symbols. It is primarily used to identify music manuscripts, but can be applied to any material containing music.</description>
-    <subfield code="" repeatable="false">
-      <description/>
+    <name>Musical Incipits Information</name>
+    <description>Coded data representing the musical incipit for music using established notation schemes that employ ordinary ASCII symbols. Primarily used to identify music manuscripts, but can be applied to any material containing music.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Number of work</description>
     </subfield>
     <subfield code="b" repeatable="false">
       <description>Number of movement</description>
@@ -430,13 +520,19 @@
     </subfield>
   </field>
   <field tag="032" repeatable="true">
-    <name>POSTAL REGISTRATION NUMBER</name>
-    <description>The number assigned to a publication for which the specified postal service permits the use of a special mailing class privilege.</description>
+    <name>Postal Registration Number</name>
+    <description>Number assigned to a publication for which the specified postal service permits the use of a special mailing class privilege.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>Postal registration number</description>
     </subfield>
     <subfield code="b" repeatable="false">
-      <description>Source</description>
+      <description>Source agency assigning number</description>
     </subfield>
     <subfield code="6" repeatable="false">
       <description>Linkage</description>
@@ -446,31 +542,31 @@
     </subfield>
   </field>
   <field tag="033" repeatable="true">
-    <name>DATE/TIME AND PLACE OF AN EVENT</name>
-    <description>Formatted date/time and/or coded place of creation, capture, or broadcast associated with an event or the finding of a naturally occurring object. This information in textual form is contained in field 518 (Date/Time and Place of an Event Note).</description>
+    <name>Date/Time and Place of an Event</name>
+    <description>Formatted date/time and/or coded place of creation, capture, recording, filming, execution, or broadcast associated with an event or the finding of a naturally occurring object. This information in textual form is contained in field 518 (Date/Time and Place of an Event Note).</description>
     <indicator position="1" value="#">
-      <description>No date information The field contains no subfield $a.</description>
+      <description>No date information</description>
     </indicator>
     <indicator position="1" value="0">
       <description>Single date</description>
     </indicator>
     <indicator position="1" value="1">
-      <description>Multiple single dates This value is also used for two consecutive dates.</description>
+      <description>Multiple single dates</description>
     </indicator>
     <indicator position="1" value="2">
-      <description>Range of dates The creation, capture, or finding dates span more than two consecutive days and the individual dates are unknown or are too numerous to be specified.</description>
+      <description>Range of dates</description>
     </indicator>
     <indicator position="2" value="#">
       <description>No information provided</description>
     </indicator>
     <indicator position="2" value="0">
-      <description>Capture The recording of sound, the filming of visual images, the making or producing of an item, including the creation of an item not involving recording or filming.</description>
+      <description>Capture</description>
     </indicator>
     <indicator position="2" value="1">
-      <description>Broadcast The broadcasting or re-broadcasting of sound or visual images.</description>
+      <description>Broadcast</description>
     </indicator>
     <indicator position="2" value="2">
-      <description>Finding The finding of a naturally occurring object.</description>
+      <description>Finding</description>
     </indicator>
     <subfield code="a" repeatable="true">
       <description>Formatted date/time</description>
@@ -481,6 +577,15 @@
     <subfield code="c" repeatable="true">
       <description>Geographic classification subarea code</description>
     </subfield>
+    <subfield code="p" repeatable="true">
+      <description>Place of event</description>
+    </subfield>
+    <subfield code="0" repeatable="true">
+      <description>Record control number</description>
+    </subfield>
+    <subfield code="2" repeatable="true">
+      <description>Source of term</description>
+    </subfield>
     <subfield code="3" repeatable="false">
       <description>Materials specified</description>
     </subfield>
@@ -492,10 +597,10 @@
     </subfield>
   </field>
   <field tag="034" repeatable="true">
-    <name>CODED CARTOGRAPHIC MATHEMATICAL DATA</name>
-    <description>The coded form of the mathematical data contained in field 255 (Mathematical Data Area) of the bibliographic record.</description>
+    <name>Coded Cartographic Mathematical Data</name>
+    <description>Coded form of the mathematical data contained in field 255 (Mathematical Data Area) of the bibliographic record.</description>
     <indicator position="1" value="0">
-      <description>Scale indeterminable/No scale recorded No representative fraction is given in field 255.</description>
+      <description>Scale indeterminable/No scale recorded</description>
     </indicator>
     <indicator position="1" value="1">
       <description>Single scale</description>
@@ -521,32 +626,32 @@
     <subfield code="c" repeatable="true">
       <description>Constant ratio linear vertical scale</description>
     </subfield>
-    <subfield code="d" repeatable="false">
-      <description>Coordinates--westernmost longitude</description>
+    <subfield code="d" repeatable="true">
+      <description>Coordinates</description>
     </subfield>
-    <subfield code="e" repeatable="false">
-      <description>Coordinates--easternmost longitude</description>
+    <subfield code="e" repeatable="true">
+      <description>Coordinates</description>
     </subfield>
-    <subfield code="f" repeatable="false">
-      <description>Coordinates--northernmost latitude</description>
+    <subfield code="f" repeatable="true">
+      <description>Coordinates</description>
     </subfield>
-    <subfield code="g" repeatable="false">
-      <description>Coordinates--southernmost latitude</description>
+    <subfield code="g" repeatable="true">
+      <description>Coordinates</description>
     </subfield>
     <subfield code="h" repeatable="true">
       <description>Angular scale</description>
     </subfield>
-    <subfield code="j" repeatable="false">
-      <description>Declination--northern limit</description>
+    <subfield code="j" repeatable="true">
+      <description>Declination</description>
     </subfield>
-    <subfield code="k" repeatable="false">
-      <description>Declination--southern limit</description>
+    <subfield code="k" repeatable="true">
+      <description>Declination</description>
     </subfield>
-    <subfield code="m" repeatable="false">
-      <description>Right ascension--eastern limit</description>
+    <subfield code="m" repeatable="true">
+      <description>Right ascension</description>
     </subfield>
-    <subfield code="n" repeatable="false">
-      <description>Right ascension--western limit</description>
+    <subfield code="n" repeatable="true">
+      <description>Right ascension</description>
     </subfield>
     <subfield code="p" repeatable="false">
       <description>Equinox</description>
@@ -572,6 +677,9 @@
     <subfield code="2" repeatable="false">
       <description>Source</description>
     </subfield>
+    <subfield code="3" repeatable="false">
+      <description>Materials specified</description>
+    </subfield>
     <subfield code="6" repeatable="false">
       <description>Linkage</description>
     </subfield>
@@ -580,8 +688,14 @@
     </subfield>
   </field>
   <field tag="035" repeatable="true">
-    <name>SYSTEM CONTROL NUMBER</name>
-    <description>A control number of a system other than the one whose control number is contained in field 001 (Control Number), field 010 (Library of Congress Control Number) or field 016 (National Bibliographic Agency Control Number).</description>
+    <name>System Control Number</name>
+    <description>Control number of a system other than the one whose control number is contained in field 001 (Control Number), field 010 (Library of Congress Control Number) or field 016 (National Bibliographic Agency Control Number).</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>System control number</description>
     </subfield>
@@ -596,13 +710,19 @@
     </subfield>
   </field>
   <field tag="036" repeatable="false">
-    <name>ORIGINAL STUDY NUMBER FOR COMPUTER DATA FILES</name>
-    <description>The original study number assigned by the producer of the computer file. The introductory phrase Original study: may be generated based on the field tag.</description>
+    <name>Original Study Number for Computer Data Files</name>
+    <description>Original study number assigned by the producer of the computer file. Introductory phrase may be generated based on the field tag.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>Original study number</description>
     </subfield>
     <subfield code="b" repeatable="false">
-      <description>Source</description>
+      <description>Source agency assigning number</description>
     </subfield>
     <subfield code="6" repeatable="false">
       <description>Linkage</description>
@@ -612,8 +732,14 @@
     </subfield>
   </field>
   <field tag="037" repeatable="true">
-    <name>SOURCE OF ACQUISITION</name>
-    <description>Information needed to order the item or its reproduction.</description>
+    <name>Source of Acquisition</name>
+    <description>Source of acquisition information for the item or its reproduction.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>Stock number</description>
     </subfield>
@@ -640,8 +766,14 @@
     </subfield>
   </field>
   <field tag="038" repeatable="false">
-    <name>RECORD CONTENT LICENSOR</name>
-    <description>Contains the MARC code of the organization that licenses the intellectual property rights to the data contained in the record, such as with contractual arrangements.</description>
+    <name>Record Content Licensor</name>
+    <description>MARC code of the organization that licenses the intellectual property rights to the data contained in the record, such as with contractual arrangements. See Appendix I: for a listing of sources used in MARC 21 records.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>Record content licensor</description>
     </subfield>
@@ -653,8 +785,14 @@
     </subfield>
   </field>
   <field tag="040" repeatable="false">
-    <name>CATALOGING SOURCE</name>
-    <description>The MARC code for or the name of the organization(s) that created the original bibliographic record, assigned MARC content designation and transcribed the record into machine-readable form, or modified (except for the addition of holdings symbols) an existing MARC record. These data and the code in 008/39 (Cataloging source) specify the parties responsible for the bibliographic record.</description>
+    <name>Cataloging Source</name>
+    <description>MARC code for or the name of the organization(s) that created the original bibliographic record, assigned MARC content designation and transcribed the record into machine-readable form, or modified (except for the addition of holdings symbols) an existing MARC record. These data and the code in 008/39 (Cataloging source) specify the parties responsible for the bibliographic record. See: for a listing of sources used in MARC 21 records.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>Original cataloging agency</description>
     </subfield>
@@ -667,7 +805,7 @@
     <subfield code="d" repeatable="true">
       <description>Modifying agency</description>
     </subfield>
-    <subfield code="e" repeatable="false">
+    <subfield code="e" repeatable="true">
       <description>Description conventions</description>
     </subfield>
     <subfield code="6" repeatable="false">
@@ -678,8 +816,11 @@
     </subfield>
   </field>
   <field tag="041" repeatable="true">
-    <name>LANGUAGE CODE</name>
-    <description>Codes for languages associated with an item when the language code in field 008/35-37 of the record is insufficient to convey full information. This includes records for multilingual items, items that involve translation, and items where the medium of communication is a sign language. The sources of the codes are: MARC Code List for Languages or other code lists such as ISO 639-1 (Codes for the representation of names of languages - Part 1 : alpha-2 code).</description>
+    <name>Language Code</name>
+    <description>Codes for languages associated with an item when the language code in field 008/35-37 of the record is insufficient to convey full information. Includes records for multilingual items, items that involve translation, and items where the medium of communication is a sign language. Sources of the codes are: or other code lists such as ISO 639-1 ( ).</description>
+    <indicator position="1" value="#">
+      <description>No information provided</description>
+    </indicator>
     <indicator position="1" value="0">
       <description>Item not a translation/does not include a translation</description>
     </indicator>
@@ -696,7 +837,7 @@
       <description>Language code of text/sound track or separate title</description>
     </subfield>
     <subfield code="b" repeatable="true">
-      <description>Language code for summary, abstract, or subtitles</description>
+      <description>Language code of summary or abstract</description>
     </subfield>
     <subfield code="d" repeatable="true">
       <description>Language code of sung or spoken text</description>
@@ -713,6 +854,9 @@
     <subfield code="h" repeatable="true">
       <description>Language code of original and/or intermediate translations of text</description>
     </subfield>
+    <subfield code="j" repeatable="true">
+      <description>Language code of subtitles or captions</description>
+    </subfield>
     <subfield code="2" repeatable="false">
       <description>Source of code</description>
     </subfield>
@@ -724,36 +868,39 @@
     </subfield>
   </field>
   <field tag="042" repeatable="false">
-    <name>AUTHENTICATION CODE</name>
-    <description>One or more codes that indicate an authentication center has reviewed a national database record. The codes are associated with specifically designated authentication agencies.</description>
+    <name>Authentication Code</name>
+    <description>One or more authentication codes indicating that the record, existing in a national database, has been reviewed in a specific way. Used for codes associated with specifically designated authentication agencies. Code from: .</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="true">
-      <description>Time period code</description>
+      <description>Authentication code</description>
     </subfield>
-    <subfield code="b" repeatable="true">
-      <description>Formatted 9999 B.C. through C.E. time period</description>
-    </subfield>
-    <subfield code="c" repeatable="true">
-      <description>Formatted pre-9999 B.C. time period</description>
-    </subfield>
-    <subfield code="6" repeatable="false">
-      <description>Linkage</description>
-    </subfield>
-    <subfield code="8" repeatable="true">
-      <description>Field link and sequence number</description>
-    </subfield>
   </field>
   <field tag="043" repeatable="false">
-    <name>GEOGRAPHIC AREA CODE</name>
-    <description>Geographic area codes associated with an item. The source of the code in subfield $a is the MARC Code List for Geographic Areas . The source of a local code in subfield $b is indicated in subfield $2. The source of codes in subfield $c is ISO 3166, Codes for the representation of names of countries and their subdivisions - Part 1 : Country codes or Part 2 : Country subdivision codes.</description>
+    <name>Geographic Area Code</name>
+    <description>Geographic area codes associated with an item. Code from: . The source of a local code in subfield $b is indicated in subfield $2. The source of codes in subfield $c is or .</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="true">
-      <description>Time period code</description>
+      <description>Geographic area code</description>
     </subfield>
     <subfield code="b" repeatable="true">
-      <description>Formatted 9999 B.C. through C.E. time period</description>
+      <description>Local GAC code</description>
     </subfield>
     <subfield code="c" repeatable="true">
-      <description>Formatted pre-9999 B.C. time period</description>
+      <description>ISO code</description>
     </subfield>
+    <subfield code="2" repeatable="true">
+      <description>Source of local code</description>
+    </subfield>
     <subfield code="6" repeatable="false">
       <description>Linkage</description>
     </subfield>
@@ -762,17 +909,26 @@
     </subfield>
   </field>
   <field tag="044" repeatable="false">
-    <name>COUNTRY OF PUBLISHING/PRODUCING ENTITY CODE</name>
-    <description>Codes for the country of producer when the code in field 008/15-17 (Place of publication, production, or execution) of the record is insufficient to convey full information for an item produced in more than one country. The source of the code is subfield $a is MARC Code List for Countries . Subfield $c may be used to include country and subentity codes from ISO 3166, Codes for the representation of names of countries and their subdivisions - Part 1 : Country codes or Part 2 : Country subdivision codes.</description>
+    <name>Country of Publishing/Producing Entity Code</name>
+    <description>Two- or three-character code for the country of the publishing or producing entity when field 008/15-17 (Place of publication, production, or execution) is insufficient to convey full information for an item published or produced in more than one country. Code from: . May be used to include country and subentity codes from or .</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="true">
-      <description>Time period code</description>
+      <description>MARC country code</description>
     </subfield>
     <subfield code="b" repeatable="true">
-      <description>Formatted 9999 B.C. through C.E. time period</description>
+      <description>Local subentity code</description>
     </subfield>
     <subfield code="c" repeatable="true">
-      <description>Formatted pre-9999 B.C. time period</description>
+      <description>ISO country code</description>
     </subfield>
+    <subfield code="2" repeatable="true">
+      <description>Source of local subentity code</description>
+    </subfield>
     <subfield code="6" repeatable="false">
       <description>Linkage</description>
     </subfield>
@@ -781,8 +937,8 @@
     </subfield>
   </field>
   <field tag="045" repeatable="false">
-    <name>TIME PERIOD OF CONTENT</name>
-    <description>A time period code (subfield $a) and/or a formatted time period (subfield $b and/or $c) associated with an item.</description>
+    <name>Time Period of Content</name>
+    <description>Time period code (subfield $a) and/or a formatted time period (subfield $b and/or $c) associated with an item.</description>
     <indicator position="1" value="#">
       <description>Subfield $b or $c not present</description>
     </indicator>
@@ -790,11 +946,14 @@
       <description>Single date/time</description>
     </indicator>
     <indicator position="1" value="1">
-      <description>Multiple single dates/times Multiple $b and/or $c subfields are present; each contains a formatted date/time.</description>
+      <description>Multiple single dates/times</description>
     </indicator>
     <indicator position="1" value="2">
-      <description>Range of dates/times Two $b and/or $c subfields are present and together express a range of dates and/or times.</description>
+      <description>Range of dates/times</description>
     </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="true">
       <description>Time period code</description>
     </subfield>
@@ -812,22 +971,28 @@
     </subfield>
   </field>
   <field tag="046" repeatable="true">
-    <name>SPECIAL CODED DATES</name>
-    <description>The date of item information that cannot be recorded in 008/06-14 (Type of date/Publication status, Date 1, Date 2) because such information involves one or more Before Common Era (B.C.) dates, incorrect dates, dates when resources have been modified or created, and date spans when resources are valid. When field 046 is used for B.C. dates, 008/06 is set to code b (No date given; B.C. date involved) and field 008/07-10 and 008/11-14 contain blanks (####). When field 046 is used for incorrect dates, field 008/06 is coded for the type of corrected data and field 008/07-10 and 008/11-14 contain correct dates.</description>
+    <name>Special Coded Dates</name>
+    <description>Date of item information that cannot be recorded in 008/06-14 (Type of date/Publication status, Date 1, Date 2) because such information involves one or more Before Common Era (B.C.) dates, incorrect dates, dates when resources have been modified or created, and date spans when resources are valid. When field 046 is used for B.C. dates, 008/06 is set to code b (No date given; B.C. date involved) and field 008/07-10 and 008/11-14 contain blanks (####). When field 046 is used for incorrect dates, field 008/06 is coded for the type of corrected data and field 008/07-10 and 008/11-14 contain correct dates.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>Type of date code</description>
     </subfield>
     <subfield code="b" repeatable="false">
-      <description>Date 1</description>
+      <description>Date 1, B.C. date</description>
     </subfield>
     <subfield code="c" repeatable="false">
-      <description>Date 1</description>
+      <description>Date 1, C.E. date</description>
     </subfield>
     <subfield code="d" repeatable="false">
-      <description>Date 2</description>
+      <description>Date 2, B.C. date</description>
     </subfield>
     <subfield code="e" repeatable="false">
-      <description>Date 2</description>
+      <description>Date 2, C.E. date</description>
     </subfield>
     <subfield code="j" repeatable="false">
       <description>Date resource modified</description>
@@ -855,8 +1020,11 @@
     </subfield>
   </field>
   <field tag="047" repeatable="true">
-    <name>FORM OF MUSICAL COMPOSITION CODE</name>
-    <description>Codes that indicate the form of musical composition of printed and manuscript music and musical sound recordings when character positions 18 and 19 (Form of composition) of field 008 (Fixed-Length Data Elements) for music contains the code mu for multiple forms or for non-MARC codes. MARC codes are listed under field 008 Music, /18-19 (Form of composition).</description>
+    <name>Form of Musical Composition Code</name>
+    <description>Codes that indicate the form of musical composition of printed and manuscript music and musical sound recordings when character positions 18 and 19 (Form of composition) of field 008 (Fixed-Length Data Elements) for music contains the code for multiple forms or for non-MARC codes. MARC codes are listed under field 008 Music, /18-19 (Form of composition).</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
     <indicator position="2" value="#">
       <description>MARC musical composition code</description>
     </indicator>
@@ -874,13 +1042,16 @@
     </subfield>
   </field>
   <field tag="048" repeatable="true">
-    <name>NUMBER OF MUSICAL INSTRUMENTS OR VOICES CODE</name>
-    <description>A two-character code that indicates the medium of performance for a musical group. Each code may be followed by a two-digit number (01-99) that indicates the number of parts or performers (e.g., va02, a two-part composition for Voices - Soprano). The number of parts may be omitted if not applicable.</description>
+    <name>Number of Musical Instruments or Voices Code</name>
+    <description>Two-character code that indicates the medium of performance for a musical composition. Also contains the of parts, indicated by a two-digit number immediately following the code for the musical instruments or voices (e.g., va02, a two-part composition for Voices - Soprano). The number of parts may be omitted if not specified.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
     <indicator position="2" value="#">
       <description>MARC code</description>
     </indicator>
     <indicator position="2" value="7">
-      <description>Source specified in subfield $2</description>
+      <description>Source specified in subfield ‡2</description>
     </indicator>
     <subfield code="a" repeatable="true">
       <description>Performer or ensemble</description>
@@ -896,19 +1067,19 @@
     </subfield>
   </field>
   <field tag="050" repeatable="true">
-    <name>LIBRARY OF CONGRESS CALL NUMBER</name>
-    <description>A classification or call number that is taken from Library of Congress Classification or LC Classification Additions and Changes. The brackets that customarily surround alternate class/call numbers are not carried in the MARC record; they may be generated based on the presence of repeated $a subfields.</description>
+    <name>Library of Congress Call Number</name>
+    <description>Classification or call number that is taken from or . The brackets that customarily surround alternate class/call numbers are not carried in the MARC record; they may be generated based on the presence of repeated ‡a subfields.</description>
     <indicator position="1" value="#">
-      <description>No information provided A call number assigned by an organization other than LC.</description>
+      <description>No information provided</description>
     </indicator>
     <indicator position="1" value="0">
-      <description>Item is in LC May be used by organizations transcribing from LC copy on which the call number is neither enclosed within brackets nor preceded by a Maltese cross.</description>
+      <description>Item is in LC</description>
     </indicator>
     <indicator position="1" value="1">
-      <description>Item is not in LC May be used by organizations transcribing from LC copy on which the call number is enclosed within brackets or is preceded by a Maltese cross. The brackets that customarily surround call numbers for items not in LC are not carried in the MARC record; they may be generated for display.</description>
+      <description>Item is not in LC</description>
     </indicator>
     <indicator position="2" value="0">
-      <description>Assigned by LC May be used by organizations transcribing from LC copy.</description>
+      <description>Assigned by LC</description>
     </indicator>
     <indicator position="2" value="4">
       <description>Assigned by agency other than LC</description>
@@ -930,8 +1101,14 @@
     </subfield>
   </field>
   <field tag="051" repeatable="true">
-    <name>LIBRARY OF CONGRESS COPY, ISSUE, OFFPRINT STATEMENT</name>
-    <description>Information added to a bibliographic record by LC that relates to copies, issues, and/or offprints of the described item that are in its collections.</description>
+    <name>Library of Congress Copy, Issue, Offprint Statement</name>
+    <description>Information added to a bibliographic record by the Library of Congress that relates to copies, issues, and/or offprints, etc. of the described material that are in its collections.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>Classification number</description>
     </subfield>
@@ -946,8 +1123,8 @@
     </subfield>
   </field>
   <field tag="052" repeatable="true">
-    <name>GEOGRAPHIC CLASSIFICATION</name>
-    <description>A code for the main geographic area and any applicable subareas associated with the item.</description>
+    <name>Geographic Classification</name>
+    <description>Geographic classification code that represents the geographic area and, if applicable, the geographic subarea and populated place name covered by an item.</description>
     <indicator position="1" value="#">
       <description>Library of Congress Classification</description>
     </indicator>
@@ -957,6 +1134,9 @@
     <indicator position="1" value="7">
       <description>Source specified in subfield $2</description>
     </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>Geographic classification area code</description>
     </subfield>
@@ -977,10 +1157,10 @@
     </subfield>
   </field>
   <field tag="055" repeatable="true">
-    <name>CLASSIFICATION NUMBERS ASSIGNED IN CANADA</name>
-    <description>A classification or call number that is assigned by the Library and Archives Canada or a contributing Canadian library.</description>
+    <name>Classification Numbers Assigned in Canada</name>
+    <description>Complete call number or a classification number assigned by Library and Archives Canada (LAC) or a library contributing to LAC.</description>
     <indicator position="1" value="#">
-      <description>Information not provided A call/class number assigned by an organization other than LAC.</description>
+      <description>Information not provided</description>
     </indicator>
     <indicator position="1" value="0">
       <description>Work held by LAC</description>
@@ -1035,10 +1215,10 @@
     </subfield>
   </field>
   <field tag="060" repeatable="true">
-    <name>NATIONAL LIBRARY OF MEDICINE CALL NUMBER</name>
-    <description>A classification or call number that is taken from National Library of Medicine Classification schedules QS-QZ and W or from Library of Congress Classification schedules as used by NLM for peripheral and related topics.</description>
+    <name>National Library of Medicine Call Number</name>
+    <description>Either a complete National Library of Medicine (NLM) call number or classification number assigned by either the National Library of Medicine or by other agencies using the . The second indicator values distinguish between content actually assigned by the National Library of Medicine and content assigned by an organization other than NLM.</description>
     <indicator position="1" value="#">
-      <description>No information provided A call number assigned by an organization other than NLM.</description>
+      <description>No information provided</description>
     </indicator>
     <indicator position="1" value="0">
       <description>Item is in NLM</description>
@@ -1063,8 +1243,14 @@
     </subfield>
   </field>
   <field tag="061" repeatable="true">
-    <name>NATIONAL LIBRARY OF MEDICINE COPY STATEMENT</name>
-    <description>Information added to a bibliographic record by NLM that relates to second copies or sets of the described item that are in its collections.</description>
+    <name>National Library of Medicine Copy Statement</name>
+    <description>Information added to a bibliographic record by the National Library of Medicine that relates to second copies or sets of the described item that are in its collections.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="true">
       <description>Classification number</description>
     </subfield>
@@ -1079,8 +1265,14 @@
     </subfield>
   </field>
   <field tag="066" repeatable="false">
-    <name>CHARACTER SETS PRESENT</name>
-    <description>Information that indicates that the character set present in a record is other than ISO 10646 (or Unicode). A detailed description of the standard escape sequences used in MARC records is provided in MARC 21 Specifications for Record Structure, Character Sets, and Exchange Media .</description>
+    <name>Character Sets Present</name>
+    <description>Information that indicates that the records were encoded with characters from sets other than ISO 10646 (or Unicode). A detailed description of the standard escape sequences used in MARC records is provided in</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>Primary G0 character set</description>
     </subfield>
@@ -1092,14 +1284,17 @@
     </subfield>
   </field>
   <field tag="070" repeatable="true">
-    <name>NATIONAL AGRICULTURAL LIBRARY CALL NUMBER</name>
-    <description>A classification or call number that is assigned by the National Agricultural Library.</description>
+    <name>National Agricultural Library Call Number</name>
+    <description>Classification or call number that is assigned by the National Agricultural Library (NAL).</description>
     <indicator position="1" value="0">
       <description>Item is in NAL</description>
     </indicator>
     <indicator position="1" value="1">
       <description>Item is not in NAL</description>
     </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="true">
       <description>Classification number</description>
     </subfield>
@@ -1111,15 +1306,21 @@
     </subfield>
   </field>
   <field tag="071" repeatable="true">
-    <name>NATIONAL AGRICULTURAL LIBRARY COPY STATEMENT</name>
-    <description>Information added to a bibliographic record by NAL that relates to second copies or sets of the described item that are in its collections.</description>
+    <name>National Agricultural Library Copy Statement</name>
+    <description>Call number and other information added to a bibliographic record by the National Agricultural Library (NAL) that relates to second copies or sets of the described item that are in its collections.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="true">
       <description>Classification number</description>
     </subfield>
     <subfield code="b" repeatable="false">
       <description>Item number</description>
     </subfield>
-    <subfield code="c" repeatable="false">
+    <subfield code="c" repeatable="true">
       <description>Copy information</description>
     </subfield>
     <subfield code="8" repeatable="true">
@@ -1127,10 +1328,13 @@
     </subfield>
   </field>
   <field tag="072" repeatable="true">
-    <name>SUBJECT CATEGORY CODE</name>
-    <description>A code for the subject category that is associated with the described item.</description>
+    <name>Subject Category Code</name>
+    <description>Code for the subject category that is associated with the described item.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
     <indicator position="2" value="0">
-      <description>NAL subject category code list The subject category code is taken from AGRIS: Subject Categories that is maintained by NAL.</description>
+      <description>NAL subject category code list</description>
     </indicator>
     <indicator position="2" value="7">
       <description>Source specified in subfield $2</description>
@@ -1152,8 +1356,14 @@
     </subfield>
   </field>
   <field tag="074" repeatable="true">
-    <name>GPO ITEM NUMBER</name>
-    <description>A number assigned by the U.S. Government Printing Office to publications to manage their distribution within its Depository Library System.</description>
+    <name>GPO Item Number</name>
+    <description>Item number assigned to publications by the U.S. Government Printing Office (GPO) to manage their distribution to libraries within its Depository Library System. Numbers are assigned from the .</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>GPO item number</description>
     </subfield>
@@ -1165,16 +1375,31 @@
     </subfield>
   </field>
   <field tag="080" repeatable="true">
-    <name>UNIVERSAL DECIMAL CLASSIFICATION NUMBER</name>
-    <description>A number taken from the Universal Decimal Classification scheme.</description>
-    <subfield code="a" repeatable="true">
-      <description>Classification number</description>
+    <name>Universal Decimal Classification Number</name>
+    <description>Number taken from the Universal Decimal Classification scheme.</description>
+    <indicator position="1" value="#">
+      <description>No information provided</description>
+    </indicator>
+    <indicator position="1" value="0">
+      <description>Full</description>
+    </indicator>
+    <indicator position="1" value="1">
+      <description>Abridged</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Universal Decimal Classification number</description>
     </subfield>
     <subfield code="b" repeatable="false">
       <description>Item number</description>
     </subfield>
+    <subfield code="x" repeatable="true">
+      <description>Common auxiliary subdivision</description>
+    </subfield>
     <subfield code="2" repeatable="false">
-      <description>Edition number</description>
+      <description>Edition identifier</description>
     </subfield>
     <subfield code="6" repeatable="false">
       <description>Linkage</description>
@@ -1184,8 +1409,8 @@
     </subfield>
   </field>
   <field tag="082" repeatable="true">
-    <name>DEWEY DECIMAL CLASSIFICATION NUMBER</name>
-    <description>The classification number is taken from Dewey Decimal Classification and Relative Index, the Abridged Dewey Decimal Classification and Relative Index, and electronic updates to either edition. Through 1997, updates where issued in DC&amp;: Dewey Decimal Classification Additions, Notes and Decisions.</description>
+    <name>Dewey Decimal Classification Number</name>
+    <description>Classification number is taken from , the , and electronic updates to either edition. Through 1997, updates were issued in .</description>
     <indicator position="1" value="0">
       <description>Full edition</description>
     </indicator>
@@ -1196,7 +1421,7 @@
       <description>No information provided</description>
     </indicator>
     <indicator position="2" value="0">
-      <description>Assigned by LC May be used by organizations transcribing from LC copy.</description>
+      <description>Assigned by LC</description>
     </indicator>
     <indicator position="2" value="4">
       <description>Assigned by agency other than LC</description>
@@ -1207,6 +1432,12 @@
     <subfield code="b" repeatable="false">
       <description>Item number</description>
     </subfield>
+    <subfield code="m" repeatable="false">
+      <description>Standard or optional designation</description>
+    </subfield>
+    <subfield code="q" repeatable="false">
+      <description>Assigning agency</description>
+    </subfield>
     <subfield code="2" repeatable="false">
       <description>Edition number</description>
     </subfield>
@@ -1217,9 +1448,55 @@
       <description>Field link and sequence number</description>
     </subfield>
   </field>
+  <field tag="083" repeatable="true">
+    <name>Additional Dewey Decimal Classification Number</name>
+    <description>Classification number used for subject access. It is taken from , the , and electronic updates to either edition. Through 1997, updates were issued in .</description>
+    <indicator position="1" value="0">
+      <description>Full edition</description>
+    </indicator>
+    <indicator position="1" value="1">
+      <description>Abridged edition</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="true">
+      <description>Classification number</description>
+    </subfield>
+    <subfield code="c" repeatable="true">
+      <description>Classification number--Ending number of span</description>
+    </subfield>
+    <subfield code="m" repeatable="false">
+      <description>Standard or optional designation</description>
+    </subfield>
+    <subfield code="q" repeatable="false">
+      <description>Assigning agency</description>
+    </subfield>
+    <subfield code="y" repeatable="true">
+      <description>Table sequence number for internal subarrangement or add table</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Table identification</description>
+    </subfield>
+    <subfield code="2" repeatable="false">
+      <description>Edition number</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
   <field tag="084" repeatable="true">
-    <name>OTHER CLASSIFICATION NUMBER</name>
-    <description>A classification number from a scheme not covered by one of the other number fields. The field should not be used for classification numbers assigned from a source for which a subfield $2 source of number code would not be assigned.</description>
+    <name>Other Classification Number</name>
+    <description>Classification number from a scheme not covered by one of the other number fields. The field should not be used for classification numbers assigned from a source for which a subfield $2 source of number code would not be assigned.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="true">
       <description>Classification number</description>
     </subfield>
@@ -1227,7 +1504,7 @@
       <description>Item number</description>
     </subfield>
     <subfield code="2" repeatable="false">
-      <description>Source of number</description>
+      <description>Number source</description>
     </subfield>
     <subfield code="6" repeatable="false">
       <description>Linkage</description>
@@ -1236,18 +1513,73 @@
       <description>Field link and sequence number</description>
     </subfield>
   </field>
+  <field tag="085" repeatable="true">
+    <name>Synthesized Classification Number Components</name>
+    <description>Information about how a synthesized classification number or a portion of a synthesized classification number was built. It traces the different components of a synthesized number, showing the different portions of the number and where the add instructions are given. If a number was built using two or more instructions, a separate field 085 is given for each instruction.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="true">
+      <description>Number where instructions are found-single number or beginning number of span</description>
+    </subfield>
+    <subfield code="b" repeatable="true">
+      <description>Base number</description>
+    </subfield>
+    <subfield code="c" repeatable="true">
+      <description>Classification number-ending number of span</description>
+    </subfield>
+    <subfield code="f" repeatable="true">
+      <description>Facet designator</description>
+    </subfield>
+    <subfield code="r" repeatable="true">
+      <description>Root number</description>
+    </subfield>
+    <subfield code="s" repeatable="true">
+      <description>Digits added from classification number in schedule or external table</description>
+    </subfield>
+    <subfield code="t" repeatable="true">
+      <description>Digits added from internal subarrangement or add table</description>
+    </subfield>
+    <subfield code="u" repeatable="true">
+      <description>Number being analyzed</description>
+    </subfield>
+    <subfield code="v" repeatable="true">
+      <description>Number in internal subarrangement or add table where instructions are found</description>
+    </subfield>
+    <subfield code="w" repeatable="true">
+      <description>Table identification-Internal subarrangement or add table</description>
+    </subfield>
+    <subfield code="y" repeatable="true">
+      <description>Table sequence number for internal subarrangement or add table</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Table identification</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
   <field tag="086" repeatable="true">
-    <name>GOVERNMENT DOCUMENT CLASSIFICATION NUMBER</name>
-    <description>The classification number assigned to documents by designated agencies in countries that have a government documents classification program.</description>
+    <name>Government Document Classification Number</name>
+    <description>Classification number assigned to documents by designated agencies in countries that have a government documents classification program.</description>
     <indicator position="1" value="#">
-      <description>Source specified in subfield $2 A classification number other than the U.S. or Canadian scheme.</description>
+      <description>Source specified in subfield $2</description>
     </indicator>
     <indicator position="1" value="0">
-      <description>Superintendent of Documents Classification System Assigned by the U.S Government Printing Office. Supt. of Docs. no.: may be generated for display.</description>
+      <description>Superintendent of Documents Classification System</description>
     </indicator>
     <indicator position="1" value="1">
       <description>Government of Canada Publications: Outline of Classification</description>
     </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>Classification number</description>
     </subfield>
@@ -1265,8 +1597,14 @@
     </subfield>
   </field>
   <field tag="088" repeatable="true">
-    <name>REPORT NUMBER</name>
-    <description>A report number that is not a Standard Technical Report Number (field 027)</description>
+    <name>Report Number</name>
+    <description>Report number that is not a Standard Technical Report Number (STRN), recorded in field 027.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>Report number</description>
     </subfield>
@@ -1280,18 +1618,25 @@
       <description>Field link and sequence number</description>
     </subfield>
   </field>
+  <field tag="09X" repeatable="true">
+    <name>Local Call Numbers</name>
+    <description>Reserved for local call number use and local definition. For interchange purposes, documentation of the structure of the 09X fields and input conventions must be provided to exchange partners by the organization initiating the interchange.</description>
+  </field>
   <field tag="100" repeatable="false">
-    <name>MAIN ENTRY--PERSONAL NAME</name>
-    <description>A personal name used as a main entry in a bibliographic record.</description>
+    <name>Main Entry-Personal Name</name>
+    <description>Personal name used as a main entry in a bibliographic record.</description>
     <indicator position="1" value="0">
-      <description>Forename The name is a forename or is a name consisting of words, initials, letters, etc., that are formatted in direct order.</description>
+      <description>Forename</description>
     </indicator>
     <indicator position="1" value="1">
-      <description>Surname The name is a single or multiple surname formatted in inverted order or a single name without forenames that is known to be a surname.</description>
+      <description>Surname</description>
     </indicator>
     <indicator position="1" value="3">
-      <description>Family name The name represents a family, clan, dynasty, house, or other such group and may be formatted in direct or inverted order.</description>
+      <description>Family name</description>
     </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>Personal name</description>
     </subfield>
@@ -1299,7 +1644,7 @@
       <description>Numeration</description>
     </subfield>
     <subfield code="c" repeatable="true">
-      <description>Titles and other words associated with a name</description>
+      <description>Titles and words associated with a name</description>
     </subfield>
     <subfield code="d" repeatable="false">
       <description>Dates associated with a name</description>
@@ -1337,6 +1682,9 @@
     <subfield code="u" repeatable="false">
       <description>Affiliation</description>
     </subfield>
+    <subfield code="0" repeatable="true">
+      <description>Authority record control number</description>
+    </subfield>
     <subfield code="4" repeatable="true">
       <description>Relator code</description>
     </subfield>
@@ -1348,17 +1696,20 @@
     </subfield>
   </field>
   <field tag="110" repeatable="false">
-    <name>MAIN ENTRY--CORPORATE NAME</name>
-    <description>A corporate name used as a main entry in a bibliographic record.</description>
+    <name>Main Entry-Corporate Name</name>
+    <description>Corporate name used as a main entry in a bibliographic record.</description>
     <indicator position="1" value="0">
-      <description>Inverted name The corporate name begins with a personal name in inverted order.</description>
+      <description>Inverted name</description>
     </indicator>
     <indicator position="1" value="1">
-      <description>Jurisdiction name The entry element is a name of a jurisdiction that is also an ecclesiastical entity or is a jurisdiction name under which a corporate name or a title of a work is entered.</description>
+      <description>Jurisdiction name</description>
     </indicator>
     <indicator position="1" value="2">
       <description>Name in direct order</description>
     </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>Corporate name or jurisdiction name as entry element</description>
     </subfield>
@@ -1398,6 +1749,9 @@
     <subfield code="u" repeatable="false">
       <description>Affiliation</description>
     </subfield>
+    <subfield code="0" repeatable="true">
+      <description>Authority record control number</description>
+    </subfield>
     <subfield code="4" repeatable="true">
       <description>Relator code</description>
     </subfield>
@@ -1409,17 +1763,20 @@
     </subfield>
   </field>
   <field tag="111" repeatable="false">
-    <name>MAIN ENTRY--MEETING NAME</name>
-    <description>A meeting name used as a main entry in a bibliographic record.</description>
+    <name>Main Entry-Meeting Name</name>
+    <description>Meeting or conference name used as a main entry in a bibliographic record.</description>
     <indicator position="1" value="0">
-      <description>Inverted name The meeting name begins with a personal name in inverted order.</description>
+      <description>Inverted name</description>
     </indicator>
     <indicator position="1" value="1">
-      <description>Jurisdiction name The entry element is a jurisdiction name under which a meeting name is entered.</description>
+      <description>Jurisdiction name</description>
     </indicator>
     <indicator position="1" value="2">
       <description>Name in direct order</description>
     </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>Meeting name or jurisdiction name as entry element</description>
     </subfield>
@@ -1462,6 +1819,9 @@
     <subfield code="u" repeatable="false">
       <description>Affiliation</description>
     </subfield>
+    <subfield code="0" repeatable="true">
+      <description>Authority record control number</description>
+    </subfield>
     <subfield code="4" repeatable="true">
       <description>Relator code</description>
     </subfield>
@@ -1473,11 +1833,41 @@
     </subfield>
   </field>
   <field tag="130" repeatable="false">
-    <name>MAIN ENTRY--UNIFORM TITLE</name>
-    <description>A uniform title used as a main entry in a bibliographic record.</description>
-    <indicator position="1" value="0-9">
-      <description>Number of nonfiling characters</description>
+    <name>Main Entry-Uniform Title</name>
+    <description>Uniform title used as a main entry in a bibliographic record.</description>
+    <indicator position="1" value="0">
+      <description>No nonfiling characters</description>
     </indicator>
+    <indicator position="1" value="1">
+      <description>Number of nonfiling characters - 1</description>
+    </indicator>
+    <indicator position="1" value="2">
+      <description>Number of nonfiling characters - 2</description>
+    </indicator>
+    <indicator position="1" value="3">
+      <description>Number of nonfiling characters - 3</description>
+    </indicator>
+    <indicator position="1" value="4">
+      <description>Number of nonfiling characters - 4</description>
+    </indicator>
+    <indicator position="1" value="5">
+      <description>Number of nonfiling characters - 5</description>
+    </indicator>
+    <indicator position="1" value="6">
+      <description>Number of nonfiling characters - 6</description>
+    </indicator>
+    <indicator position="1" value="7">
+      <description>Number of nonfiling characters - 7</description>
+    </indicator>
+    <indicator position="1" value="8">
+      <description>Number of nonfiling characters - 8</description>
+    </indicator>
+    <indicator position="1" value="9">
+      <description>Number of nonfiling characters - 9</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>Uniform title</description>
     </subfield>
@@ -1520,6 +1910,9 @@
     <subfield code="t" repeatable="false">
       <description>Title of a work</description>
     </subfield>
+    <subfield code="0" repeatable="true">
+      <description>Authority record control number</description>
+    </subfield>
     <subfield code="6" repeatable="false">
       <description>Linkage</description>
     </subfield>
@@ -1528,8 +1921,8 @@
     </subfield>
   </field>
   <field tag="210" repeatable="true">
-    <name>ABBREVIATED TITLE</name>
-    <description>Contains title as abbreviated for indexing or identification. An abbreviated key title is supplied by ISSN centers, based on the Key Title (Field 222). Other abbreviated titles are supplied by cataloging agencies, including abstracting and indexing services.</description>
+    <name>Abbreviated Title</name>
+    <description>Title as abbreviated for indexing or identification. An abbreviated title is supplied by ISSN centers, based on the Key Title (Field 222). Other abbreviated titles are supplied by cataloging agencies, including abstracting and indexing services.</description>
     <indicator position="1" value="0">
       <description>No added entry</description>
     </indicator>
@@ -1559,11 +1952,41 @@
     </subfield>
   </field>
   <field tag="222" repeatable="true">
-    <name>KEY TITLE</name>
-    <description>A unique title for a continuing resource that is assigned in conjunction with an ISSN recorded in field 022 by national centers under the auspices of the ISSN Network.</description>
-    <indicator position="2" value="0-9">
-      <description>Number of nonfiling characters</description>
+    <name>Key Title</name>
+    <description>Unique title for a continuing resource that is assigned in conjunction with an ISSN recorded in field 022 by national centers under the auspices of the ISSN Network.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
     </indicator>
+    <indicator position="2" value="0">
+      <description>No nonfiling characters</description>
+    </indicator>
+    <indicator position="2" value="1">
+      <description>Number of nonfiling characters - 1</description>
+    </indicator>
+    <indicator position="2" value="2">
+      <description>Number of nonfiling characters - 2</description>
+    </indicator>
+    <indicator position="2" value="3">
+      <description>Number of nonfiling characters - 3</description>
+    </indicator>
+    <indicator position="2" value="4">
+      <description>Number of nonfiling characters - 4</description>
+    </indicator>
+    <indicator position="2" value="5">
+      <description>Number of nonfiling characters - 5</description>
+    </indicator>
+    <indicator position="2" value="6">
+      <description>Number of nonfiling characters - 6</description>
+    </indicator>
+    <indicator position="2" value="7">
+      <description>Number of nonfiling characters - 7</description>
+    </indicator>
+    <indicator position="2" value="8">
+      <description>Number of nonfiling characters - 8</description>
+    </indicator>
+    <indicator position="2" value="9">
+      <description>Number of nonfiling characters - 9</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>Key title</description>
     </subfield>
@@ -1578,17 +2001,44 @@
     </subfield>
   </field>
   <field tag="240" repeatable="false">
-    <name>UNIFORM TITLE</name>
-    <description>The uniform title for an item when the bibliographic description is entered under a main entry field that contains a personal (field 100), corporate (110), or meeting (111) name.</description>
+    <name>Uniform Title</name>
+    <description>Uniform title for an item when the bibliographic description is entered under a main entry field that contains a personal (field 100), corporate (110), or meeting (111) name.</description>
     <indicator position="1" value="0">
       <description>Not printed or displayed</description>
     </indicator>
     <indicator position="1" value="1">
       <description>Printed or displayed</description>
     </indicator>
-    <indicator position="2" value="0-9">
-      <description>Number of nonfiling characters</description>
+    <indicator position="2" value="0">
+      <description>No nonfiling characters</description>
     </indicator>
+    <indicator position="2" value="1">
+      <description>Number of nonfiling characters - 1</description>
+    </indicator>
+    <indicator position="2" value="2">
+      <description>Number of nonfiling characters - 2</description>
+    </indicator>
+    <indicator position="2" value="3">
+      <description>Number of nonfiling characters - 3</description>
+    </indicator>
+    <indicator position="2" value="4">
+      <description>Number of nonfiling characters - 4</description>
+    </indicator>
+    <indicator position="2" value="5">
+      <description>Number of nonfiling characters - 5</description>
+    </indicator>
+    <indicator position="2" value="6">
+      <description>Number of nonfiling characters - 6</description>
+    </indicator>
+    <indicator position="2" value="7">
+      <description>Number of nonfiling characters - 7</description>
+    </indicator>
+    <indicator position="2" value="8">
+      <description>Number of nonfiling characters - 8</description>
+    </indicator>
+    <indicator position="2" value="9">
+      <description>Number of nonfiling characters - 9</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>Uniform title</description>
     </subfield>
@@ -1628,6 +2078,9 @@
     <subfield code="s" repeatable="false">
       <description>Version</description>
     </subfield>
+    <subfield code="0" repeatable="true">
+      <description>Authority record control number</description>
+    </subfield>
     <subfield code="6" repeatable="false">
       <description>Linkage</description>
     </subfield>
@@ -1636,17 +2089,44 @@
     </subfield>
   </field>
   <field tag="242" repeatable="true">
-    <name>TRANSLATION OF TITLE BY CATALOGING AGENCY</name>
-    <description>A translation of the title proper that is made by the cataloger when the translated title does not appear as a parallel title on the item. For a note, the introductory phrase Title translated: may be generated based on the field tag for display.</description>
+    <name>Translation of Title by Cataloging Agency</name>
+    <description>Translation of the title proper that is made by the cataloging agency when the translated title does not appear as a parallel title on the item. For a note, the introductory phrase may be generated based on the field tag for display.</description>
     <indicator position="1" value="0">
       <description>No added entry</description>
     </indicator>
     <indicator position="1" value="1">
-      <description>Added entry A value that indicates whether an added entry for the title is to be generated.</description>
+      <description>Added entry</description>
     </indicator>
-    <indicator position="2" value="0-9">
-      <description>Number of nonfiling characters</description>
+    <indicator position="2" value="0">
+      <description>No nonfiling characters</description>
     </indicator>
+    <indicator position="2" value="1">
+      <description>Number of nonfiling characters - 1</description>
+    </indicator>
+    <indicator position="2" value="2">
+      <description>Number of nonfiling characters - 2</description>
+    </indicator>
+    <indicator position="2" value="3">
+      <description>Number of nonfiling characters - 3</description>
+    </indicator>
+    <indicator position="2" value="4">
+      <description>Number of nonfiling characters - 4</description>
+    </indicator>
+    <indicator position="2" value="5">
+      <description>Number of nonfiling characters - 5</description>
+    </indicator>
+    <indicator position="2" value="6">
+      <description>Number of nonfiling characters - 6</description>
+    </indicator>
+    <indicator position="2" value="7">
+      <description>Number of nonfiling characters - 7</description>
+    </indicator>
+    <indicator position="2" value="8">
+      <description>Number of nonfiling characters - 8</description>
+    </indicator>
+    <indicator position="2" value="9">
+      <description>Number of nonfiling characters - 9</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>Title</description>
     </subfield>
@@ -1676,17 +2156,44 @@
     </subfield>
   </field>
   <field tag="243" repeatable="false">
-    <name>COLLECTIVE UNIFORM TITLE</name>
-    <description>A generic title that is constructed by the cataloger to collect works by a prolific author. The brackets that customarily enclose a collective uniform title are not carried in the MARC record. They may be generated based on the field tag.</description>
+    <name>Collective Uniform Title</name>
+    <description>Generic title that is constructed by the cataloger to collect works by a prolific author. Brackets that customarily enclose a collective uniform title are not carried in the MARC record. They may be generated based on the field tag.</description>
     <indicator position="1" value="0">
       <description>Not printed or displayed</description>
     </indicator>
     <indicator position="1" value="1">
       <description>Printed or displayed</description>
     </indicator>
-    <indicator position="2" value="0-9">
-      <description>Number of nonfiling characters</description>
+    <indicator position="2" value="0">
+      <description>No nonfiling characters</description>
     </indicator>
+    <indicator position="2" value="1">
+      <description>Number of nonfiling characters - 1</description>
+    </indicator>
+    <indicator position="2" value="2">
+      <description>Number of nonfiling characters - 2</description>
+    </indicator>
+    <indicator position="2" value="3">
+      <description>Number of nonfiling characters - 3</description>
+    </indicator>
+    <indicator position="2" value="4">
+      <description>Number of nonfiling characters - 4</description>
+    </indicator>
+    <indicator position="2" value="5">
+      <description>Number of nonfiling characters - 5</description>
+    </indicator>
+    <indicator position="2" value="6">
+      <description>Number of nonfiling characters - 6</description>
+    </indicator>
+    <indicator position="2" value="7">
+      <description>Number of nonfiling characters - 7</description>
+    </indicator>
+    <indicator position="2" value="8">
+      <description>Number of nonfiling characters - 8</description>
+    </indicator>
+    <indicator position="2" value="9">
+      <description>Number of nonfiling characters - 9</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>Uniform title</description>
     </subfield>
@@ -1734,17 +2241,44 @@
     </subfield>
   </field>
   <field tag="245" repeatable="false">
-    <name>TITLE STATEMENT</name>
-    <description>The title and statement of responsibility area of the bibliographic description of a work.</description>
+    <name>Title Statement</name>
+    <description>Title and statement of responsibility area of the bibliographic description of a work.</description>
     <indicator position="1" value="0">
-      <description>No added entry No title added entry is made either because no title added entry is desired or because the title added entry is not traced the same as the title in field 245.</description>
+      <description>No added entry</description>
     </indicator>
     <indicator position="1" value="1">
-      <description>Added entry The desired title added entry is the same as the title in field 245.</description>
+      <description>Added entry</description>
     </indicator>
-    <indicator position="2" value="0-9">
-      <description>Number of nonfiling characters</description>
+    <indicator position="2" value="0">
+      <description>No nonfiling characters</description>
     </indicator>
+    <indicator position="2" value="1">
+      <description>Number of nonfiling characters - 1</description>
+    </indicator>
+    <indicator position="2" value="2">
+      <description>Number of nonfiling characters - 2</description>
+    </indicator>
+    <indicator position="2" value="3">
+      <description>Number of nonfiling characters - 3</description>
+    </indicator>
+    <indicator position="2" value="4">
+      <description>Number of nonfiling characters - 4</description>
+    </indicator>
+    <indicator position="2" value="5">
+      <description>Number of nonfiling characters - 5</description>
+    </indicator>
+    <indicator position="2" value="6">
+      <description>Number of nonfiling characters - 6</description>
+    </indicator>
+    <indicator position="2" value="7">
+      <description>Number of nonfiling characters - 7</description>
+    </indicator>
+    <indicator position="2" value="8">
+      <description>Number of nonfiling characters - 8</description>
+    </indicator>
+    <indicator position="2" value="9">
+      <description>Number of nonfiling characters - 9</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>Title</description>
     </subfield>
@@ -1783,8 +2317,8 @@
     </subfield>
   </field>
   <field tag="246" repeatable="true">
-    <name>VARYING FORM OF TITLE</name>
-    <description>A form of the title appearing on different parts of an item or a portion of the title proper, or an alternative form of the title when the form differs significantly from the title contained in field 245.</description>
+    <name>Varying Form of Title</name>
+    <description>Varying forms of the title appearing on different parts of an item or a portion of the title proper, or an alternative form of the title when the form differs substantially from the title statement in field 245 and if they contribute to the further identification of the item.</description>
     <indicator position="1" value="0">
       <description>Note, no added entry</description>
     </indicator>
@@ -1792,7 +2326,7 @@
       <description>Note, added entry</description>
     </indicator>
     <indicator position="1" value="2">
-      <description>No note, no title added entry</description>
+      <description>No note, no added entry</description>
     </indicator>
     <indicator position="1" value="3">
       <description>No note, added entry</description>
@@ -1801,31 +2335,31 @@
       <description>No type specified</description>
     </indicator>
     <indicator position="2" value="0">
-      <description>Portion of title An added entry may be generated by first indicator value 1. No note is generated.</description>
+      <description>Portion of title</description>
     </indicator>
     <indicator position="2" value="1">
-      <description>Parallel title The parallel title that is contained in subfield $b of field 245. No note is generated.</description>
+      <description>Parallel title</description>
     </indicator>
     <indicator position="2" value="2">
-      <description>Distinctive title A special title that appears in addition to the regular title on individual issues of an item and by which the issue may be known. Distinctive title: may be generated with the note for display.</description>
+      <description>Distinctive title</description>
     </indicator>
     <indicator position="2" value="3">
-      <description>Other title A title that appears on the piece that is not more appropriately indicated by one of the other values. Other title: may be generated with the note for display.</description>
+      <description>Other title</description>
     </indicator>
     <indicator position="2" value="4">
-      <description>Cover title A title that is printed on the original cover of a publication or lettered or stamped on the publisher's binding and which is used when the cover is not the chief source of the bibliographic description. Cover title: may be generated with the note for display.</description>
+      <description>Cover title</description>
     </indicator>
     <indicator position="2" value="5">
-      <description>Added title page title A title in another language found on a title page that is not used as the chief source of the bibliographic description. Added title page title: may be generated with the note for display.</description>
+      <description>Added title page title</description>
     </indicator>
     <indicator position="2" value="6">
-      <description>Caption title A title printed at the head of the first page of text. Caption title: may be generated with the note for display.</description>
+      <description>Caption title</description>
     </indicator>
     <indicator position="2" value="7">
-      <description>Running title A title printed at the top or bottom margin of each page of a publication. Running title: may be generated with the note for display.</description>
+      <description>Running title</description>
     </indicator>
     <indicator position="2" value="8">
-      <description>Spine title A publisher's title found on the spine of a publication. Spine title: may be generated with the note for display.</description>
+      <description>Spine title</description>
     </indicator>
     <subfield code="a" repeatable="false">
       <description>Title proper/short title</description>
@@ -1862,8 +2396,8 @@
     </subfield>
   </field>
   <field tag="247" repeatable="true">
-    <name>FORMER TITLE</name>
-    <description>A former title proper when one cataloging record represents several titles associated with an entity.</description>
+    <name>Former Title</name>
+    <description>Former title proper used when one cataloging record represents several titles associated with an entity.</description>
     <indicator position="1" value="0">
       <description>No added entry</description>
     </indicator>
@@ -1871,10 +2405,10 @@
       <description>Added entry</description>
     </indicator>
     <indicator position="2" value="0">
-      <description>Display noteTitle varies: may be generated with the note for display.</description>
+      <description>Display note</description>
     </indicator>
     <indicator position="2" value="1">
-      <description>Do not display note A textual note is contained in field 547 (Former Title Complexity Note).</description>
+      <description>Do not display note</description>
     </indicator>
     <subfield code="a" repeatable="false">
       <description>Title</description>
@@ -1908,8 +2442,14 @@
     </subfield>
   </field>
   <field tag="250" repeatable="false">
-    <name>EDITION STATEMENT</name>
+    <name>Edition Statement</name>
     <description>Information relating to the edition of a work as determined by applicable cataloging rules.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>Edition statement</description>
     </subfield>
@@ -1924,8 +2464,14 @@
     </subfield>
   </field>
   <field tag="254" repeatable="false">
-    <name>MUSICAL PRESENTATION STATEMENT</name>
-    <description>A description of the format of an edition of a work of printed or manuscript music that may differ from the format of another edition of the same work.</description>
+    <name>Musical Presentation Statement</name>
+    <description>Musical presentation statement for printed or manuscript music that describes the format of the edition, which may differ from that of another edition of the same work.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>Musical presentation statement</description>
     </subfield>
@@ -1937,8 +2483,14 @@
     </subfield>
   </field>
   <field tag="255" repeatable="true">
-    <name>CARTOGRAPHIC MATHEMATICAL DATA</name>
-    <description>Mathematical data that is associated with map material, including celestial charts. This data may also be coded in field 034 (Coded Mathematical Data).</description>
+    <name>Cartographic Mathematical Data</name>
+    <description>Mathematical data associated with cartographic material, including celestial charts. This data may also be coded in field 034 (Coded Mathematical Data).</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>Statement of scale</description>
     </subfield>
@@ -1968,8 +2520,14 @@
     </subfield>
   </field>
   <field tag="256" repeatable="false">
-    <name>COMPUTER FILE CHARACTERISTICS</name>
-    <description>Characteristics of a computer file, such as the type of file, the number of records or statements.</description>
+    <name>Computer File Characteristics</name>
+    <description>Characteristics of a computer file, such as the type of file (e.g., Computer programs), the number of records, statements, etc. (e.g., 1250 records, 5076 bytes).</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>Computer file characteristics</description>
     </subfield>
@@ -1980,10 +2538,16 @@
       <description>Field link and sequence number</description>
     </subfield>
   </field>
-  <field tag="257" repeatable="false">
-    <name>COUNTRY OF PRODUCING ENTITY FOR ARCHIVAL FILMS</name>
-    <description>The name or abbreviation of the name of the country where the principal offices of the producing entity of a moving image work are located.</description>
-    <subfield code="a" repeatable="false">
+  <field tag="257" repeatable="true">
+    <name>Country of Producing Entity</name>
+    <description>Name or abbreviation of the name of the country(s) where the principal offices of the producing entity(s) of a resource are located.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="true">
       <description>Country of producing entity</description>
     </subfield>
     <subfield code="6" repeatable="false">
@@ -1994,8 +2558,14 @@
     </subfield>
   </field>
   <field tag="258" repeatable="true">
-    <name>PHILATELIC ISSUE DATA</name>
-    <description>Stamps, postal stationery and all other documents created and/or used to signify pre-payment or payment due for postal services; stamps or other labels resembling the material described above, but which have no postal value; cancellations or other marks created and/or used by a postal administration to show evidence of postal usage; material bearing one or more of the items described above.</description>
+    <name>Philatelic Issue Data</name>
+    <description>Issuing jurisdiction and denomination information about philatelic material, such as postage stamps, postal stationery (postal cards, etc., made available by a postal administration bearing a stamped impression (indicium) of denomination), revenue stamps (tax stamps), postage due stamps, and registered mail stamps. These are usually valid within a defined area and carry a value signifying prepayment or payment due for services or taxes.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>Issuing jurisdiction</description>
     </subfield>
@@ -2009,8 +2579,8 @@
       <description>Field link and sequence number</description>
     </subfield>
   </field>
-  <field tag="260" repeatable="false">
-    <name>PUBLICATION, DISTRIBUTION, ETC.</name>
+  <field tag="260" repeatable="true">
+    <name>Publication, Distribution, etc. (Imprint)</name>
     <description>Information relating to the publication, printing, distribution, issue, release, or production of a work.</description>
     <indicator position="1" value="#">
       <description>Not applicable/No information provided/Earliest available publisher</description>
@@ -2021,6 +2591,9 @@
     <indicator position="1" value="3">
       <description>Current/latest publisher</description>
     </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="true">
       <description>Place of publication, distribution, etc.</description>
     </subfield>
@@ -2050,65 +2623,17 @@
     </subfield>
   </field>
   <field tag="263" repeatable="false">
-    <name>PROJECTED PUBLICATION DATE</name>
-    <description>The projected date of publication used in bibliographic records for works that have not yet been published.</description>
-    <subfield code="a" repeatable="true">
-      <description>Address</description>
+    <name>Projected Publication Date</name>
+    <description>Projected date of publication used in bibliographic records for works that have not yet been published.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Projected publication date</description>
     </subfield>
-    <subfield code="b" repeatable="false">
-      <description>City</description>
-    </subfield>
-    <subfield code="c" repeatable="false">
-      <description>State or province</description>
-    </subfield>
-    <subfield code="d" repeatable="false">
-      <description>Country</description>
-    </subfield>
-    <subfield code="e" repeatable="false">
-      <description>Postal code</description>
-    </subfield>
-    <subfield code="f" repeatable="false">
-      <description>Terms preceding attention name</description>
-    </subfield>
-    <subfield code="g" repeatable="false">
-      <description>Attention name</description>
-    </subfield>
-    <subfield code="h" repeatable="false">
-      <description>Attention position</description>
-    </subfield>
-    <subfield code="i" repeatable="false">
-      <description>Type of address</description>
-    </subfield>
-    <subfield code="j" repeatable="true">
-      <description>Specialized telephone number</description>
-    </subfield>
-    <subfield code="k" repeatable="true">
-      <description>Telephone number</description>
-    </subfield>
-    <subfield code="l" repeatable="true">
-      <description>Fax number</description>
-    </subfield>
-    <subfield code="m" repeatable="true">
-      <description>Electronic mail address</description>
-    </subfield>
-    <subfield code="n" repeatable="true">
-      <description>TDD or TTY number</description>
-    </subfield>
-    <subfield code="p" repeatable="true">
-      <description>Contact person</description>
-    </subfield>
-    <subfield code="q" repeatable="true">
-      <description>Title of contact person</description>
-    </subfield>
-    <subfield code="r" repeatable="true">
-      <description>Hours</description>
-    </subfield>
-    <subfield code="z" repeatable="true">
-      <description>Public note</description>
-    </subfield>
-    <subfield code="4" repeatable="true">
-      <description>Relator code</description>
-    </subfield>
     <subfield code="6" repeatable="false">
       <description>Linkage</description>
     </subfield>
@@ -2117,8 +2642,8 @@
     </subfield>
   </field>
   <field tag="270" repeatable="true">
-    <name>ADDRESS</name>
-    <description>Contains an address (as well as electronic access data such as telephone, fax, TTY, etc. numbers) associated with a bibliographic item. Multiple addresses, such as mailing addresses and addresses corresponding to the physical location of an item or facilities, are recorded in separate occurrences of field 270.</description>
+    <name>Address</name>
+    <description>An address (as well as electronic access information such as email, telephone, fax, TTY, etc. numbers) for contacts related to the content of the bibliographic item. Multiple addresses, such as mailing addresses and addresses corresponding to the physical location of an item or facilities, are recorded in separate occurrences of field 270.</description>
     <indicator position="1" value="#">
       <description>No level specified</description>
     </indicator>
@@ -2202,8 +2727,14 @@
     </subfield>
   </field>
   <field tag="300" repeatable="true">
-    <name>PHYSICAL DESCRIPTION</name>
-    <description>A physical description of the described item, including its extent, dimensions, and such other physical details as a description of any accompanying materials and unit type and size.</description>
+    <name>Physical Description</name>
+    <description>Physical description of the described item, including its extent, dimensions, and such other physical details as a description of any accompanying materials and unit type and size.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="true">
       <description>Extent</description>
     </subfield>
@@ -2233,14 +2764,17 @@
     </subfield>
   </field>
   <field tag="306" repeatable="false">
-    <name>PLAYING TIME</name>
-    <description>Six numeric characters, in the pattern hhmmss, that represent the playing time for a sound recording or the stated duration of performance of printed or manuscript music. If the playing time is less than 1 hour, the hour (hh) is recorded as two zeroes; if less than a minute, the minute (mm) is also recorded as two zeroes.</description>
-    <subfield code="a" repeatable="false">
-      <description>Hours</description>
+    <name>Playing Time</name>
+    <description>Six numeric characters, in the pattern that represent the playing time for a sound recording, videorecording, etc. or the stated duration of performance of printed or manuscript music. If the playing time is less than 1 hour, the hour is recorded as two zeroes; if less than a minute, the minute is also recorded as two zeroes.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="true">
+      <description>Playing time</description>
     </subfield>
-    <subfield code="b" repeatable="false">
-      <description>Additional information</description>
-    </subfield>
     <subfield code="6" repeatable="false">
       <description>Linkage</description>
     </subfield>
@@ -2249,14 +2783,17 @@
     </subfield>
   </field>
   <field tag="307" repeatable="true">
-    <name>HOURS, ETC.</name>
-    <description>Chronological information identifying the days and/or times an item is available or accessible. It is used primarily in records for electronic resources.</description>
+    <name>Hours, Etc.</name>
+    <description>Chronological information identifying the days and/or times an item is available or accessible. Used primarily in records for electronic resources.</description>
     <indicator position="1" value="#">
       <description>Hours</description>
     </indicator>
     <indicator position="1" value="8">
       <description>No display constant generated</description>
     </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>Hours</description>
     </subfield>
@@ -2271,8 +2808,14 @@
     </subfield>
   </field>
   <field tag="310" repeatable="false">
-    <name>CURRENT PUBLICATION FREQUENCY</name>
-    <description>The current stated publication frequency of either an item or an update to an item. Dates are included when the beginning date of the current frequency is not the same as the beginning date of publication. These data are related to coded data in field 008/18 (Frequency) and 008/19 (Regularity).</description>
+    <name>Current Publication Frequency</name>
+    <description>Current stated publication frequency of either an item or an update to an item. Dates are included when the beginning date of the current frequency is not the same as the beginning date of publication.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>Current publication frequency</description>
     </subfield>
@@ -2287,8 +2830,14 @@
     </subfield>
   </field>
   <field tag="321" repeatable="true">
-    <name>FORMER PUBLICATION FREQUENCY</name>
-    <description>The former frequency of either an item or an update to an item when a current frequency is contained in field 310.</description>
+    <name>Former Publication Frequency</name>
+    <description>Former publication frequency of either an item or an update to an item when a current publication frequency is given in field 310 (Current Publication Frequency).</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>Former publication frequency</description>
     </subfield>
@@ -2302,9 +2851,99 @@
       <description>Field link and sequence number</description>
     </subfield>
   </field>
+  <field tag="336" repeatable="true">
+    <name>Content Type</name>
+    <description>The form of communication through which a work is expressed. Used in conjunction with Leader /06 (Type of record), which indicates the general type of content of the resource. Field 336 information enables expression of more specific content types and content types from various lists.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="true">
+      <description>Content type term</description>
+    </subfield>
+    <subfield code="b" repeatable="true">
+      <description>Content type code</description>
+    </subfield>
+    <subfield code="2" repeatable="false">
+      <description>Source</description>
+    </subfield>
+    <subfield code="3" repeatable="false">
+      <description>Materials specified</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="337" repeatable="true">
+    <name>Media Type</name>
+    <description>Media type reflects the general type of intermediation device required to view, play, run, etc., the content of a resource. Used as an alternative to or in addition to the coded expression of Media type in field 007/00 (Category of material). Field 337 information enables indication of more specific media types and media types from various lists.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="true">
+      <description>Media type term</description>
+    </subfield>
+    <subfield code="b" repeatable="true">
+      <description>Media type code</description>
+    </subfield>
+    <subfield code="2" repeatable="false">
+      <description>Source</description>
+    </subfield>
+    <subfield code="3" repeatable="false">
+      <description>Materials specified</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="338" repeatable="true">
+    <name>Carrier Type</name>
+    <description>Carrier type reflects the format of the storage medium and housing of a carrier in combination with the media type (which indicates the intermediation device required to view, play, run, etc., the content of a resource). Used as an alternative to or in addition to the coded expression of carrier type in field 007/01 (Specific material designation). Field 338 information enables indication of more specific carrier types and carrier types from various lists.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="true">
+      <description>Carrier type term</description>
+    </subfield>
+    <subfield code="b" repeatable="true">
+      <description>Carrier type code</description>
+    </subfield>
+    <subfield code="2" repeatable="false">
+      <description>Source</description>
+    </subfield>
+    <subfield code="3" repeatable="false">
+      <description>Materials specified</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
   <field tag="340" repeatable="true">
-    <name>PHYSICAL MEDIUM</name>
+    <name>Physical Medium</name>
     <description>Physical description information for an item that requires technical equipment for its use or an item that has special conservation or storage needs.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="true">
       <description>Material base and configuration</description>
     </subfield>
@@ -2340,8 +2979,8 @@
     </subfield>
   </field>
   <field tag="342" repeatable="true">
-    <name>GEOSPATIAL REFERENCE DATA</name>
-    <description>A description of the frame of reference for the coordinates in a data set. To work with a data set a user must be able to identify how location accuracy has been affected through the application of a geospatial reference method, thus enabling the user to manipulate the data set to recover location accuracy.</description>
+    <name>Geospatial Reference Data</name>
+    <description>Description of the frame of reference for the coordinates in a data set. To work with a data set a user must be able to identify how location accuracy has been affected through the application of a geospatial reference method, thus enabling the user to manipulate the data set to recover location accuracy.</description>
     <indicator position="1" value="0">
       <description>Horizontal coordinate system</description>
     </indicator>
@@ -2379,7 +3018,7 @@
       <description>Name</description>
     </subfield>
     <subfield code="b" repeatable="false">
-      <description>Coordinate or distance units</description>
+      <description>Coordinate units or distance units</description>
     </subfield>
     <subfield code="c" repeatable="false">
       <description>Latitude resolution</description>
@@ -2397,7 +3036,7 @@
       <description>Longitude of central meridian or projection center</description>
     </subfield>
     <subfield code="h" repeatable="false">
-      <description>Latitude of projection origin or projection center</description>
+      <description>Latitude of projection center or projection origin</description>
     </subfield>
     <subfield code="i" repeatable="false">
       <description>False easting</description>
@@ -2455,8 +3094,14 @@
     </subfield>
   </field>
   <field tag="343" repeatable="true">
-    <name>PLANAR COORDINATE DATA</name>
+    <name>Planar Coordinate Data</name>
     <description>Information about the coordinate system developed on a planar surface. The information is provided to allow the user of a geospatial data set to identify the quantities of distances, or distances and angles. These define the position of a point on a reference plane onto which the surface of the Earth has been projected.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>Planar coordinate encoding method</description>
     </subfield>
@@ -2492,8 +3137,14 @@
     </subfield>
   </field>
   <field tag="351" repeatable="true">
-    <name>ORGANIZATION AND ARRANGEMENT OF MATERIALS</name>
-    <description>Describes the organization and arrangement of a collection of items.</description>
+    <name>Organization and Arrangement of Materials</name>
+    <description>Information about the organization and arrangement of a collection of items.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="true">
       <description>Organization</description>
     </subfield>
@@ -2514,8 +3165,14 @@
     </subfield>
   </field>
   <field tag="352" repeatable="true">
-    <name>DIGITAL GRAPHIC REPRESENTATION</name>
-    <description>A description of the method of referencing and the mechanism used to represent graphic information in a data set. This information consists of the type of storage technique used, the number of items in the data set, and the format in which the data is stored.</description>
+    <name>Digital Graphic Representation</name>
+    <description>Description of the method of referencing and the mechanism used to represent graphic information in a data set. This information consists of the type of storage technique used, the number of items in the data set, and the format in which the data is stored.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>Direct reference method</description>
     </subfield>
@@ -2540,7 +3197,7 @@
     <subfield code="i" repeatable="false">
       <description>Indirect reference description</description>
     </subfield>
-    <subfield code="q" repeatable="true">
+    <subfield code="q" repeatable="false">
       <description>Format of the digital image</description>
     </subfield>
     <subfield code="6" repeatable="false">
@@ -2551,8 +3208,8 @@
     </subfield>
   </field>
   <field tag="355" repeatable="true">
-    <name>SECURITY CLASSIFICATION CONTROL</name>
-    <description>Specifics pertaining to the security classification associated with the document, title, abstract, contents note, and/or the author. In addition, it can contain handling instructions and external dissemination information pertaining to the dissemination of the document, title, abstract, contents note, and author. The field may also contain downgrading or declassification data, the name of the classification system, and a country of origin code. Code from: MARC Code List for Countries</description>
+    <name>Security Classification Control</name>
+    <description>Specifics pertaining to the security classification associated with the document, title, abstract, contents note, and/or the author. In addition, it can contain handling instructions and external dissemination information pertaining to the dissemination of the document, title, abstract, contents note, and author. The field may also contain downgrading or declassification data, the name of the classification system, and a country of origin code.</description>
     <indicator position="1" value="0">
       <description>Document</description>
     </indicator>
@@ -2572,8 +3229,11 @@
       <description>Record</description>
     </indicator>
     <indicator position="1" value="8">
-      <description>Other element</description>
+      <description>None of the above</description>
     </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>Security classification</description>
     </subfield>
@@ -2609,14 +3269,26 @@
     </subfield>
   </field>
   <field tag="357" repeatable="false">
-    <name>ORIGINATOR DISSEMINATION CONTROL</name>
+    <name>Originator Dissemination Control</name>
     <description>Specifics pertaining to originator (i.e., author, producer) control of dissemination of the material in hand. Subfield $a contains a specific term denoting that the originator has control over the material.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
-      <description>Dates of publication and/or sequential designation</description>
+      <description>Originator control term</description>
     </subfield>
-    <subfield code="z" repeatable="false">
-      <description>Source of information</description>
+    <subfield code="b" repeatable="true">
+      <description>Originating agency</description>
     </subfield>
+    <subfield code="c" repeatable="true">
+      <description>Authorized recipients of material</description>
+    </subfield>
+    <subfield code="g" repeatable="true">
+      <description>Other restrictions</description>
+    </subfield>
     <subfield code="6" repeatable="false">
       <description>Linkage</description>
     </subfield>
@@ -2625,14 +3297,17 @@
     </subfield>
   </field>
   <field tag="362" repeatable="true">
-    <name>DATES OF PUBLICATION AND/OR SEQUENTIAL DESIGNATION</name>
-    <description>Contains the beginning/ending date(s) of an item and/or the sequential designations used on each part. Dates to be used in this field are chronological designations that identify individual issues of the continuing resource. The sequential designations are usually numeric but can be alphabetic as well. The information may be formatted or unformatted. If the date information has been obtained from a source other than the first and/or last issue of the item published, the information is given in an unformatted note and the source of the information is usually cited.</description>
+    <name>Dates of Publication and/or Sequential Designation</name>
+    <description>Beginning/ending date(s) of an item and/or the sequential designations used on each part. Dates to be used in this field are chronological designations that identify individual issues of the continuing resource. The sequential designations are usually numeric but can be alphabetic as well. The information may be formatted or unformatted. If the date information has been obtained from a source other than the first and/or last issue of the item published, the information is given in an unformatted note and the source of the information is usually cited.</description>
     <indicator position="1" value="0">
       <description>Formatted style</description>
     </indicator>
     <indicator position="1" value="1">
       <description>Unformatted note</description>
     </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>Dates of publication and/or sequential designation</description>
     </subfield>
@@ -2646,9 +3321,94 @@
       <description>Field link and sequence number</description>
     </subfield>
   </field>
+  <field tag="363" repeatable="true">
+    <name>Normalized Date and Sequential Designation</name>
+    <description>The numeric, alphabetic and/or normalized date designation used on the bibliographic item that identifies its parts and shows the relationship of the parts to the whole.</description>
+    <indicator position="1" value="#">
+      <description>No information provided</description>
+    </indicator>
+    <indicator position="1" value="0">
+      <description>Starting information</description>
+    </indicator>
+    <indicator position="1" value="1">
+      <description>Ending information</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Not specified</description>
+    </indicator>
+    <indicator position="2" value="0">
+      <description>Closed</description>
+    </indicator>
+    <indicator position="2" value="1">
+      <description>Open</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>First level of enumeration</description>
+    </subfield>
+    <subfield code="b" repeatable="false">
+      <description>Second level of enumeration</description>
+    </subfield>
+    <subfield code="c" repeatable="false">
+      <description>Third level of enumeration</description>
+    </subfield>
+    <subfield code="d" repeatable="false">
+      <description>Fourth level of enumeration</description>
+    </subfield>
+    <subfield code="e" repeatable="false">
+      <description>Fifth level of enumeration</description>
+    </subfield>
+    <subfield code="f" repeatable="false">
+      <description>Sixth level of enumeration</description>
+    </subfield>
+    <subfield code="g" repeatable="false">
+      <description>Alternative numbering scheme, first level of enumeration</description>
+    </subfield>
+    <subfield code="h" repeatable="false">
+      <description>Alternative numbering scheme, second level of enumeration</description>
+    </subfield>
+    <subfield code="i" repeatable="false">
+      <description>First level of chronology</description>
+    </subfield>
+    <subfield code="j" repeatable="false">
+      <description>Second level of chronology</description>
+    </subfield>
+    <subfield code="k" repeatable="false">
+      <description>Third level of chronology</description>
+    </subfield>
+    <subfield code="l" repeatable="false">
+      <description>Fourth level of chronology</description>
+    </subfield>
+    <subfield code="m" repeatable="false">
+      <description>Alternative numbering scheme, chronology</description>
+    </subfield>
+    <subfield code="u" repeatable="false">
+      <description>First level textual designation</description>
+    </subfield>
+    <subfield code="v" repeatable="false">
+      <description>First level of chronology, issuance</description>
+    </subfield>
+    <subfield code="x" repeatable="true">
+      <description>Nonpublic note</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Public note</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="false">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
   <field tag="365" repeatable="true">
-    <name>TRADE PRICE</name>
-    <description>Contains the current price of an item or records the special export price of an item in any currency.</description>
+    <name>Trade Price</name>
+    <description>Current price of an item or the special export price of an item in any currency.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>Price type code</description>
     </subfield>
@@ -2696,8 +3456,14 @@
     </subfield>
   </field>
   <field tag="366" repeatable="true">
-    <name>TRADE AVAILABILITY INFORMATION</name>
-    <description>Contains detailed information relating to the availability of items from publishers.</description>
+    <name>Trade Availability Information</name>
+    <description>Detailed information relating to the availability of items from publishers.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>Publishers' compressed title identification</description>
     </subfield>
@@ -2714,7 +3480,7 @@
       <description>Note</description>
     </subfield>
     <subfield code="f" repeatable="false">
-      <description>Publishers' discount category</description>
+      <description>Publisher's discount category</description>
     </subfield>
     <subfield code="g" repeatable="false">
       <description>Date made out of print</description>
@@ -2738,12 +3504,173 @@
       <description>Field link and sequence number</description>
     </subfield>
   </field>
+  <field tag="380" repeatable="true">
+    <name>Form of Work</name>
+    <description>A class or genre to which a work belongs. May be used to differentiate a work from another work with the same title.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="true">
+      <description>Form of work</description>
+    </subfield>
+    <subfield code="0" repeatable="true">
+      <description>Record control number</description>
+    </subfield>
+    <subfield code="2" repeatable="false">
+      <description>Source of term</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="381" repeatable="true">
+    <name>Other Distinguishing Characteristics of Work or Expression</name>
+    <description>Any characteristic that is not accommodated in a special field that serves to characterize a work or expression. Examples are an issuing body, arranged statement of music, version, or a geographic term. May be used to differentiate a work from another work with the same title.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="true">
+      <description>Other distinguishing characteristic</description>
+    </subfield>
+    <subfield code="u" repeatable="true">
+      <description>Uniform Resource Identifier</description>
+    </subfield>
+    <subfield code="v" repeatable="true">
+      <description>Source of information</description>
+    </subfield>
+    <subfield code="0" repeatable="true">
+      <description>Record control number</description>
+    </subfield>
+    <subfield code="2" repeatable="false">
+      <description>Source of term</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="382" repeatable="true">
+    <name>Medium of Performance</name>
+    <description>The instrumental, vocal, and/or other medium of performance for which a musical work was originally conceived or for which a musical expression is written or performed. May be used to differentiate a musical work or expression from another with the same title.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="true">
+      <description>Medium of performance</description>
+    </subfield>
+    <subfield code="0" repeatable="true">
+      <description>Record control number</description>
+    </subfield>
+    <subfield code="2" repeatable="false">
+      <description>Source of term</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="383" repeatable="true">
+    <name>Numeric Designation of Musical Work</name>
+    <description>A serial number, opus number, or thematic index number assigned to a musical work by the composer, publisher, or a musicologist. May be used to differentiate a musical work from another with the same title.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="true">
+      <description>Serial number</description>
+    </subfield>
+    <subfield code="b" repeatable="true">
+      <description>Opus number</description>
+    </subfield>
+    <subfield code="c" repeatable="true">
+      <description>Thematic index number</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="384" repeatable="false">
+    <name>Key</name>
+    <description>The set of pitch relationships that establishes a single pitch class as a tonal centre for a musical work or expression. May be used to differentiate a musical work or expression from another with the same title.</description>
+    <indicator position="1" value="#">
+      <description>Relationship to original unknown</description>
+    </indicator>
+    <indicator position="1" value="0">
+      <description>Original key</description>
+    </indicator>
+    <indicator position="1" value="1">
+      <description>Transposed key</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Key</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
   <field tag="440" repeatable="true">
-    <name>SERIES STATEMENT/ADDED ENTRY--TITLE</name>
-    <description>A series statement consisting of a series title alone.</description>
-    <indicator position="2" value="0-9">
-      <description>Number of nonfiling characters</description>
+    <name>Series Statement/Added Entry-Title</name>
+    <description>Series statement consisting of a series title alone.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
     </indicator>
+    <indicator position="2" value="0">
+      <description>No nonfiling characters</description>
+    </indicator>
+    <indicator position="2" value="1">
+      <description>Number of nonfiling characters - 1</description>
+    </indicator>
+    <indicator position="2" value="2">
+      <description>Number of nonfiling characters - 2</description>
+    </indicator>
+    <indicator position="2" value="3">
+      <description>Number of nonfiling characters - 3</description>
+    </indicator>
+    <indicator position="2" value="4">
+      <description>Number of nonfiling characters - 4</description>
+    </indicator>
+    <indicator position="2" value="5">
+      <description>Number of nonfiling characters - 5</description>
+    </indicator>
+    <indicator position="2" value="6">
+      <description>Number of nonfiling characters - 6</description>
+    </indicator>
+    <indicator position="2" value="7">
+      <description>Number of nonfiling characters - 7</description>
+    </indicator>
+    <indicator position="2" value="8">
+      <description>Number of nonfiling characters - 8</description>
+    </indicator>
+    <indicator position="2" value="9">
+      <description>Number of nonfiling characters - 9</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>Title</description>
     </subfield>
@@ -2754,11 +3681,17 @@
       <description>Name of part/section of a work</description>
     </subfield>
     <subfield code="v" repeatable="false">
-      <description>Volume number/sequential designation</description>
+      <description>Volume/sequential designation</description>
     </subfield>
+    <subfield code="w" repeatable="true">
+      <description>Bibliographic record control number</description>
+    </subfield>
     <subfield code="x" repeatable="false">
       <description>International Standard Serial Number</description>
     </subfield>
+    <subfield code="0" repeatable="true">
+      <description>Authority record control number</description>
+    </subfield>
     <subfield code="6" repeatable="false">
       <description>Linkage</description>
     </subfield>
@@ -2767,14 +3700,17 @@
     </subfield>
   </field>
   <field tag="490" repeatable="true">
-    <name>SERIES STATEMENT</name>
-    <description>A series statement for which no series added entry is traced or for which the added entry is traced in one of the 800-830 fields in a form different from the form contained in field 490.</description>
+    <name>Series Statement</name>
+    <description>Series statement for a series title.</description>
     <indicator position="1" value="0">
       <description>Series not traced</description>
     </indicator>
     <indicator position="1" value="1">
-      <description>Series traced differently</description>
+      <description>Series traced</description>
     </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="true">
       <description>Series statement</description>
     </subfield>
@@ -2782,11 +3718,14 @@
       <description>Library of Congress call number</description>
     </subfield>
     <subfield code="v" repeatable="true">
-      <description>Volume number/sequential designation</description>
+      <description>Volume/sequential designation</description>
     </subfield>
-    <subfield code="x" repeatable="false">
+    <subfield code="x" repeatable="true">
       <description>International Standard Serial Number</description>
     </subfield>
+    <subfield code="3" repeatable="false">
+      <description>Materials specified</description>
+    </subfield>
     <subfield code="6" repeatable="false">
       <description>Linkage</description>
     </subfield>
@@ -2795,8 +3734,14 @@
     </subfield>
   </field>
   <field tag="500" repeatable="true">
-    <name>GENERAL NOTE</name>
+    <name>General Note</name>
     <description>General information for which a specialized 5XX note field has not been defined.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>General note</description>
     </subfield>
@@ -2814,8 +3759,14 @@
     </subfield>
   </field>
   <field tag="501" repeatable="true">
-    <name>WITH NOTE</name>
-    <description>A note that is used when more than one bibliographic work is contained in a physical item at the time of publishing, release, issue, or execution. The works usually have distinctive titles and lack a collective title.</description>
+    <name>With Note</name>
+    <description>Note indicating that more than one bibliographical work is contained in the physical item at the time of publishing, release, issue, or execution. The works that are contained in the item usually have distinctive titles and lack a collective title.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>With note</description>
     </subfield>
@@ -2830,11 +3781,32 @@
     </subfield>
   </field>
   <field tag="502" repeatable="true">
-    <name>DISSERTATION NOTE</name>
-    <description>The designation of an academic dissertation or thesis and the institution to which it was presented. (A note that describes the relationship of a work to a dissertation or thesis is recorded in field 500).</description>
+    <name>Dissertation Note</name>
+    <description>Designation of an academic dissertation or thesis and the institution to which it was presented. Other notes indicating the relationship between the item being cataloged and the author's dissertation or thesis, such as statements indicating that the work represents or is based on the author's thesis (e.g., ) are recorded in field 500 (General Note).</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>Dissertation note</description>
     </subfield>
+    <subfield code="b" repeatable="false">
+      <description>Degree type</description>
+    </subfield>
+    <subfield code="c" repeatable="false">
+      <description>Name of granting institution</description>
+    </subfield>
+    <subfield code="d" repeatable="false">
+      <description>Year degree granted</description>
+    </subfield>
+    <subfield code="g" repeatable="true">
+      <description>Miscellaneous information</description>
+    </subfield>
+    <subfield code="o" repeatable="true">
+      <description>Dissertation identifier</description>
+    </subfield>
     <subfield code="6" repeatable="false">
       <description>Linkage</description>
     </subfield>
@@ -2843,8 +3815,14 @@
     </subfield>
   </field>
   <field tag="504" repeatable="true">
-    <name>BIBLIOGRAPHY, ETC. NOTE</name>
+    <name>Bibliography, Etc. Note</name>
     <description>Information on the presence of one or more bibliographies, discographies, filmographies, and/or other bibliographic references in a described item or in accompanying material.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>Bibliography, etc. note</description>
     </subfield>
@@ -2859,16 +3837,16 @@
     </subfield>
   </field>
   <field tag="505" repeatable="true">
-    <name>FORMATTED CONTENTS NOTE</name>
-    <description>The titles of separate works or parts of an item or the table of contents. The field may also contain statements of responsibility and volume numbers or other sequential designations.</description>
+    <name>Formatted Contents Note</name>
+    <description>Titles of separate works or parts of an item or the table of contents. The field may also contain statements of responsibility and volume numbers or other sequential designations.</description>
     <indicator position="1" value="0">
       <description>Contents</description>
     </indicator>
     <indicator position="1" value="1">
-      <description>Incomplete contents All parts of a multipart item are not listed because they were not available for analysis. Incomplete contents: may be generated for display.</description>
+      <description>Incomplete contents</description>
     </indicator>
     <indicator position="1" value="2">
-      <description>Partial contents All parts were available for analysis but only selected parts are listed. Partial contents: may be generated for display.</description>
+      <description>Partial contents</description>
     </indicator>
     <indicator position="1" value="8">
       <description>No display constant generated</description>
@@ -2902,8 +3880,8 @@
     </subfield>
   </field>
   <field tag="506" repeatable="true">
-    <name>RESTRICTIONS ON ACCESS NOTE</name>
-    <description>Information on the restrictions that govern access to or the limited distribution of the described materials.</description>
+    <name>Restrictions on Access Note</name>
+    <description>Information about restrictions imposed on access to the described materials.</description>
     <indicator position="1" value="#">
       <description>No information provided</description>
     </indicator>
@@ -2913,6 +3891,9 @@
     <indicator position="1" value="1">
       <description>Restrictions apply</description>
     </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>Terms governing access</description>
     </subfield>
@@ -2951,8 +3932,14 @@
     </subfield>
   </field>
   <field tag="507" repeatable="false">
-    <name>SCALE NOTE FOR GRAPHIC MATERIAL</name>
-    <description>For visual materials, this field contains the scale of architectural drawings or three-dimensional artifacts. For maps, the scale of an item is contained in this field only in pre-AACR 2 cataloging records. Scale information is contained in field 255 (Mathematical Data Area) in AACR 2 formulated records.</description>
+    <name>Scale Note for Graphic Material</name>
+    <description>Scale of a graphic material item given as a note. For , this field contains the scale of architectural drawings or three-dimensional artifacts. For , the scale of an item is contained in this field only in pre-AACR 2 cataloging records. Scale information is contained in field 255 (Mathematical Data Area) in AACR 2 formulated records.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>Representative fraction of scale note</description>
     </subfield>
@@ -2967,8 +3954,14 @@
     </subfield>
   </field>
   <field tag="508" repeatable="true">
-    <name>CREATION/PRODUCTION CREDITS NOTE</name>
-    <description>The names of the persons (other than members of the cast) or organizations who participated in the artistic or technical production of the work. The introductory term Credits: that customarily precedes the names is not carried in the MARC record. It may be generated based on the field tag.</description>
+    <name>Creation/Production Credits Note</name>
+    <description>Credits for persons or organizations, other than members of the cast, who have participated in the creation and/or production of the work. The introductory term is usually generated as a display constant.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>Creation/production credits note</description>
     </subfield>
@@ -2980,23 +3973,17 @@
     </subfield>
   </field>
   <field tag="510" repeatable="true">
-    <name>CITATION/REFERENCES NOTE</name>
+    <name>Citation/References Note</name>
     <description>Citations or references to published bibliographic descriptions, reviews, abstracts, or indexes of the content of the described item.</description>
     <indicator position="1" value="0">
-      <description>Coverage unknown The abstracting and indexing coverage is not specified. Indexed by: may be generated for display.</description>
+      <description>Coverage unknown</description>
     </indicator>
     <indicator position="1" value="1">
-      <description>Coverage complete The abstracting and indexing coverage includes references to all articles in a journal and/or all issues within each volume. Indexed in its entirety by: may be generated for display.</description>
+      <description>Coverage complete</description>
     </indicator>
-    <indicator position="1" value="2">
-      <description>Coverage is selective The abstracting and indexing coverage is selective. Indexed selectively by: may be generated for display.</description>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
     </indicator>
-    <indicator position="1" value="3">
-      <description>Location in source not givenReferences: may be generated for display.</description>
-    </indicator>
-    <indicator position="1" value="4">
-      <description>Location in source givenReferences: may be generated for display.</description>
-    </indicator>
     <subfield code="a" repeatable="false">
       <description>Name of source</description>
     </subfield>
@@ -3020,14 +4007,17 @@
     </subfield>
   </field>
   <field tag="511" repeatable="true">
-    <name>PARTICIPANT OR PERFORMER NOTE</name>
-    <description>The names of the participants, players, narrators, presenters, or performers.</description>
+    <name>Participant or Performer Note</name>
+    <description>Information about the participants, players, narrators, presenters, or performers.</description>
     <indicator position="1" value="0">
       <description>No display constant generated</description>
     </indicator>
     <indicator position="1" value="1">
-      <description>CastCast: may be generated for display.</description>
+      <description>Cast</description>
     </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>Participant or performer note</description>
     </subfield>
@@ -3039,8 +4029,14 @@
     </subfield>
   </field>
   <field tag="513" repeatable="true">
-    <name>TYPE OF REPORT AND PERIOD COVERED NOTE</name>
+    <name>Type of Report and Period Covered Note</name>
     <description>Information on the type of report and the period covered by the report.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>Type of report</description>
     </subfield>
@@ -3055,8 +4051,14 @@
     </subfield>
   </field>
   <field tag="514" repeatable="false">
-    <name>DATA QUALITY NOTE</name>
+    <name>Data Quality Note</name>
     <description>Provides a general assessment of the quality of the data set constituting the item.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>Attribute accuracy report</description>
     </subfield>
@@ -3107,8 +4109,14 @@
     </subfield>
   </field>
   <field tag="515" repeatable="true">
-    <name>NUMBERING PECULIARITIES NOTE</name>
-    <description>An unformatted description of irregularities and peculiarities in numbering or publishing patterns, report year coverage, revised editions, and/or issuance in parts.</description>
+    <name>Numbering Peculiarities Note</name>
+    <description>Unformatted note giving irregularities and peculiarities in numbering or publishing patterns, report year coverage, revised editions, and/or issuance in parts.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>Numbering peculiarities note</description>
     </subfield>
@@ -3120,14 +4128,17 @@
     </subfield>
   </field>
   <field tag="516" repeatable="true">
-    <name>TYPE OF COMPUTER FILE OR DATA NOTE</name>
-    <description>A general descriptor that characterizes a file (e.g., text, computer program, numeric). Specific information such as the form or genre of textual material (e.g., biography, indexes) also may be included. The general type of file is coded in field 008/26 (Type of computer file).</description>
+    <name>Type of Computer File or Data Note</name>
+    <description>General descriptor that characterizes the file (e.g., text, computer program, numeric). Specific information, such as the form or genre of textual material (e.g., biography, dictionaries, indexes) may be included. The general type of computer file information in coded form is recorded in 008/26 (Type of computer file).</description>
     <indicator position="1" value="#">
       <description>Type of file</description>
     </indicator>
     <indicator position="1" value="8">
       <description>No display constant generated</description>
     </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>Type of computer file or data note</description>
     </subfield>
@@ -3139,11 +4150,32 @@
     </subfield>
   </field>
   <field tag="518" repeatable="true">
-    <name>DATE/TIME AND PLACE OF AN EVENT NOTE</name>
-    <description>Textual information on the date/time and/or place of creation, capture, or broadcast associated with an event or the finding of a naturally occurring object. This information in coded form is contained in field 033 (Date/Time and Place of an Event).</description>
+    <name>Date/Time and Place of an Event Note</name>
+    <description>Note on the date/time and/or place of creation, capture, recording, filming, execution, or broadcast associated with an event or the finding of a naturally occurring object. Field 033 (Date/Time and Place of an Event) contains the same information in coded form.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>Date/time and place of an event note</description>
     </subfield>
+    <subfield code="d" repeatable="true">
+      <description>Date of event</description>
+    </subfield>
+    <subfield code="o" repeatable="false">
+      <description>Other event information</description>
+    </subfield>
+    <subfield code="p" repeatable="true">
+      <description>Place of event</description>
+    </subfield>
+    <subfield code="0" repeatable="true">
+      <description>Record control number</description>
+    </subfield>
+    <subfield code="2" repeatable="true">
+      <description>Source of term</description>
+    </subfield>
     <subfield code="3" repeatable="false">
       <description>Materials specified</description>
     </subfield>
@@ -3155,8 +4187,8 @@
     </subfield>
   </field>
   <field tag="520" repeatable="true">
-    <name>SUMMARY, ETC.</name>
-    <description>Unformatted information that describes the scope and general contents of the materials. This could be a summary, abstract, annotation, review, or only a phrase describing the material.</description>
+    <name>Summary, Etc.</name>
+    <description>Unformatted information that describes the scope and general contents of the materials.</description>
     <indicator position="1" value="#">
       <description>Summary</description>
     </indicator>
@@ -3172,18 +4204,30 @@
     <indicator position="1" value="3">
       <description>Abstract</description>
     </indicator>
+    <indicator position="1" value="4">
+      <description>Content advice</description>
+    </indicator>
     <indicator position="1" value="8">
       <description>No display constant generated</description>
     </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
-      <description>Summary, etc. note</description>
+      <description>Summary, etc.</description>
     </subfield>
     <subfield code="b" repeatable="false">
       <description>Expansion of summary note</description>
     </subfield>
+    <subfield code="c" repeatable="false">
+      <description>Assigning source</description>
+    </subfield>
     <subfield code="u" repeatable="true">
       <description>Uniform Resource Identifier</description>
     </subfield>
+    <subfield code="2" repeatable="false">
+      <description>Source</description>
+    </subfield>
     <subfield code="3" repeatable="false">
       <description>Materials specified</description>
     </subfield>
@@ -3195,7 +4239,7 @@
     </subfield>
   </field>
   <field tag="521" repeatable="true">
-    <name>TARGET AUDIENCE NOTE</name>
+    <name>Target Audience Note</name>
     <description>Information that identifies the specific audience or intellectual level for which the content of the described item is considered appropriate.</description>
     <indicator position="1" value="#">
       <description>Audience</description>
@@ -3213,11 +4257,14 @@
       <description>Special audience characteristics</description>
     </indicator>
     <indicator position="1" value="4">
-      <description>Motivation interest level</description>
+      <description>Motivation/interest level</description>
     </indicator>
     <indicator position="1" value="8">
       <description>No display constant generated</description>
     </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="true">
       <description>Target audience note</description>
     </subfield>
@@ -3235,14 +4282,17 @@
     </subfield>
   </field>
   <field tag="522" repeatable="true">
-    <name>GEOGRAPHIC COVERAGE NOTE</name>
-    <description>Information on the geographic coverage of the described material (usually survey material). This information in coded form may be contained in field 052 (Geographic Classification Code).</description>
+    <name>Geographic Coverage Note</name>
+    <description>Information about the geographic coverage of the described material (usually survey material). This information in coded form may be contained in field 052 (Geographic Classification Code).</description>
     <indicator position="1" value="#">
       <description>Geographic coverage</description>
     </indicator>
     <indicator position="1" value="8">
       <description>No display constant generated</description>
     </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>Geographic coverage note</description>
     </subfield>
@@ -3254,14 +4304,17 @@
     </subfield>
   </field>
   <field tag="524" repeatable="true">
-    <name>PREFERRED CITATION OF DESCRIBED MATERIALS NOTE</name>
-    <description>The format of the citation of the described materials that is preferred by the custodian.</description>
+    <name>Preferred Citation of Described Materials Note</name>
+    <description>Format for the citation of the described materials that is preferred by the custodian.</description>
     <indicator position="1" value="#">
       <description>Cite as</description>
     </indicator>
     <indicator position="1" value="8">
       <description>No display constant generated</description>
     </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>Preferred citation of described materials note</description>
     </subfield>
@@ -3279,8 +4332,14 @@
     </subfield>
   </field>
   <field tag="525" repeatable="true">
-    <name>SUPPLEMENT NOTE</name>
-    <description>Information on the existence of supplements or special issues (usually unnamed) that are neither cataloged as separate records nor recorded in field 770 (Supplement/Special Issue Entry).</description>
+    <name>Supplement Note</name>
+    <description>Information on the existence of supplements or special issues that are neither cataloged in separate records nor recorded in a linking entry field 770 (Supplement/Special Issue Entry).</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>Supplement note</description>
     </subfield>
@@ -3292,14 +4351,17 @@
     </subfield>
   </field>
   <field tag="526" repeatable="true">
-    <name>STUDY PROGRAM INFORMATION NOTE</name>
-    <description>A note giving the name of a study program which uses the title described in the record. Details about the study program data elements are also contained in the field. Field 526 is generally used for formal curriculum-based study or reading programs.</description>
+    <name>Study Program Information Note</name>
+    <description>Note giving the name of a study program which uses the title described in the record. Details about the study program data elements are also contained in the field. Field 526 is generally used for formal curriculum-based study or reading programs.</description>
     <indicator position="1" value="0">
       <description>Reading program</description>
     </indicator>
     <indicator position="1" value="8">
       <description>No display constant generated</description>
     </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>Program name</description>
     </subfield>
@@ -3332,8 +4394,14 @@
     </subfield>
   </field>
   <field tag="530" repeatable="true">
-    <name>ADDITIONAL PHYSICAL FORM AVAILABLE NOTE</name>
-    <description>Availability information concerning a different physical format in which the described item is available.</description>
+    <name>Additional Physical Form Available Note</name>
+    <description>Information concerning a different physical format in which the described item is available.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>Additional physical form available note</description>
     </subfield>
@@ -3360,8 +4428,14 @@
     </subfield>
   </field>
   <field tag="533" repeatable="true">
-    <name>REPRODUCTION NOTE</name>
+    <name>Reproduction Note</name>
     <description>Descriptive data for a reproduction of an original item when the main portion of the bibliographic record describes the original item and the data differ.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>Type of reproduction</description>
     </subfield>
@@ -3389,19 +4463,28 @@
     <subfield code="3" repeatable="false">
       <description>Materials specified</description>
     </subfield>
-    <subfield code="6" repeatable="false">
-      <description>Linkage</description>
+    <subfield code="5" repeatable="false">
+      <description>Institution to which field applies</description>
     </subfield>
     <subfield code="7" repeatable="false">
       <description>Fixed-length data elements of reproduction</description>
     </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
     <subfield code="8" repeatable="true">
       <description>Field link and sequence number</description>
     </subfield>
   </field>
   <field tag="534" repeatable="true">
-    <name>ORIGINAL VERSION NOTE</name>
+    <name>Original Version Note</name>
     <description>Descriptive data for an original item when the main portion of the bibliographic record describes a reproduction of that item and the data differ. Details relevant to the original are given in field 534.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>Main entry of original</description>
     </subfield>
@@ -3429,6 +4512,9 @@
     <subfield code="n" repeatable="true">
       <description>Note about original</description>
     </subfield>
+    <subfield code="o" repeatable="true">
+      <description>Other resource identifier</description>
+    </subfield>
     <subfield code="p" repeatable="false">
       <description>Introductory phrase</description>
     </subfield>
@@ -3441,6 +4527,9 @@
     <subfield code="z" repeatable="true">
       <description>International Standard Book Number</description>
     </subfield>
+    <subfield code="3" repeatable="false">
+      <description>Materials specified</description>
+    </subfield>
     <subfield code="6" repeatable="false">
       <description>Linkage</description>
     </subfield>
@@ -3449,14 +4538,17 @@
     </subfield>
   </field>
   <field tag="535" repeatable="true">
-    <name>LOCATION OF ORIGINALS/DUPLICATES NOTE</name>
-    <description>The name and address of the repository that has custody of the original or a duplicate copy of the described material when either is housed in a repository different from that of the material being described.</description>
+    <name>Location of Originals/Duplicates Note</name>
+    <description>Name and address of the repository with custody over originals or duplicates of the described materials. This field is used only when the originals or duplicates are housed in a repository different from that of the materials being described.</description>
     <indicator position="1" value="1">
       <description>Holder of originals</description>
     </indicator>
     <indicator position="1" value="2">
       <description>Holder of duplicates</description>
     </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>Custodian</description>
     </subfield>
@@ -3483,8 +4575,14 @@
     </subfield>
   </field>
   <field tag="536" repeatable="true">
-    <name>FUNDING INFORMATION NOTE</name>
-    <description>Contract, grant, and/or project numbers when the described material is the result of a funded project. Information concerning the sponsor or funding agency also may be included.</description>
+    <name>Funding Information Note</name>
+    <description>Contract, grant, and project numbers when the material results from a funded project. Information concerning the sponsor or funding agency also may be included.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>Text of note</description>
     </subfield>
@@ -3517,8 +4615,14 @@
     </subfield>
   </field>
   <field tag="538" repeatable="true">
-    <name>SYSTEM DETAILS NOTE</name>
+    <name>System Details Note</name>
     <description>Technical information about an item, such as the presence or absence of certain kinds of codes; or the physical characteristics of a computer file, such as recording densities, parity, blocking factors, mode of access, software programming language, computer requirements, peripheral requirements, trade name or recording systems, number of lines of resolution, and modulation frequency. For sound and videorecordings, information about the trade name or recording system(s) (e.g., VHS), modulation frequency and number of lines of resolution may be included.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>System details note</description>
     </subfield>
@@ -3531,6 +4635,9 @@
     <subfield code="3" repeatable="false">
       <description>Materials specified</description>
     </subfield>
+    <subfield code="5" repeatable="true">
+      <description>Institution to which field applies</description>
+    </subfield>
     <subfield code="6" repeatable="false">
       <description>Linkage</description>
     </subfield>
@@ -3539,8 +4646,14 @@
     </subfield>
   </field>
   <field tag="540" repeatable="true">
-    <name>TERMS GOVERNING USE AND REPRODUCTION NOTE</name>
-    <description>Terms governing the use of the described materials (e.g., copyrights, film rights, trade rights) after access has been provided.</description>
+    <name>Terms Governing Use and Reproduction Note</name>
+    <description>Terms governing the use of the materials after access has been provided. The field includes, but is not limited to, copyrights, film rights, trade restrictions, etc. that restrict the right to reproduce, exhibit, fictionalize, quote, etc.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>Terms governing use and reproduction</description>
     </subfield>
@@ -3570,8 +4683,8 @@
     </subfield>
   </field>
   <field tag="541" repeatable="true">
-    <name>IMMEDIATE SOURCE OF ACQUISITION NOTE</name>
-    <description>Information on the immediate source of acquisition of the described materials. The field is used primarily for original or historical items or other archival collections.</description>
+    <name>Immediate Source of Acquisition Note</name>
+    <description>Information about the immediate source of acquisition of the described materials and is used primarily with original or historical items, or other archival collections.</description>
     <indicator position="1" value="#">
       <description>No information provided</description>
     </indicator>
@@ -3581,6 +4694,9 @@
     <indicator position="1" value="1">
       <description>Not private</description>
     </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>Source of acquisition</description>
     </subfield>
@@ -3621,18 +4737,106 @@
       <description>Field link and sequence number</description>
     </subfield>
   </field>
+  <field tag="542" repeatable="true">
+    <name>Information Relating to Copyright Status</name>
+    <description>Information known about the item that may be used to determine copyright status.</description>
+    <indicator position="1" value="#">
+      <description>No information provided</description>
+    </indicator>
+    <indicator position="1" value="0">
+      <description>Private</description>
+    </indicator>
+    <indicator position="1" value="1">
+      <description>Not private</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Personal creator</description>
+    </subfield>
+    <subfield code="b" repeatable="false">
+      <description>Personal creator death date</description>
+    </subfield>
+    <subfield code="c" repeatable="false">
+      <description>Corporate creator</description>
+    </subfield>
+    <subfield code="d" repeatable="true">
+      <description>Copyright holder</description>
+    </subfield>
+    <subfield code="e" repeatable="true">
+      <description>Copyright holder contact information</description>
+    </subfield>
+    <subfield code="f" repeatable="true">
+      <description>Copyright statement</description>
+    </subfield>
+    <subfield code="g" repeatable="false">
+      <description>Copyright date</description>
+    </subfield>
+    <subfield code="h" repeatable="true">
+      <description>Copyright renewal date</description>
+    </subfield>
+    <subfield code="i" repeatable="false">
+      <description>Publication date</description>
+    </subfield>
+    <subfield code="j" repeatable="false">
+      <description>Creation date</description>
+    </subfield>
+    <subfield code="k" repeatable="true">
+      <description>Publisher</description>
+    </subfield>
+    <subfield code="l" repeatable="false">
+      <description>Copyright status</description>
+    </subfield>
+    <subfield code="m" repeatable="false">
+      <description>Publication status</description>
+    </subfield>
+    <subfield code="n" repeatable="true">
+      <description>Note</description>
+    </subfield>
+    <subfield code="o" repeatable="false">
+      <description>Research date</description>
+    </subfield>
+    <subfield code="p" repeatable="true">
+      <description>Country of publication or creation</description>
+    </subfield>
+    <subfield code="q" repeatable="false">
+      <description>Supplying agency</description>
+    </subfield>
+    <subfield code="r" repeatable="false">
+      <description>Jurisdiction of copyright assessment</description>
+    </subfield>
+    <subfield code="s" repeatable="false">
+      <description>Source of information</description>
+    </subfield>
+    <subfield code="u" repeatable="true">
+      <description>Uniform Resource Identifier</description>
+    </subfield>
+    <subfield code="3" repeatable="false">
+      <description>Materials specified</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
   <field tag="544" repeatable="true">
-    <name>LOCATION OF OTHER ARCHIVAL MATERIALS NOTE</name>
-    <description>The name and address of the custodian of materials that, at a previous time, have been part of the same collection or record group as the described materials.</description>
+    <name>Location of Other Archival Materials Note</name>
+    <description>Name and address of custodians of archival materials related to the described materials by provenance, specifically by having been, at a previous time, a part of the same collection or record group.</description>
     <indicator position="1" value="#">
       <description>No information provided</description>
     </indicator>
     <indicator position="1" value="0">
-      <description>Associated materials Indicates that the other materials identified in the note have the same provenance but reside in a different repository.</description>
+      <description>Associated materials</description>
     </indicator>
     <indicator position="1" value="1">
-      <description>Related materials Indicates that the other materials identified in the note share the sphere of activity, reside in the same repository, but have different provenance.</description>
+      <description>Related materials</description>
     </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="true">
       <description>Custodian</description>
     </subfield>
@@ -3662,8 +4866,8 @@
     </subfield>
   </field>
   <field tag="545" repeatable="true">
-    <name>BIOGRAPHICAL OR HISTORICAL DATA</name>
-    <description>Biographical information about an individual or historical information about an institution or an event used as the main entry of the bibliographic record for the described materials. When a distinction between levels of detail is required, a brief summary is given in subfield $a and a fuller annotation is given in subfield $b.</description>
+    <name>Biographical or Historical Data</name>
+    <description>Biographical information about an individual or historical information about an institution or event used as the main entry for the item being cataloged. When a distinction between levels of detail is required, a brief summary is given in subfield $a and a fuller annotation is given in subfield $b.</description>
     <indicator position="1" value="#">
       <description>No information provided</description>
     </indicator>
@@ -3673,8 +4877,11 @@
     <indicator position="1" value="1">
       <description>Administrative history</description>
     </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
-      <description>Biographical or historical note</description>
+      <description>Biographical or historical data</description>
     </subfield>
     <subfield code="b" repeatable="false">
       <description>Expansion</description>
@@ -3690,8 +4897,14 @@
     </subfield>
   </field>
   <field tag="546" repeatable="true">
-    <name>LANGUAGE NOTE</name>
+    <name>Language Note</name>
     <description>Textual information on the language of the described materials. A description of the alphabet, script, or other symbol system (e.g., arabic alphabet, ASCII, musical notation system, bar code, logarithmic graphing) may also be included. Coded language information is contained in fields 008/35-37 (Language) and/or 041 (Language code).</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>Language note</description>
     </subfield>
@@ -3709,8 +4922,14 @@
     </subfield>
   </field>
   <field tag="547" repeatable="true">
-    <name>FORMER TITLE COMPLEXITY NOTE</name>
-    <description>A description of the complex relationship between former titles proper whenever an intelligible note cannot be generated from the data in field 247 (Former Title).</description>
+    <name>Former Title Complexity Note</name>
+    <description>Description of the complex relationship between titles proper whenever an intelligible note cannot be system generated from the data in field 247 (Former Title).</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>Former title complexity note</description>
     </subfield>
@@ -3722,8 +4941,14 @@
     </subfield>
   </field>
   <field tag="550" repeatable="true">
-    <name>ISSUING BODY NOTE</name>
+    <name>Issuing Body Note</name>
     <description>Information about the current and former issuing bodies of a continuing resource.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>Issuing body note</description>
     </subfield>
@@ -3735,8 +4960,14 @@
     </subfield>
   </field>
   <field tag="552" repeatable="true">
-    <name>ENTITY AND ATTRIBUTE INFORMATION NOTE</name>
-    <description>A description of the information content of the data set, including the entity types, their attributes, and the domains from which attribute values may be assigned.</description>
+    <name>Entity and Attribute Information Note</name>
+    <description>Description of the information content of the data set, including the entity types, their attributes, and the domains from which attribute values may be assigned.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>Entity type label</description>
     </subfield>
@@ -3768,7 +4999,7 @@
       <description>Attribute units of measurement and resolution</description>
     </subfield>
     <subfield code="k" repeatable="false">
-      <description>Beginning date and ending date of attribute values</description>
+      <description>Beginning and ending date of attribute values</description>
     </subfield>
     <subfield code="l" repeatable="false">
       <description>Attribute value accuracy</description>
@@ -3799,17 +5030,20 @@
     </subfield>
   </field>
   <field tag="555" repeatable="true">
-    <name>CUMULATIVE INDEX/FINDING AIDS NOTE</name>
-    <description>Information on the availability of cumulative indexes for continuing resources or finding aids and similar control materials for archival and manuscripts control and visual materials.</description>
+    <name>Cumulative Index/Finding Aids Note</name>
+    <description>Information on the availability of cumulative indexes for continuing resources or finding aids and similar control materials for archival and manuscripts control and visual materials whose only or major focus is the described material.</description>
     <indicator position="1" value="#">
-      <description>IndexesIndexes: may be generated for display.</description>
+      <description>Indexes</description>
     </indicator>
     <indicator position="1" value="0">
-      <description>Finding aidsFinding aids: may be generated for display.</description>
+      <description>Finding aids</description>
     </indicator>
     <indicator position="1" value="8">
       <description>No display constant generated</description>
     </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>Cumulative index/finding aids note</description>
     </subfield>
@@ -3836,14 +5070,17 @@
     </subfield>
   </field>
   <field tag="556" repeatable="true">
-    <name>INFORMATION ABOUT DOCUMENTATION NOTE</name>
-    <description>Information about the documentation of a file, e.g., codebooks that explain the content and use of the file.</description>
+    <name>Information About Documentation Note</name>
+    <description>Information about the documentation of the described materials, such as codebooks which explain the contents and use of the file or a users’ manual to a serial.</description>
     <indicator position="1" value="#">
-      <description>DocumentationDocumentation: may be generated for display.</description>
+      <description>Documentation</description>
     </indicator>
     <indicator position="1" value="8">
       <description>No display constant generated</description>
     </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>Information about documentation note</description>
     </subfield>
@@ -3858,8 +5095,8 @@
     </subfield>
   </field>
   <field tag="561" repeatable="true">
-    <name>OWNERSHIP AND CUSTODIAL HISTORY</name>
-    <description>A copy-specific field that contains information concerning the ownership and custodial history of the described materials from the time of their creation to the time of their accessioning, including the time at which individual items or group of items were first brought together in their current arrangement or collation.</description>
+    <name>Ownership and Custodial History</name>
+    <description>Copy-specific field that contains information concerning the ownership and custodial history of the described materials from the time of their creation to the time of their accessioning, including the time at which individual items or groups of items were first brought together in their current arrangement or collation.</description>
     <indicator position="1" value="#">
       <description>No information provided</description>
     </indicator>
@@ -3869,6 +5106,9 @@
     <indicator position="1" value="1">
       <description>Not private</description>
     </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>History</description>
     </subfield>
@@ -3886,8 +5126,14 @@
     </subfield>
   </field>
   <field tag="562" repeatable="true">
-    <name>COPY AND VERSION IDENTIFICATION NOTE</name>
-    <description>Information that distinguishes the copy or version of materials held by an archive or manuscript repository when more than one copy or version exists or could exist.</description>
+    <name>Copy and Version Identification Note</name>
+    <description>Information that distinguishes the copy(s) or version(s) of materials held by an archive or manuscript repository when more than one copy or version exists or could exist.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="true">
       <description>Identifying markings</description>
     </subfield>
@@ -3917,8 +5163,14 @@
     </subfield>
   </field>
   <field tag="563" repeatable="true">
-    <name>BINDING INFORMATION</name>
-    <description>Intended primarily for use with antiquarian materials, rare books and other special collections.</description>
+    <name>Binding Information</name>
+    <description>Binding information intended primarily for use with antiquarian materials, rare books and other special collections.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>Binding note</description>
     </subfield>
@@ -3939,8 +5191,8 @@
     </subfield>
   </field>
   <field tag="565" repeatable="true">
-    <name>CASE FILE CHARACTERISTICS NOTE</name>
-    <description>Information on the content, characteristics, and/or the number of cases or variables making up a case file or a database.</description>
+    <name>Case File Characteristics Note</name>
+    <description>Information about the content and characteristics of case files and/or the number of cases or variables making up a case file or a database.</description>
     <indicator position="1" value="#">
       <description>File size</description>
     </indicator>
@@ -3950,6 +5202,9 @@
     <indicator position="1" value="8">
       <description>No display constant generated</description>
     </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>Number of cases/variables</description>
     </subfield>
@@ -3976,14 +5231,17 @@
     </subfield>
   </field>
   <field tag="567" repeatable="true">
-    <name>METHODOLOGY NOTE</name>
-    <description>Information on significant methodological characteristics of the material, such as the algorithm, sampling procedures, or validation characteristics.</description>
+    <name>Methodology Note</name>
+    <description>Information concerning significant methodological characteristics of the material, such as the algorithm, universe description, sampling procedures, classification, or validation characteristics.</description>
     <indicator position="1" value="#">
       <description>Methodology</description>
     </indicator>
     <indicator position="1" value="8">
       <description>No display constant generated</description>
     </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>Methodology note</description>
     </subfield>
@@ -3995,8 +5253,14 @@
     </subfield>
   </field>
   <field tag="580" repeatable="true">
-    <name>LINKING ENTRY COMPLEXITY NOTE</name>
-    <description>A description of the complex relationship between the described item and other items when an intelligible note cannot be generated from data in the linking entry fields 760-787.</description>
+    <name>Linking Entry Complexity Note</name>
+    <description>Description of the complex relationship between the item described in the record and other items that cannot be adequately generated from the linking entry fields 760-787.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>Linking entry complexity note</description>
     </subfield>
@@ -4008,14 +5272,17 @@
     </subfield>
   </field>
   <field tag="581" repeatable="true">
-    <name>PUBLICATIONS ABOUT DESCRIBED MATERIALS NOTE</name>
-    <description>A citation to or information about a publication that is a study or analysis of the described materials.</description>
+    <name>Publications About Described Materials Note</name>
+    <description>Citation or information about a publication that is based on the use, study, or analysis of the materials described in the record.</description>
     <indicator position="1" value="#">
       <description>Publications</description>
     </indicator>
     <indicator position="1" value="8">
       <description>No display constant generated</description>
     </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>Publications about described materials note</description>
     </subfield>
@@ -4033,8 +5300,8 @@
     </subfield>
   </field>
   <field tag="583" repeatable="true">
-    <name>ACTION NOTE</name>
-    <description>Contains information about processing, reference, and preservation actions.</description>
+    <name>Action Note</name>
+    <description>Information about processing, reference, and preservation actions.</description>
     <indicator position="1" value="#">
       <description>No information provided</description>
     </indicator>
@@ -4044,6 +5311,9 @@
     <indicator position="1" value="1">
       <description>Not private</description>
     </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>Action</description>
     </subfield>
@@ -4109,8 +5379,14 @@
     </subfield>
   </field>
   <field tag="584" repeatable="true">
-    <name>ACCUMULATION AND FREQUENCY OF USE NOTE</name>
-    <description>Information on the rates of accumulation (for continuing, open-ended accessions) and/or the rate of reference use of the described materials.</description>
+    <name>Accumulation and Frequency of Use Note</name>
+    <description>Measurements of and information about the rates of accumulation (for continuing, open-ended accessions) and/or the rate of reference use of the described materials.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="true">
       <description>Accumulation</description>
     </subfield>
@@ -4131,8 +5407,14 @@
     </subfield>
   </field>
   <field tag="585" repeatable="true">
-    <name>EXHIBITIONS NOTE</name>
-    <description>A copy-specific field that contains a citation to an exhibition where the described materials have been shown.</description>
+    <name>Exhibitions Note</name>
+    <description>Copy-specific field that contains a note which cites exhibitions where the material described has been shown.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>Exhibitions note</description>
     </subfield>
@@ -4150,7 +5432,7 @@
     </subfield>
   </field>
   <field tag="586" repeatable="true">
-    <name>AWARDS NOTE</name>
+    <name>Awards Note</name>
     <description>Information on awards associated with the described item.</description>
     <indicator position="1" value="#">
       <description>Awards</description>
@@ -4158,6 +5440,9 @@
     <indicator position="1" value="8">
       <description>No display constant generated</description>
     </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>Awards note</description>
     </subfield>
@@ -4171,123 +5456,21 @@
       <description>Field link and sequence number</description>
     </subfield>
   </field>
-  <field tag="59X" repeatable="false">
-    <name/>
-    <description>The 590-599 fields are reserved for local use and local definition.</description>
-    <indicator position="1" value="0">
-      <description>Forename</description>
+  <field tag="588" repeatable="true">
+    <name>Source of Description Note</name>
+    <description>Information used for tracking and controlling the metadata contained in the record. It includes general and specific source of description notes that are especially of interest to other catalogers.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
     </indicator>
-    <indicator position="1" value="1">
-      <description>Surname</description>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
     </indicator>
-    <indicator position="1" value="3">
-      <description>Family name</description>
-    </indicator>
-    <indicator position="2" value="0">
-      <description>Library of Congress Subject Headings The subject added entry conforms to and is appropriate for use in the Library of Congress Subject Headings (LCSH) and the Name authority files.</description>
-    </indicator>
-    <indicator position="2" value="1">
-      <description>LC subject headings for children's literature The subject added entry conforms to the "AC Subject Headings" section of the LCSH and is appropriate for use in the LC Annotated Card Program.</description>
-    </indicator>
-    <indicator position="2" value="2">
-      <description>Medical Subject Headings The subject added entry conforms to the NLM authority files.</description>
-    </indicator>
-    <indicator position="2" value="3">
-      <description>National Agricultural Library subject authority file The subject added entry conforms to the NAL subject authority file.</description>
-    </indicator>
-    <indicator position="2" value="4">
-      <description>Source not specified The subject added entry conforms to a controlled list that cannot be identified by another defined value or by a code in subfield $2.</description>
-    </indicator>
-    <indicator position="2" value="5">
-      <description>Canadian Subject Headings The subject added entry conforms to and is appropriate for use in the Canadian Subject Headings and the LAC authority files.</description>
-    </indicator>
-    <indicator position="2" value="6">
-      <description>R&#xC3;&#xA9;pertoire de vedettes-mati&#xC3;&#xA8;re The subject added entry conforms to and is appropriate for use in the R&#xC3;&#xA9;pertoire de vedettes-mati&#xC3;&#xA8;re and the LAC authority fields</description>
-    </indicator>
-    <indicator position="2" value="7">
-      <description>Source specified in subfield $2</description>
-    </indicator>
     <subfield code="a" repeatable="false">
-      <description>Personal name</description>
+      <description>Source of description note</description>
     </subfield>
-    <subfield code="b" repeatable="false">
-      <description>Numeration</description>
+    <subfield code="5" repeatable="false">
+      <description>Institution to which field applies</description>
     </subfield>
-    <subfield code="c" repeatable="true">
-      <description>Titles and other words associated with a name</description>
-    </subfield>
-    <subfield code="d" repeatable="false">
-      <description>Dates associated with a name</description>
-    </subfield>
-    <subfield code="e" repeatable="true">
-      <description>Relator term</description>
-    </subfield>
-    <subfield code="f" repeatable="false">
-      <description>Date of a work</description>
-    </subfield>
-    <subfield code="g" repeatable="false">
-      <description>Miscellaneous information</description>
-    </subfield>
-    <subfield code="h" repeatable="false">
-      <description>Medium</description>
-    </subfield>
-    <subfield code="j" repeatable="true">
-      <description>Attribution qualifier</description>
-    </subfield>
-    <subfield code="k" repeatable="true">
-      <description>Form subheading</description>
-    </subfield>
-    <subfield code="l" repeatable="false">
-      <description>Language of a work</description>
-    </subfield>
-    <subfield code="m" repeatable="true">
-      <description>Medium of performance for music</description>
-    </subfield>
-    <subfield code="n" repeatable="true">
-      <description>Number of part/section of a work</description>
-    </subfield>
-    <subfield code="o" repeatable="false">
-      <description>Arranged statement for music</description>
-    </subfield>
-    <subfield code="p" repeatable="true">
-      <description>Name of part/section of a work</description>
-    </subfield>
-    <subfield code="q" repeatable="false">
-      <description>Fuller form of name</description>
-    </subfield>
-    <subfield code="r" repeatable="false">
-      <description>Key for music</description>
-    </subfield>
-    <subfield code="s" repeatable="false">
-      <description>Version</description>
-    </subfield>
-    <subfield code="t" repeatable="false">
-      <description>Title of a work</description>
-    </subfield>
-    <subfield code="u" repeatable="false">
-      <description>Affiliation</description>
-    </subfield>
-    <subfield code="v" repeatable="true">
-      <description>Form subdivision</description>
-    </subfield>
-    <subfield code="x" repeatable="true">
-      <description>General subdivision</description>
-    </subfield>
-    <subfield code="y" repeatable="true">
-      <description>Chronological subdivision</description>
-    </subfield>
-    <subfield code="z" repeatable="true">
-      <description>Geographic subdivision</description>
-    </subfield>
-    <subfield code="2" repeatable="false">
-      <description>Source of heading or term</description>
-    </subfield>
-    <subfield code="3" repeatable="false">
-      <description>Materials specified</description>
-    </subfield>
-    <subfield code="4" repeatable="true">
-      <description>Relator code</description>
-    </subfield>
     <subfield code="6" repeatable="false">
       <description>Linkage</description>
     </subfield>
@@ -4295,9 +5478,13 @@
       <description>Field link and sequence number</description>
     </subfield>
   </field>
+  <field tag="59X" repeatable="true">
+    <name>Local Notes</name>
+    <description>Reserved in MARC for local use and local definition.</description>
+  </field>
   <field tag="600" repeatable="true">
-    <name>SUBJECT ADDED ENTRY--PERSONAL NAME</name>
-    <description>A subject added entry in which the entry element is a personal name.</description>
+    <name>Subject Added Entry-Personal Name</name>
+    <description>Subject added entry in which the entry element is a personal name.</description>
     <indicator position="1" value="0">
       <description>Forename</description>
     </indicator>
@@ -4308,25 +5495,25 @@
       <description>Family name</description>
     </indicator>
     <indicator position="2" value="0">
-      <description>Library of Congress Subject Headings The subject added entry conforms to and is appropriate for use in the Library of Congress Subject Headings (LCSH) and the Name authority files.</description>
+      <description>Library of Congress Subject Headings</description>
     </indicator>
     <indicator position="2" value="1">
-      <description>LC subject headings for children's literature The subject added entry conforms to the "AC Subject Headings" section of the LCSH and is appropriate for use in the LC Annotated Card Program.</description>
+      <description>LC subject headings for children's literature</description>
     </indicator>
     <indicator position="2" value="2">
-      <description>Medical Subject Headings The subject added entry conforms to the NLM authority files.</description>
+      <description>Medical Subject Headings</description>
     </indicator>
     <indicator position="2" value="3">
-      <description>National Agricultural Library subject authority file The subject added entry conforms to the NAL subject authority file.</description>
+      <description>National Agricultural Library subject authority file</description>
     </indicator>
     <indicator position="2" value="4">
-      <description>Source not specified The subject added entry conforms to a controlled list that cannot be identified by another defined value or by a code in subfield $2.</description>
+      <description>Source not specified</description>
     </indicator>
     <indicator position="2" value="5">
-      <description>Canadian Subject Headings The subject added entry conforms to and is appropriate for use in the Canadian Subject Headings and the LAC authority files.</description>
+      <description>Canadian Subject Headings</description>
     </indicator>
     <indicator position="2" value="6">
-      <description>R&#xC3;&#xA9;pertoire de vedettes-mati&#xC3;&#xA8;re The subject added entry conforms to and is appropriate for use in the R&#xC3;&#xA9;pertoire de vedettes-mati&#xC3;&#xA8;re and the LAC authority fields</description>
+      <description>Répertoire de vedettes-matière</description>
     </indicator>
     <indicator position="2" value="7">
       <description>Source specified in subfield $2</description>
@@ -4403,6 +5590,9 @@
     <subfield code="z" repeatable="true">
       <description>Geographic subdivision</description>
     </subfield>
+    <subfield code="0" repeatable="true">
+      <description>Authority record control number</description>
+    </subfield>
     <subfield code="2" repeatable="false">
       <description>Source of heading or term</description>
     </subfield>
@@ -4420,8 +5610,8 @@
     </subfield>
   </field>
   <field tag="610" repeatable="true">
-    <name>SUBJECT ADDED ENTRY--CORPORATE NAME</name>
-    <description>A subject added entry in which the entry element is a corporate name.</description>
+    <name>Subject Added Entry-Corporate Name</name>
+    <description>Subject added entry in which the entry element is a corporate name.</description>
     <indicator position="1" value="0">
       <description>Inverted name</description>
     </indicator>
@@ -4432,25 +5622,25 @@
       <description>Name in direct order</description>
     </indicator>
     <indicator position="2" value="0">
-      <description>Library of Congress Subject Headings The subject added entry conforms to and is appropriate for use in the Library of Congress Subject Headings (LCSH) and the Name authority files.</description>
+      <description>Library of Congress Subject Headings</description>
     </indicator>
     <indicator position="2" value="1">
-      <description>LC subject headings for children's literature The subject added entry conforms to the "AC Subject Headings" section of the LCSH and is appropriate for use in the LC Annotated Card Program.</description>
+      <description>LC subject headings for children's literature</description>
     </indicator>
     <indicator position="2" value="2">
-      <description>Medical Subject Headings The subject added entry conforms to the NLM authority files.</description>
+      <description>Medical Subject Headings</description>
     </indicator>
     <indicator position="2" value="3">
-      <description>National Agricultural Library subject authority file The subject added entry conforms to the NAL subject authority file.</description>
+      <description>National Agricultural Library subject authority file</description>
     </indicator>
     <indicator position="2" value="4">
-      <description>Source not specified The subject added entry conforms to a controlled list that cannot be identified by another defined value or by a code in subfield $2.</description>
+      <description>Source not specified</description>
     </indicator>
     <indicator position="2" value="5">
-      <description>Canadian Subject Headings The subject added entry conforms to and is appropriate for use in the Canadian Subject Headings and the LAC authority files.</description>
+      <description>Canadian Subject Headings</description>
     </indicator>
     <indicator position="2" value="6">
-      <description>R&#xC3;&#xA9;pertoire de vedettes-mati&#xC3;&#xA8;re The subject added entry conforms to and is appropriate for use in the R&#xC3;&#xA9;pertoire de vedettes-mati&#xC3;&#xA8;re and the LAC authority fields</description>
+      <description>Répertoire de vedettes-matière</description>
     </indicator>
     <indicator position="2" value="7">
       <description>Source specified in subfield $2</description>
@@ -4521,6 +5711,9 @@
     <subfield code="z" repeatable="true">
       <description>Geographic subdivision</description>
     </subfield>
+    <subfield code="0" repeatable="true">
+      <description>Authority record control number</description>
+    </subfield>
     <subfield code="2" repeatable="false">
       <description>Source of heading or term</description>
     </subfield>
@@ -4538,8 +5731,8 @@
     </subfield>
   </field>
   <field tag="611" repeatable="true">
-    <name>SUBJECT ADDED ENTRY--MEETING NAME</name>
-    <description>A subject added entry in which the entry element is a meeting name.</description>
+    <name>Subject Added Entry-Meeting Name</name>
+    <description>Subject added entry in which the entry element is a meeting or conference name.</description>
     <indicator position="1" value="0">
       <description>Inverted name</description>
     </indicator>
@@ -4550,25 +5743,25 @@
       <description>Name in direct order</description>
     </indicator>
     <indicator position="2" value="0">
-      <description>Library of Congress Subject Headings The subject added entry conforms to and is appropriate for use in the Library of Congress Subject Headings (LCSH) and the Name authority files.</description>
+      <description>Library of Congress Subject Headings</description>
     </indicator>
     <indicator position="2" value="1">
-      <description>LC subject headings for children's literature The subject added entry conforms to the "AC Subject Headings" section of the LCSH and is appropriate for use in the LC Annotated Card Program.</description>
+      <description>LC subject headings for children's literature</description>
     </indicator>
     <indicator position="2" value="2">
-      <description>Medical Subject Headings The subject added entry conforms to the NLM authority files.</description>
+      <description>Medical Subject Headings</description>
     </indicator>
     <indicator position="2" value="3">
-      <description>National Agricultural Library subject authority file The subject added entry conforms to the NAL subject authority file.</description>
+      <description>National Agricultural Library subject authority file</description>
     </indicator>
     <indicator position="2" value="4">
-      <description>Source not specified The subject added entry conforms to a controlled list that cannot be identified by another defined value or by a code in subfield $2.</description>
+      <description>Source not specified</description>
     </indicator>
     <indicator position="2" value="5">
-      <description>Canadian Subject Headings The subject added entry conforms to and is appropriate for use in the Canadian Subject Headings and the LAC authority files.</description>
+      <description>Canadian Subject Headings</description>
     </indicator>
     <indicator position="2" value="6">
-      <description>R&#xC3;&#xA9;pertoire de vedettes-mati&#xC3;&#xA8;re The subject added entry conforms to and is appropriate for use in the R&#xC3;&#xA9;pertoire de vedettes-mati&#xC3;&#xA8;re and the LAC authority fields</description>
+      <description>Répertoire de vedettes-matière</description>
     </indicator>
     <indicator position="2" value="7">
       <description>Source specified in subfield $2</description>
@@ -4633,6 +5826,9 @@
     <subfield code="z" repeatable="true">
       <description>Geographic subdivision</description>
     </subfield>
+    <subfield code="0" repeatable="true">
+      <description>Authority record control number</description>
+    </subfield>
     <subfield code="2" repeatable="false">
       <description>Source of heading or term</description>
     </subfield>
@@ -4650,31 +5846,58 @@
     </subfield>
   </field>
   <field tag="630" repeatable="true">
-    <name>SUBJECT ADDED ENTRY--UNIFORM TITLE</name>
-    <description>A subject added entry in which the entry element is a uniform title.</description>
-    <indicator position="1" value="0-9">
-      <description>Number of nonfiling characters A value that indicates the number of character positions associated with an initial definite or indefinite article at the beginning of a uniform title field that are to be disregarded in sorting and filing processes.</description>
+    <name>Subject Added Entry-Uniform Title</name>
+    <description>Subject added entry in which the entry element is a uniform title.</description>
+    <indicator position="1" value="0">
+      <description>No nonfiling characters</description>
     </indicator>
+    <indicator position="1" value="1">
+      <description>Number of nonfiling characters - 1</description>
+    </indicator>
+    <indicator position="1" value="2">
+      <description>Number of nonfiling characters - 2</description>
+    </indicator>
+    <indicator position="1" value="3">
+      <description>Number of nonfiling characters - 3</description>
+    </indicator>
+    <indicator position="1" value="4">
+      <description>Number of nonfiling characters - 4</description>
+    </indicator>
+    <indicator position="1" value="5">
+      <description>Number of nonfiling characters - 5</description>
+    </indicator>
+    <indicator position="1" value="6">
+      <description>Number of nonfiling characters - 6</description>
+    </indicator>
+    <indicator position="1" value="7">
+      <description>Number of nonfiling characters - 7</description>
+    </indicator>
+    <indicator position="1" value="8">
+      <description>Number of nonfiling characters - 8</description>
+    </indicator>
+    <indicator position="1" value="9">
+      <description>Number of nonfiling characters - 9</description>
+    </indicator>
     <indicator position="2" value="0">
-      <description>Library of Congress Subject Headings The subject added entry conforms to and is appropriate for use in the Library of Congress Subject Headings (LCSH) and the Name authority files.</description>
+      <description>Library of Congress Subject Headings</description>
     </indicator>
     <indicator position="2" value="1">
-      <description>LC subject headings for children's literature The subject added entry conforms to the "AC Subject Headings" section of the LCSH and is appropriate for use in the LC Annotated Card Program.</description>
+      <description>LC subject headings for children's literature</description>
     </indicator>
     <indicator position="2" value="2">
-      <description>Medical Subject Headings The subject added entry conforms to the NLM authority files.</description>
+      <description>Medical Subject Headings</description>
     </indicator>
     <indicator position="2" value="3">
-      <description>National Agricultural Library subject authority file The subject added entry conforms to the NAL subject authority file.</description>
+      <description>National Agricultural Library subject authority file</description>
     </indicator>
     <indicator position="2" value="4">
-      <description>Source not specified The subject added entry conforms to a controlled list that cannot be identified by another defined value or by a code in subfield $2.</description>
+      <description>Source not specified</description>
     </indicator>
     <indicator position="2" value="5">
-      <description>Canadian Subject Headings The subject added entry conforms to and is appropriate for use in the Canadian Subject Headings and the LAC authority files.</description>
+      <description>Canadian Subject Headings</description>
     </indicator>
     <indicator position="2" value="6">
-      <description>R&#xC3;&#xA9;pertoire de vedettes-mati&#xC3;&#xA8;re The subject added entry conforms to and is appropriate for use in the R&#xC3;&#xA9;pertoire de vedettes-mati&#xC3;&#xA8;re and the LAC authority fields</description>
+      <description>Répertoire de vedettes-matière</description>
     </indicator>
     <indicator position="2" value="7">
       <description>Source specified in subfield $2</description>
@@ -4736,6 +5959,9 @@
     <subfield code="z" repeatable="true">
       <description>Geographic subdivision</description>
     </subfield>
+    <subfield code="0" repeatable="true">
+      <description>Authority record control number</description>
+    </subfield>
     <subfield code="2" repeatable="false">
       <description>Source of heading or term</description>
     </subfield>
@@ -4753,28 +5979,31 @@
     </subfield>
   </field>
   <field tag="648" repeatable="true">
-    <name>SUBJECT ADDED ENTRY--CHRONOLOGICAL TERM</name>
-    <description>A subject added entry in which the entry element is a chronological term.</description>
+    <name>Subject Added Entry-Chronological Term</name>
+    <description>Subject added entry in which the entry element is a chronological term.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
     <indicator position="2" value="0">
-      <description>Library of Congress Subject Headings The subject added entry conforms to and is appropriate for use in the Library of Congress Subject Headings (LCSH) and the Name authority files.</description>
+      <description>Library of Congress Subject Headings</description>
     </indicator>
     <indicator position="2" value="1">
-      <description>LC subject headings for children's literature The subject added entry conforms to the "AC Subject Headings" section of the LCSH and is appropriate for use in the LC Annotated Card Program.</description>
+      <description>LC subject headings for children's literature</description>
     </indicator>
     <indicator position="2" value="2">
-      <description>Medical Subject Headings The subject added entry conforms to the NLM authority files.</description>
+      <description>Medical Subject Headings</description>
     </indicator>
     <indicator position="2" value="3">
-      <description>National Agricultural Library subject authority file The subject added entry conforms to the NAL subject authority file.</description>
+      <description>National Agricultural Library subject authority file</description>
     </indicator>
     <indicator position="2" value="4">
-      <description>Source not specified The subject added entry conforms to a controlled list that cannot be identified by another defined value or by a code in subfield $2.</description>
+      <description>Source not specified</description>
     </indicator>
     <indicator position="2" value="5">
-      <description>Canadian Subject Headings The subject added entry conforms to and is appropriate for use in the Canadian Subject Headings and the LAC authority files.</description>
+      <description>Canadian Subject Headings</description>
     </indicator>
     <indicator position="2" value="6">
-      <description>R&#xC3;&#xA9;pertoire de vedettes-mati&#xC3;&#xA8;re The subject added entry conforms to and is appropriate for use in the R&#xC3;&#xA9;pertoire de vedettes-mati&#xC3;&#xA8;re and the LAC authority fields</description>
+      <description>Répertoire de vedettes-matière</description>
     </indicator>
     <indicator position="2" value="7">
       <description>Source specified in subfield $2</description>
@@ -4794,6 +6023,9 @@
     <subfield code="z" repeatable="true">
       <description>Geographic subdivision</description>
     </subfield>
+    <subfield code="0" repeatable="true">
+      <description>Authority record control number</description>
+    </subfield>
     <subfield code="2" repeatable="false">
       <description>Source of heading or term</description>
     </subfield>
@@ -4808,40 +6040,40 @@
     </subfield>
   </field>
   <field tag="650" repeatable="true">
-    <name>SUBJECT ADDED ENTRY--TOPICAL TERM</name>
-    <description>A subject added entry in which the entry element is a topical term.</description>
+    <name>Subject Added Entry-Topical Term</name>
+    <description>Subject added entry in which the entry element is a topical term.</description>
     <indicator position="1" value="#">
       <description>No information provided</description>
     </indicator>
     <indicator position="1" value="0">
-      <description>No level specified The level of the term could be determined but is not specified.</description>
+      <description>No level specified</description>
     </indicator>
     <indicator position="1" value="1">
-      <description>Primary The term describes the main focus or subject content of the material.</description>
+      <description>Primary</description>
     </indicator>
     <indicator position="1" value="2">
-      <description>Secondary The subject term describes a less important aspect of the content of the material.</description>
+      <description>Secondary</description>
     </indicator>
     <indicator position="2" value="0">
-      <description>Library of Congress Subject Headings The subject added entry conforms to and is appropriate for use in the Library of Congress Subject Headings (LCSH) and the Name authority files.</description>
+      <description>Library of Congress Subject Headings</description>
     </indicator>
     <indicator position="2" value="1">
-      <description>LC subject headings for children's literature The subject added entry conforms to the "AC Subject Headings" section of the LCSH and is appropriate for use in the LC Annotated Card Program.</description>
+      <description>LC subject headings for children's literature</description>
     </indicator>
     <indicator position="2" value="2">
-      <description>Medical Subject Headings The subject added entry conforms to the NLM authority files.</description>
+      <description>Medical Subject Headings</description>
     </indicator>
     <indicator position="2" value="3">
-      <description>National Agricultural Library subject authority file The subject added entry conforms to the NAL subject authority file.</description>
+      <description>National Agricultural Library subject authority file</description>
     </indicator>
     <indicator position="2" value="4">
-      <description>Source not specified The subject added entry conforms to a controlled list that cannot be identified by another defined value or by a code in subfield $2.</description>
+      <description>Source not specified</description>
     </indicator>
     <indicator position="2" value="5">
-      <description>Canadian Subject Headings The subject added entry conforms to and is appropriate for use in the Canadian Subject Headings and the LAC authority files.</description>
+      <description>Canadian Subject Headings</description>
     </indicator>
     <indicator position="2" value="6">
-      <description>R&#xC3;&#xA9;pertoire de vedettes-mati&#xC3;&#xA8;re The subject added entry conforms to and is appropriate for use in the R&#xC3;&#xA9;pertoire de vedettes-mati&#xC3;&#xA8;re and the LAC authority fields</description>
+      <description>Répertoire de vedettes-matière</description>
     </indicator>
     <indicator position="2" value="7">
       <description>Source specified in subfield $2</description>
@@ -4873,6 +6105,9 @@
     <subfield code="z" repeatable="true">
       <description>Geographic subdivision</description>
     </subfield>
+    <subfield code="0" repeatable="true">
+      <description>Authority record control number</description>
+    </subfield>
     <subfield code="2" repeatable="false">
       <description>Source of heading or term</description>
     </subfield>
@@ -4890,28 +6125,31 @@
     </subfield>
   </field>
   <field tag="651" repeatable="true">
-    <name>SUBJECT ADDED ENTRY--GEOGRAPHIC NAME</name>
-    <description>A subject added entry in which the entry element is a geographic name.</description>
+    <name>Subject Added Entry-Geographic Name</name>
+    <description>Subject added entry in which the entry element is a geographic name.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
     <indicator position="2" value="0">
-      <description>Library of Congress Subject Headings The subject added entry conforms to and is appropriate for use in the Library of Congress Subject Headings (LCSH) and the Name authority files.</description>
+      <description>Library of Congress Subject Headings</description>
     </indicator>
     <indicator position="2" value="1">
-      <description>LC subject headings for children's literature The subject added entry conforms to the "AC Subject Headings" section of the LCSH and is appropriate for use in the LC Annotated Card Program.</description>
+      <description>LC subject headings for children's literature</description>
     </indicator>
     <indicator position="2" value="2">
-      <description>Medical Subject Headings The subject added entry conforms to the NLM authority files.</description>
+      <description>Medical Subject Headings</description>
     </indicator>
     <indicator position="2" value="3">
-      <description>National Agricultural Library subject authority file The subject added entry conforms to the NAL subject authority file.</description>
+      <description>National Agricultural Library subject authority file</description>
     </indicator>
     <indicator position="2" value="4">
-      <description>Source not specified The subject added entry conforms to a controlled list that cannot be identified by another defined value or by a code in subfield $2.</description>
+      <description>Source not specified</description>
     </indicator>
     <indicator position="2" value="5">
-      <description>Canadian Subject Headings The subject added entry conforms to and is appropriate for use in the Canadian Subject Headings and the LAC authority files.</description>
+      <description>Canadian Subject Headings</description>
     </indicator>
     <indicator position="2" value="6">
-      <description>R&#xC3;&#xA9;pertoire de vedettes-mati&#xC3;&#xA8;re The subject added entry conforms to and is appropriate for use in the R&#xC3;&#xA9;pertoire de vedettes-mati&#xC3;&#xA8;re and the LAC authority fields</description>
+      <description>Répertoire de vedettes-matière</description>
     </indicator>
     <indicator position="2" value="7">
       <description>Source specified in subfield $2</description>
@@ -4934,6 +6172,9 @@
     <subfield code="z" repeatable="true">
       <description>Geographic subdivision</description>
     </subfield>
+    <subfield code="0" repeatable="true">
+      <description>Authority record control number</description>
+    </subfield>
     <subfield code="2" repeatable="false">
       <description>Source of heading or term</description>
     </subfield>
@@ -4951,20 +6192,44 @@
     </subfield>
   </field>
   <field tag="653" repeatable="true">
-    <name>INDEX TERM--UNCONTROLLED</name>
-    <description>An index term added entry that is not constructed by standard subject heading/thesaurus-building conventions.</description>
+    <name>Index Term-Uncontrolled</name>
+    <description>Index term added entry that is not constructed by standard subject heading/thesaurus-building conventions.</description>
     <indicator position="1" value="#">
       <description>No information provided</description>
     </indicator>
     <indicator position="1" value="0">
-      <description>No level specified The level of the term could be determined but is not specified.</description>
+      <description>No level specified</description>
     </indicator>
     <indicator position="1" value="1">
-      <description>Primary The term describes the main focus or subject content of the material.</description>
+      <description>Primary</description>
     </indicator>
     <indicator position="1" value="2">
-      <description>Secondary The subject term describes a less important aspect of the content of the material.</description>
+      <description>Secondary</description>
     </indicator>
+    <indicator position="2" value="#">
+      <description>No information provided</description>
+    </indicator>
+    <indicator position="2" value="0">
+      <description>Topical term</description>
+    </indicator>
+    <indicator position="2" value="1">
+      <description>Personal name</description>
+    </indicator>
+    <indicator position="2" value="2">
+      <description>Corporate name</description>
+    </indicator>
+    <indicator position="2" value="3">
+      <description>Meeting name</description>
+    </indicator>
+    <indicator position="2" value="4">
+      <description>Chronological term</description>
+    </indicator>
+    <indicator position="2" value="5">
+      <description>Geographic name</description>
+    </indicator>
+    <indicator position="2" value="6">
+      <description>Genre/form term</description>
+    </indicator>
     <subfield code="a" repeatable="true">
       <description>Uncontrolled term</description>
     </subfield>
@@ -4976,20 +6241,23 @@
     </subfield>
   </field>
   <field tag="654" repeatable="true">
-    <name>SUBJECT ADDED ENTRY--FACETED TOPICAL TERMS</name>
-    <description>A topical subject constructed from a faceted vocabulary.</description>
+    <name>Subject Added Entry-Faceted Topical Terms</name>
+    <description>Topical subject constructed from a faceted vocabulary.</description>
     <indicator position="1" value="#">
       <description>No information provided</description>
     </indicator>
     <indicator position="1" value="0">
-      <description>No level specified The level of the term could be determined but is not specified.</description>
+      <description>No level specified</description>
     </indicator>
     <indicator position="1" value="1">
-      <description>Primary The term describes the main focus or subject content of the material.</description>
+      <description>Primary</description>
     </indicator>
     <indicator position="1" value="2">
-      <description>Secondary The subject term describes a less important aspect of the content of the material.</description>
+      <description>Secondary</description>
     </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="true">
       <description>Focus term</description>
     </subfield>
@@ -5011,6 +6279,9 @@
     <subfield code="z" repeatable="true">
       <description>Geographic subdivision</description>
     </subfield>
+    <subfield code="0" repeatable="true">
+      <description>Authority record control number</description>
+    </subfield>
     <subfield code="2" repeatable="false">
       <description>Source of heading or term</description>
     </subfield>
@@ -5028,8 +6299,8 @@
     </subfield>
   </field>
   <field tag="655" repeatable="true">
-    <name>INDEX TERM--GENRE/FORM</name>
-    <description>Terms indicating the genre, form, and/or physical characteristics of the materials being described. A genre term designates the style or technique of the intellectual content of textual materials or, for graphic materials, aspects such as vantage point, intended purpose, or method of representation. A form term designates historically and functionally specific kinds of materials distinguished by their physical character, the subject of their intellectual content, or the order of information within them. Physical characteristic terms designate historically and functionally specific kinds of materials as distinguished by an examination of their physical character, subject of their intellectual content, or the order of information with them.</description>
+    <name>Index Term-Genre/Form</name>
+    <description>Terms indicating the genre, form, and/or physical characteristics of the materials being described. A designates the style or technique of the intellectual content of textual materials or, for graphic materials, aspects such as vantage point, intended purpose, characteristics of the creator, publication status, or method of representation. A designates historically and functionally specific kinds of materials distinguished by their physical character, the subject of their intellectual content, or the order of information within them. terms designate historically and functionally specific kinds of materials as distinguished by an examination of their physical character, subject of their intellectual content, or the order of information with them.</description>
     <indicator position="1" value="#">
       <description>Basic</description>
     </indicator>
@@ -5037,25 +6308,25 @@
       <description>Faceted</description>
     </indicator>
     <indicator position="2" value="0">
-      <description>Library of Congress Subject Headings The subject index term conforms to and is appropriate for use in the Library of Congress Subject Headings (LCSH).</description>
+      <description>Library of Congress Subject Headings</description>
     </indicator>
     <indicator position="2" value="1">
-      <description>LC subject headings for children's literature The subject index term conforms to the "AC Subject Headings" section of the LCSH and is appropriate for use in the LC Annotated Card Program.</description>
+      <description>LC subject headings for children's literature</description>
     </indicator>
     <indicator position="2" value="2">
-      <description>Medical Subject Headings The subject index term conforms to the NLM subject authority file.</description>
+      <description>Medical Subject Headings</description>
     </indicator>
     <indicator position="2" value="3">
-      <description>National Agricultural Library subject authority file The subject added entry conforms to the NAL subject authority file.</description>
+      <description>National Agricultural Library subject authority file</description>
     </indicator>
     <indicator position="2" value="4">
-      <description>Source not specified The subject index term conforms to a controlled list that cannot be identified by another defined value or by a code in subfield $2.</description>
+      <description>Source not specified</description>
     </indicator>
     <indicator position="2" value="5">
-      <description>Canadian Subject Headings The subject index term conforms to and is appropriate for use in the Canadian Subject Headings that is maintained by the National Library of Canada.</description>
+      <description>Canadian Subject Headings</description>
     </indicator>
     <indicator position="2" value="6">
-      <description>R&#xC3;&#xA9;pertoire de vedettes-mati&#xC3;&#xA8;re The subject index term conforms to and is appropriate for use in the R&#xC3;&#xA9;pertoire de vedettes-mati&#xC3;&#xA8;re.</description>
+      <description>Répertoire de vedettes-matière</description>
     </indicator>
     <indicator position="2" value="7">
       <description>Source specified in subfield $2</description>
@@ -5081,6 +6352,9 @@
     <subfield code="z" repeatable="true">
       <description>Geographic subdivision</description>
     </subfield>
+    <subfield code="0" repeatable="true">
+      <description>Authority record control number</description>
+    </subfield>
     <subfield code="2" repeatable="false">
       <description>Source of term</description>
     </subfield>
@@ -5098,8 +6372,11 @@
     </subfield>
   </field>
   <field tag="656" repeatable="true">
-    <name>INDEX TERM--OCCUPATION</name>
-    <description>An index term that is descriptive of the occupation reflected in the contents of the described materials.</description>
+    <name>Index Term-Occupation</name>
+    <description>Index term that is descriptive of the occupation (including avocation) reflected in the contents of the described materials.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
     <indicator position="2" value="7">
       <description>Source specified in subfield $2</description>
     </indicator>
@@ -5121,6 +6398,9 @@
     <subfield code="z" repeatable="true">
       <description>Geographic subdivision</description>
     </subfield>
+    <subfield code="0" repeatable="true">
+      <description>Authority record control number</description>
+    </subfield>
     <subfield code="2" repeatable="false">
       <description>Source of term</description>
     </subfield>
@@ -5135,8 +6415,11 @@
     </subfield>
   </field>
   <field tag="657" repeatable="true">
-    <name>INDEX TERM--FUNCTION</name>
-    <description>An index term that is descriptive of the activity or function that generated the described materials.</description>
+    <name>Index Term-Function</name>
+    <description>Index term that describes the activity or function that generated the described materials.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
     <indicator position="2" value="7">
       <description>Source specified in subfield $2</description>
     </indicator>
@@ -5155,6 +6438,9 @@
     <subfield code="z" repeatable="true">
       <description>Geographic subdivision</description>
     </subfield>
+    <subfield code="0" repeatable="true">
+      <description>Authority record control number</description>
+    </subfield>
     <subfield code="2" repeatable="false">
       <description>Source of term</description>
     </subfield>
@@ -5169,8 +6455,14 @@
     </subfield>
   </field>
   <field tag="658" repeatable="true">
-    <name>INDEX TERM--CURRICULUM OBJECTIVE</name>
+    <name>Index Term-Curriculum Objective</name>
     <description>Index terms denoting curriculum or course-of-study objectives applicable to the content of the described materials. The field may also contain correlation factors indicating the degree to which the described materials meet an objective. Codes assigned to specific objectives in published lists are also recorded in this field.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>Main curriculum objective</description>
     </subfield>
@@ -5194,8 +6486,14 @@
     </subfield>
   </field>
   <field tag="662" repeatable="true">
-    <name>SUBJECT ADDED ENTRY--HIERARCHICAL PLACE NAME</name>
-    <description>Contains a hierarchical form of a geographic name used as a subject added entry.</description>
+    <name>Subject Added Entry-Hierarchical Place Name</name>
+    <description>Hierarchical form of a geographic name used as a subject added entry.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="true">
       <description>Country or larger entity</description>
     </subfield>
@@ -5220,6 +6518,9 @@
     <subfield code="h" repeatable="true">
       <description>Extraterrestrial area</description>
     </subfield>
+    <subfield code="0" repeatable="true">
+      <description>Authority record control number</description>
+    </subfield>
     <subfield code="2" repeatable="false">
       <description>Source of heading or term</description>
     </subfield>
@@ -5233,9 +6534,13 @@
       <description>Field link and sequence number</description>
     </subfield>
   </field>
+  <field tag="69X" repeatable="true">
+    <name>Local Subject Access Fields</name>
+    <description>Fields 690-699 are reserved for local subject use and local definition. For interchange purposes, documentation of the structure of the 69X fields and input conventions should be provided to exchange partners by the organization initiating the exchange.</description>
+  </field>
   <field tag="700" repeatable="true">
-    <name>ADDED ENTRY--PERSONAL NAME</name>
-    <description>An added entry in which the entry element is a personal name.</description>
+    <name>Added Entry-Personal Name</name>
+    <description>Added entry in which the entry element is a personal name.</description>
     <indicator position="1" value="0">
       <description>Forename</description>
     </indicator>
@@ -5249,7 +6554,7 @@
       <description>No information provided</description>
     </indicator>
     <indicator position="2" value="2">
-      <description>Analytical entry The item represented by the added entry is contained in the item described by the bibliographic record.</description>
+      <description>Analytical entry</description>
     </indicator>
     <subfield code="a" repeatable="false">
       <description>Personal name</description>
@@ -5314,6 +6619,9 @@
     <subfield code="x" repeatable="false">
       <description>International Standard Serial Number</description>
     </subfield>
+    <subfield code="0" repeatable="true">
+      <description>Authority record control number</description>
+    </subfield>
     <subfield code="3" repeatable="false">
       <description>Materials specified</description>
     </subfield>
@@ -5331,8 +6639,8 @@
     </subfield>
   </field>
   <field tag="710" repeatable="true">
-    <name>ADDED ENTRY--CORPORATE NAME</name>
-    <description>An added entry in which the entry element is a corporate name.</description>
+    <name>Added Entry-Corporate Name</name>
+    <description>Added entry in which the entry element is a corporate name.</description>
     <indicator position="1" value="0">
       <description>Inverted name</description>
     </indicator>
@@ -5346,7 +6654,7 @@
       <description>No information provided</description>
     </indicator>
     <indicator position="2" value="2">
-      <description>Analytical entry The item represented by the added entry is contained in the item described by the bibliographic record.</description>
+      <description>Analytical entry</description>
     </indicator>
     <subfield code="a" repeatable="false">
       <description>Corporate name or jurisdiction name as entry element</description>
@@ -5405,6 +6713,9 @@
     <subfield code="x" repeatable="false">
       <description>International Standard Serial Number</description>
     </subfield>
+    <subfield code="0" repeatable="true">
+      <description>Authority record control number</description>
+    </subfield>
     <subfield code="3" repeatable="false">
       <description>Materials specified</description>
     </subfield>
@@ -5422,8 +6733,8 @@
     </subfield>
   </field>
   <field tag="711" repeatable="true">
-    <name>ADDED ENTRY--MEETING NAME</name>
-    <description>An added entry in which the entry element is a meeting name.</description>
+    <name>Added Entry-Meeting Name</name>
+    <description>Added entry in which the entry element is a meeting name.</description>
     <indicator position="1" value="0">
       <description>Inverted name</description>
     </indicator>
@@ -5437,7 +6748,7 @@
       <description>No information provided</description>
     </indicator>
     <indicator position="2" value="2">
-      <description>Analytical entry The item represented by the added entry is contained in the item described by the bibliographic record.</description>
+      <description>Analytical entry</description>
     </indicator>
     <subfield code="a" repeatable="false">
       <description>Meeting name or jurisdiction name as entry element</description>
@@ -5490,6 +6801,9 @@
     <subfield code="x" repeatable="false">
       <description>International Standard Serial Number</description>
     </subfield>
+    <subfield code="0" repeatable="true">
+      <description>Authority record control number</description>
+    </subfield>
     <subfield code="3" repeatable="false">
       <description>Materials specified</description>
     </subfield>
@@ -5507,8 +6821,8 @@
     </subfield>
   </field>
   <field tag="720" repeatable="true">
-    <name>ADDED ENTRY--UNCONTROLLED NAME</name>
-    <description>An added entry in which the name is not controlled in an authority file or list. It is also used for names that have not been formulated according to cataloging rules. Names may be of any type (e.g., personal, corporate, meeting).</description>
+    <name>Added Entry-Uncontrolled Name</name>
+    <description>Added entry in which the name is not controlled in an authority file or list. It is also used for names that have not been formulated according to cataloging rules. Names may be of any type (e.g., personal, corporate, meeting).</description>
     <indicator position="1" value="#">
       <description>Not specified</description>
     </indicator>
@@ -5518,6 +6832,9 @@
     <indicator position="1" value="2">
       <description>Other</description>
     </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>Name</description>
     </subfield>
@@ -5535,16 +6852,43 @@
     </subfield>
   </field>
   <field tag="730" repeatable="true">
-    <name>ADDED ENTRY--UNIFORM TITLE</name>
-    <description>Contains a related or an analytical title that is controlled by an authority file or list.</description>
-    <indicator position="1" value="0-9">
-      <description>Number of nonfiling characters</description>
+    <name>Added Entry-Uniform Title</name>
+    <description>Uniform title, a related or an analytical title that is controlled by an authority file or list, used as an added entry.</description>
+    <indicator position="1" value="0">
+      <description>No nonfiling characters</description>
     </indicator>
+    <indicator position="1" value="1">
+      <description>Number of nonfiling characters - 1</description>
+    </indicator>
+    <indicator position="1" value="2">
+      <description>Number of nonfiling characters - 2</description>
+    </indicator>
+    <indicator position="1" value="3">
+      <description>Number of nonfiling characters - 3</description>
+    </indicator>
+    <indicator position="1" value="4">
+      <description>Number of nonfiling characters - 4</description>
+    </indicator>
+    <indicator position="1" value="5">
+      <description>Number of nonfiling characters - 5</description>
+    </indicator>
+    <indicator position="1" value="6">
+      <description>Number of nonfiling characters - 6</description>
+    </indicator>
+    <indicator position="1" value="7">
+      <description>Number of nonfiling characters - 7</description>
+    </indicator>
+    <indicator position="1" value="8">
+      <description>Number of nonfiling characters - 8</description>
+    </indicator>
+    <indicator position="1" value="9">
+      <description>Number of nonfiling characters - 9</description>
+    </indicator>
     <indicator position="2" value="#">
       <description>No information provided</description>
     </indicator>
     <indicator position="2" value="2">
-      <description>Analytical entry The item represented by the added entry is contained in the item described by the bibliographic record.</description>
+      <description>Analytical entry</description>
     </indicator>
     <subfield code="a" repeatable="false">
       <description>Uniform title</description>
@@ -5591,6 +6935,9 @@
     <subfield code="x" repeatable="false">
       <description>International Standard Serial Number</description>
     </subfield>
+    <subfield code="0" repeatable="true">
+      <description>Authority record control number</description>
+    </subfield>
     <subfield code="3" repeatable="false">
       <description>Materials specified</description>
     </subfield>
@@ -5605,16 +6952,43 @@
     </subfield>
   </field>
   <field tag="740" repeatable="true">
-    <name>ADDED ENTRY--UNCONTROLLED RELATED/ANALYTICAL TITLE</name>
-    <description>Contains related or analytical titles that are not controlled through an authority file or list. (If related or analytical titles are controlled by an authority file, use field 730 (Added entry - uniform title)).</description>
-    <indicator position="1" value="0-9">
-      <description>Number of nonfiling characters</description>
+    <name>Added Entry-Uncontrolled Related/Analytical Title</name>
+    <description>Added entries for related or analytical titles that are not controlled through an authority file or list. (If related or analytical titles are controlled by an authority file, use field 730 (Added entry - uniform title)).</description>
+    <indicator position="1" value="0">
+      <description>No nonfiling characters</description>
     </indicator>
+    <indicator position="1" value="1">
+      <description>Number of nonfiling characters - 1</description>
+    </indicator>
+    <indicator position="1" value="2">
+      <description>Number of nonfiling characters - 2</description>
+    </indicator>
+    <indicator position="1" value="3">
+      <description>Number of nonfiling characters - 3</description>
+    </indicator>
+    <indicator position="1" value="4">
+      <description>Number of nonfiling characters - 4</description>
+    </indicator>
+    <indicator position="1" value="5">
+      <description>Number of nonfiling characters - 5</description>
+    </indicator>
+    <indicator position="1" value="6">
+      <description>Number of nonfiling characters - 6</description>
+    </indicator>
+    <indicator position="1" value="7">
+      <description>Number of nonfiling characters - 7</description>
+    </indicator>
+    <indicator position="1" value="8">
+      <description>Number of nonfiling characters - 8</description>
+    </indicator>
+    <indicator position="1" value="9">
+      <description>Number of nonfiling characters - 9</description>
+    </indicator>
     <indicator position="2" value="#">
       <description>No information provided</description>
     </indicator>
     <indicator position="2" value="2">
-      <description>Analytical entry The item represented by the added entry is contained in the item described by the bibliographic record.</description>
+      <description>Analytical entry</description>
     </indicator>
     <subfield code="a" repeatable="false">
       <description>Uncontrolled related/analytical title</description>
@@ -5638,9 +7012,49 @@
       <description>Field link and sequence number</description>
     </subfield>
   </field>
+  <field tag="751" repeatable="true">
+    <name>Added Entry-Geographic Name</name>
+    <description>Added entry in which the entry element is a geographic name that is related to a particular attribute of the described item, e.g., the place of publication for a rare book, place of distribution, place of a university to which a dissertation is submitted, place of an event such as a conference, etc.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Geographic name</description>
+    </subfield>
+    <subfield code="e" repeatable="true">
+      <description>Relator term</description>
+    </subfield>
+    <subfield code="0" repeatable="true">
+      <description>Authority record control number</description>
+    </subfield>
+    <subfield code="2" repeatable="false">
+      <description>Source of heading or term</description>
+    </subfield>
+    <subfield code="3" repeatable="false">
+      <description>Materials specified</description>
+    </subfield>
+    <subfield code="4" repeatable="true">
+      <description>Relator code</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
   <field tag="752" repeatable="true">
-    <name>ADDED ENTRY--HIERARCHICAL PLACE NAME</name>
-    <description>An added entry in which the entry element is a hierarchical form of place name that is related to a particular attribute of the described item, e.g., the place of publication for a rare book. For display, a dash (--) may be generated to separate the subelements of the place name, e.g., Canada -- British Columbia -- Vancouver.</description>
+    <name>Added Entry-Hierarchical Place Name</name>
+    <description>Added entry in which the entry element is a hierarchical form of place name that is related to a particular attribute of the described item, e.g., the place of publication for a rare book. For display, a dash (--) may be generated to separate the subelements of the place name, e.g., Canada -- British Columbia -- Vancouver.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="true">
       <description>Country or larger entity</description>
     </subfield>
@@ -5662,6 +7076,9 @@
     <subfield code="h" repeatable="true">
       <description>Extraterrestrial area</description>
     </subfield>
+    <subfield code="0" repeatable="true">
+      <description>Authority record control number</description>
+    </subfield>
     <subfield code="2" repeatable="false">
       <description>Source of heading or term</description>
     </subfield>
@@ -5673,8 +7090,14 @@
     </subfield>
   </field>
   <field tag="753" repeatable="true">
-    <name>SYSTEM DETAILS ACCESS TO COMPUTER FILES</name>
+    <name>System Details Access to Computer Files</name>
     <description>Information on the technical aspects of a computer file and any accompanying material that may be used to select and arrange the record with other records in a printed index.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>Make and model of machine</description>
     </subfield>
@@ -5692,8 +7115,14 @@
     </subfield>
   </field>
   <field tag="754" repeatable="true">
-    <name>ADDED ENTRY--TAXONOMIC IDENTIFICATION</name>
-    <description>An added entry in which the entry element is the taxonomic name or category associated with the described item.</description>
+    <name>Added Entry-Taxonomic Identification</name>
+    <description>Added entry in which the entry element is the taxonomic name or category associated with the described item.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="true">
       <description>Taxonomic name</description>
     </subfield>
@@ -5709,6 +7138,9 @@
     <subfield code="z" repeatable="true">
       <description>Public note</description>
     </subfield>
+    <subfield code="0" repeatable="true">
+      <description>Authority record control number</description>
+    </subfield>
     <subfield code="2" repeatable="false">
       <description>Source of taxonomic identification</description>
     </subfield>
@@ -5720,13 +7152,13 @@
     </subfield>
   </field>
   <field tag="760" repeatable="true">
-    <name>MAIN SERIES ENTRY</name>
-    <description>Information concerning the related main series when the target item is a subseries (vertical relationship). When a note is generated from this field, the introductory phrase Main series: or Subseries of: may be generated based on the field tag for display.</description>
+    <name>Main Series Entry</name>
+    <description>Information concerning the related main series when the target item is a subseries (vertical relationship). When a note is generated from this field, the introductory phrase or may be generated based on the field tag for display.</description>
     <indicator position="1" value="0">
       <description>Display note</description>
     </indicator>
     <indicator position="1" value="1">
-      <description>Do not display note A textual note is contained in field 580 (Linking Entry Complexity Note).</description>
+      <description>Do not display note</description>
     </indicator>
     <indicator position="2" value="#">
       <description>Main series</description>
@@ -5747,13 +7179,13 @@
       <description>Place, publisher, and date of publication</description>
     </subfield>
     <subfield code="g" repeatable="true">
-      <description>Relationship information</description>
+      <description>Related parts</description>
     </subfield>
     <subfield code="h" repeatable="false">
       <description>Physical description</description>
     </subfield>
-    <subfield code="i" repeatable="false">
-      <description>Display text</description>
+    <subfield code="i" repeatable="true">
+      <description>Relationship information</description>
     </subfield>
     <subfield code="m" repeatable="false">
       <description>Material-specific details</description>
@@ -5785,18 +7217,120 @@
     <subfield code="7" repeatable="false">
       <description>Control subfield</description>
     </subfield>
+    <subfield code="p" repeatable="true">
+      <description>Personal name</description>
+    </subfield>
+    <subfield code="c" repeatable="true">
+      <description>Corporate name</description>
+    </subfield>
+    <subfield code="m" repeatable="true">
+      <description>Meeting name</description>
+    </subfield>
+    <subfield code="u" repeatable="true">
+      <description>Uniform title</description>
+    </subfield>
+    <subfield code="n" repeatable="true">
+      <description>Not applicable</description>
+    </subfield>
+    <subfield code="0" repeatable="true">
+      <description>Forename</description>
+    </subfield>
+    <subfield code="1" repeatable="true">
+      <description>Single surname</description>
+    </subfield>
+    <subfield code="2" repeatable="true">
+      <description>Multiple surname</description>
+    </subfield>
+    <subfield code="3" repeatable="true">
+      <description>Family name</description>
+    </subfield>
+    <subfield code="0" repeatable="true">
+      <description>Inverted name</description>
+    </subfield>
+    <subfield code="1" repeatable="true">
+      <description>Jurisdiction name</description>
+    </subfield>
+    <subfield code="2" repeatable="true">
+      <description>Name in direct order</description>
+    </subfield>
+    <subfield code="n" repeatable="true">
+      <description>Not applicable</description>
+    </subfield>
+    <subfield code="a" repeatable="true">
+      <description>Language material</description>
+    </subfield>
+    <subfield code="c" repeatable="true">
+      <description>Notated music</description>
+    </subfield>
+    <subfield code="d" repeatable="true">
+      <description>Manuscript notated music</description>
+    </subfield>
+    <subfield code="e" repeatable="true">
+      <description>Cartographic material</description>
+    </subfield>
+    <subfield code="f" repeatable="true">
+      <description>Manuscript cartographic material</description>
+    </subfield>
+    <subfield code="g" repeatable="true">
+      <description>Projected medium</description>
+    </subfield>
+    <subfield code="i" repeatable="true">
+      <description>Nonmusical sound recording</description>
+    </subfield>
+    <subfield code="j" repeatable="true">
+      <description>Musical sound recording</description>
+    </subfield>
+    <subfield code="k" repeatable="true">
+      <description>Two-dimensional nonprojectable graphic</description>
+    </subfield>
+    <subfield code="m" repeatable="true">
+      <description>Computer file</description>
+    </subfield>
+    <subfield code="o" repeatable="true">
+      <description>Kit</description>
+    </subfield>
+    <subfield code="p" repeatable="true">
+      <description>Mixed material</description>
+    </subfield>
+    <subfield code="r" repeatable="true">
+      <description>Three-dimensional artifact or naturally occurring object</description>
+    </subfield>
+    <subfield code="t" repeatable="true">
+      <description>Manuscript language material</description>
+    </subfield>
+    <subfield code="a" repeatable="true">
+      <description>Monographic component part</description>
+    </subfield>
+    <subfield code="b" repeatable="true">
+      <description>Serial component part</description>
+    </subfield>
+    <subfield code="c" repeatable="true">
+      <description>Collection</description>
+    </subfield>
+    <subfield code="d" repeatable="true">
+      <description>Subunit</description>
+    </subfield>
+    <subfield code="m" repeatable="true">
+      <description>Monograph/item</description>
+    </subfield>
+    <subfield code="s" repeatable="true">
+      <description>Serial</description>
+    </subfield>
+    <subfield code="i" repeatable="true">
+      <description>Integrating resource</description>
+    </subfield>
     <subfield code="8" repeatable="true">
       <description>Field link and sequence number</description>
     </subfield>
   </field>
   <field tag="762" repeatable="true">
-    <name>SUBSERIES ENTRY</name>
-    <description>Information concerning a related subseries when the target item is a main series or a parent subseries (vertical relationship). When a note is generated from this field, the introductory phrase Has subseries: may be generated based on the field tag for display.</description>
+    <name>Subseries Entry</name>
+    <description>Information concerning a related subseries when the target item is a main series or a parent subseries (vertical relationship). When a note is generated from this field, the introductory phrase may be generated based on the field tag for display.</description>
     <indicator position="1" value="0">
       <description>Display note</description>
     </indicator>
     <indicator position="1" value="1">
-      <description>Do not display note A textual note is contained in field 580 (Linking Entry Complexity Note).</description>
+      <description>Do not display note</description>
     </indicator>
     <indicator position="2" value="#">
       <description>Has subseries</description>
@@ -5817,13 +7351,13 @@
       <description>Place, publisher, and date of publication</description>
     </subfield>
     <subfield code="g" repeatable="true">
-      <description>Relationship information</description>
+      <description>Related parts</description>
     </subfield>
     <subfield code="h" repeatable="false">
       <description>Physical description</description>
     </subfield>
-    <subfield code="i" repeatable="false">
-      <description>Display text</description>
+    <subfield code="i" repeatable="true">
+      <description>Relationship information</description>
     </subfield>
     <subfield code="m" repeatable="false">
       <description>Material-specific details</description>
@@ -5860,13 +7394,13 @@
     </subfield>
   </field>
   <field tag="765" repeatable="true">
-    <name>ORIGINAL LANGUAGE ENTRY</name>
-    <description>Information concerning the publication in its original language when the target item is a translation (horizontal relationship). When a note is generated from this field, the introductory phrase Translation of: may be generated based on the field tag for display.</description>
+    <name>Original Language Entry</name>
+    <description>Information concerning the publication in its original language when the target item is a translation (horizontal relationship). When a note is generated from this field, the introductory phrase may be generated based on the field tag for display.</description>
     <indicator position="1" value="0">
       <description>Display note</description>
     </indicator>
     <indicator position="1" value="1">
-      <description>Do not display note A textual note is contained in field 580 (Linking Entry Complexity Note).</description>
+      <description>Do not display note</description>
     </indicator>
     <indicator position="2" value="#">
       <description>Translation of</description>
@@ -5887,13 +7421,13 @@
       <description>Place, publisher, and date of publication</description>
     </subfield>
     <subfield code="g" repeatable="true">
-      <description>Relationship information</description>
+      <description>Related parts</description>
     </subfield>
     <subfield code="h" repeatable="false">
       <description>Physical description</description>
     </subfield>
-    <subfield code="i" repeatable="false">
-      <description>Display text</description>
+    <subfield code="i" repeatable="true">
+      <description>Relationship information</description>
     </subfield>
     <subfield code="k" repeatable="true">
       <description>Series data for related item</description>
@@ -5942,13 +7476,13 @@
     </subfield>
   </field>
   <field tag="767" repeatable="true">
-    <name>TRANSLATION ENTRY</name>
-    <description>Information concerning the publication in some other language other than the original when the target item is in the original language or is another translation (horizontal relationship). When a note is generated from this field, the introductory phrase Translated as: may be generated based on the field tag for display.</description>
+    <name>Translation Entry</name>
+    <description>Information concerning the publication in some other language other than the original when the target item is in the original language or is another translation (horizontal relationship). When a note is generated from this field, the introductory phrase may be generated based on the field tag for display.</description>
     <indicator position="1" value="0">
       <description>Display note</description>
     </indicator>
     <indicator position="1" value="1">
-      <description>Do not display note A textual note is contained in field 580 (Linking Entry Complexity Note).</description>
+      <description>Do not display note</description>
     </indicator>
     <indicator position="2" value="#">
       <description>Translated as</description>
@@ -5969,13 +7503,13 @@
       <description>Place, publisher, and date of publication</description>
     </subfield>
     <subfield code="g" repeatable="true">
-      <description>Relationship information</description>
+      <description>Related parts</description>
     </subfield>
     <subfield code="h" repeatable="false">
       <description>Physical description</description>
     </subfield>
-    <subfield code="i" repeatable="false">
-      <description>Display text</description>
+    <subfield code="i" repeatable="true">
+      <description>Relationship information</description>
     </subfield>
     <subfield code="k" repeatable="true">
       <description>Series data for related item</description>
@@ -6024,13 +7558,13 @@
     </subfield>
   </field>
   <field tag="770" repeatable="true">
-    <name>SUPPLEMENT/SPECIAL ISSUE ENTRY</name>
-    <description>Information concerning the supplement or special issue associated with the target item but cataloged and/or input as a separate record (vertical relationship). When a note is generated from this field, the introductory phrase Has supplement: may be generated based on the field tag for display.</description>
+    <name>Supplement/Special Issue Entry</name>
+    <description>Information concerning the supplement or special issue associated with the target item but cataloged and/or input as a separate record (vertical relationship). When a note is generated from this field, the introductory phrase may be generated based on the field tag for display.</description>
     <indicator position="1" value="0">
       <description>Display note</description>
     </indicator>
     <indicator position="1" value="1">
-      <description>Do not display note A textual note is contained in field 580 (Linking Entry Complexity Note).</description>
+      <description>Do not display note</description>
     </indicator>
     <indicator position="2" value="#">
       <description>Has supplement</description>
@@ -6051,13 +7585,13 @@
       <description>Place, publisher, and date of publication</description>
     </subfield>
     <subfield code="g" repeatable="true">
-      <description>Relationship information</description>
+      <description>Related parts</description>
     </subfield>
     <subfield code="h" repeatable="false">
       <description>Physical description</description>
     </subfield>
-    <subfield code="i" repeatable="false">
-      <description>Display text</description>
+    <subfield code="i" repeatable="true">
+      <description>Relationship information</description>
     </subfield>
     <subfield code="k" repeatable="true">
       <description>Series data for related item</description>
@@ -6106,13 +7640,13 @@
     </subfield>
   </field>
   <field tag="772" repeatable="true">
-    <name>SUPPLEMENT PARENT ENTRY</name>
-    <description>Information concerning the related parent record when the target item is a single issue, supplement or special issue (vertical relationship) of the parent item. When a note is generated from this field, the introductory phrase Supplement to: may be generated based on the field tag for display.</description>
+    <name>Supplement Parent Entry</name>
+    <description>Information concerning the related parent record when the target item is a single issue, supplement or special issue (vertical relationship) of the parent item. When a note is generated from this field, the introductory phrase may be generated based on the field tag for display.</description>
     <indicator position="1" value="0">
       <description>Display note</description>
     </indicator>
     <indicator position="1" value="1">
-      <description>Do not display note A textual note is contained in field 580 (Linking Entry Complexity Note).</description>
+      <description>Do not display note</description>
     </indicator>
     <indicator position="2" value="#">
       <description>Supplement to</description>
@@ -6136,13 +7670,13 @@
       <description>Place, publisher, and date of publication</description>
     </subfield>
     <subfield code="g" repeatable="true">
-      <description>Relationship information</description>
+      <description>Related parts</description>
     </subfield>
     <subfield code="h" repeatable="false">
       <description>Physical description</description>
     </subfield>
-    <subfield code="i" repeatable="false">
-      <description>Display text</description>
+    <subfield code="i" repeatable="true">
+      <description>Relationship information</description>
     </subfield>
     <subfield code="k" repeatable="true">
       <description>Series data for related item</description>
@@ -6191,13 +7725,13 @@
     </subfield>
   </field>
   <field tag="773" repeatable="true">
-    <name>HOST ITEM ENTRY</name>
+    <name>Host Item Entry</name>
     <description>Information concerning the host item for the constituent unit described in the record (vertical relationship). In the case of host items that are serial or multi-volume in nature, information in subfields $g and $q is necessary to point to the exact location of the component part within the bibliographic item.</description>
     <indicator position="1" value="0">
       <description>Display note</description>
     </indicator>
     <indicator position="1" value="1">
-      <description>Do not display note A textual note is contained in field 580 (Linking Entry Complexity Note).</description>
+      <description>Do not display note</description>
     </indicator>
     <indicator position="2" value="#">
       <description>In</description>
@@ -6215,13 +7749,13 @@
       <description>Place, publisher, and date of publication</description>
     </subfield>
     <subfield code="g" repeatable="true">
-      <description>Relationship information</description>
+      <description>Related parts</description>
     </subfield>
     <subfield code="h" repeatable="false">
       <description>Physical description</description>
     </subfield>
-    <subfield code="i" repeatable="false">
-      <description>Display text</description>
+    <subfield code="i" repeatable="true">
+      <description>Relationship information</description>
     </subfield>
     <subfield code="k" repeatable="true">
       <description>Series data for related item</description>
@@ -6279,13 +7813,13 @@
     </subfield>
   </field>
   <field tag="774" repeatable="true">
-    <name>CONSTITUENT UNIT ENTRY</name>
-    <description>Information concerning a constituent unit associated with a larger bibliographic unit (vertical relationship). When a note is generated from this field, the introductory term Constituent unit: may be generated based on the field tag for display.</description>
+    <name>Constituent Unit Entry</name>
+    <description>Information concerning a constituent unit associated with a larger bibliographic unit (vertical relationship). When a note is generated from this field, the introductory term may be generated based on the field tag for display.</description>
     <indicator position="1" value="0">
       <description>Display note</description>
     </indicator>
     <indicator position="1" value="1">
-      <description>Do not display note A textual note is contained in field 580 (Linking Entry Complexity Note).</description>
+      <description>Do not display note</description>
     </indicator>
     <indicator position="2" value="#">
       <description>Constituent unit</description>
@@ -6306,13 +7840,13 @@
       <description>Place, publisher, and date of publication</description>
     </subfield>
     <subfield code="g" repeatable="true">
-      <description>Relationship information</description>
+      <description>Related parts</description>
     </subfield>
     <subfield code="h" repeatable="false">
       <description>Physical description</description>
     </subfield>
-    <subfield code="i" repeatable="false">
-      <description>Display text</description>
+    <subfield code="i" repeatable="true">
+      <description>Relationship information</description>
     </subfield>
     <subfield code="k" repeatable="true">
       <description>Series data for related item</description>
@@ -6361,13 +7895,13 @@
     </subfield>
   </field>
   <field tag="775" repeatable="true">
-    <name>OTHER EDITION ENTRY</name>
-    <description>The entry for another available edition of the target item (horizontal relationship). When a note is generated from this field, the introductory phrase Other editions available: may be generated based on the field tag for display.</description>
+    <name>Other Edition Entry</name>
+    <description>Entry for another available edition of the target item (horizontal relationship). When a note is generated from this field, the introductory phrase may be generated based on the field tag for display.</description>
     <indicator position="1" value="0">
       <description>Display note</description>
     </indicator>
     <indicator position="1" value="1">
-      <description>Do not display note A textual note is contained in field 580 (Linking Entry Complexity Note).</description>
+      <description>Do not display note</description>
     </indicator>
     <indicator position="2" value="#">
       <description>Other edition available</description>
@@ -6394,13 +7928,13 @@
       <description>Country code</description>
     </subfield>
     <subfield code="g" repeatable="true">
-      <description>Relationship information</description>
+      <description>Related parts</description>
     </subfield>
     <subfield code="h" repeatable="false">
       <description>Physical description</description>
     </subfield>
-    <subfield code="i" repeatable="false">
-      <description>Display text</description>
+    <subfield code="i" repeatable="true">
+      <description>Relationship information</description>
     </subfield>
     <subfield code="k" repeatable="true">
       <description>Series data for related item</description>
@@ -6449,13 +7983,13 @@
     </subfield>
   </field>
   <field tag="776" repeatable="true">
-    <name>ADDITIONAL PHYSICAL FORM ENTRY</name>
-    <description>Information concerning another available physical form of the target item (horizontal relationship). When a note is generated from this field, the introductory phrase Available in other form: may be generated based on the field tag for display.</description>
+    <name>Additional Physical Form Entry</name>
+    <description>Information concerning another available physical form of the target item (horizontal relationship). When a note is generated from this field, the introductory phrase may be generated based on the field tag for display.</description>
     <indicator position="1" value="0">
       <description>Display note</description>
     </indicator>
     <indicator position="1" value="1">
-      <description>Do not display note A textual note is contained in field 580 (Linking Entry Complexity Note).</description>
+      <description>Do not display note</description>
     </indicator>
     <indicator position="2" value="#">
       <description>Available in another form</description>
@@ -6476,13 +8010,13 @@
       <description>Place, publisher, and date of publication</description>
     </subfield>
     <subfield code="g" repeatable="true">
-      <description>Relationship information</description>
+      <description>Related parts</description>
     </subfield>
     <subfield code="h" repeatable="false">
       <description>Physical description</description>
     </subfield>
-    <subfield code="i" repeatable="false">
-      <description>Display text</description>
+    <subfield code="i" repeatable="true">
+      <description>Relationship information</description>
     </subfield>
     <subfield code="k" repeatable="true">
       <description>Series data for related item</description>
@@ -6531,13 +8065,13 @@
     </subfield>
   </field>
   <field tag="777" repeatable="true">
-    <name>ISSUED WITH ENTRY</name>
-    <description>Information concerning the publication that is separately cataloged but that is issued with or included in the target item (horizontal relationship). When a note is generated from this field, the introductory phrase Issued with: may be generated based on the field tag for display.</description>
+    <name>Issued With Entry</name>
+    <description>Information concerning the publication that is separately cataloged but that is issued with or included in the target item (horizontal relationship). When a note is generated from this field, the introductory phrase may be generated based on the field tag for display.</description>
     <indicator position="1" value="0">
       <description>Display note</description>
     </indicator>
     <indicator position="1" value="1">
-      <description>Do not display note A textual note is contained in field 580 (Linking Entry Complexity Note).</description>
+      <description>Do not display note</description>
     </indicator>
     <indicator position="2" value="#">
       <description>Issued with</description>
@@ -6558,13 +8092,13 @@
       <description>Place, publisher, and date of publication</description>
     </subfield>
     <subfield code="g" repeatable="true">
-      <description>Relationship information</description>
+      <description>Related parts</description>
     </subfield>
     <subfield code="h" repeatable="false">
       <description>Physical description</description>
     </subfield>
-    <subfield code="i" repeatable="false">
-      <description>Display text</description>
+    <subfield code="i" repeatable="true">
+      <description>Relationship information</description>
     </subfield>
     <subfield code="k" repeatable="true">
       <description>Series data for related item</description>
@@ -6604,37 +8138,37 @@
     </subfield>
   </field>
   <field tag="780" repeatable="true">
-    <name>PRECEDING ENTRY</name>
+    <name>Preceding Entry</name>
     <description>Information concerning the immediate predecessor of the target item (chronological relationship). When a note is generated from this field, the introductory term or phrase may be generated based on the value in the second indicator position for display.</description>
     <indicator position="1" value="0">
       <description>Display note</description>
     </indicator>
     <indicator position="1" value="1">
-      <description>Do not display note A textual note is contained in field 580 (Linking Entry Complexity Note).</description>
+      <description>Do not display note</description>
     </indicator>
     <indicator position="2" value="0">
-      <description>ContinuesContinues: may be generated for display.</description>
+      <description>Continues</description>
     </indicator>
     <indicator position="2" value="1">
-      <description>Continues in partContinues in part: may be generated for display.</description>
+      <description>Continues in part</description>
     </indicator>
     <indicator position="2" value="2">
-      <description>SupersedesSupersedes: may be generated for display.</description>
+      <description>Supersedes</description>
     </indicator>
     <indicator position="2" value="3">
-      <description>Supersedes in partSupersedes in part: may be generated for display.</description>
+      <description>Supersedes in part</description>
     </indicator>
     <indicator position="2" value="4">
-      <description>Formed by the union of... and ...Formed by the union:... and ... may be generated for display.</description>
+      <description>Formed by the union of ... and ...</description>
     </indicator>
     <indicator position="2" value="5">
-      <description>AbsorbedAbsorbed: may be generated for display.</description>
+      <description>Absorbed</description>
     </indicator>
     <indicator position="2" value="6">
-      <description>Absorbed in partAbsorbed in part: may be generated for display.</description>
+      <description>Absorbed in part</description>
     </indicator>
     <indicator position="2" value="7">
-      <description>Separated fromSeparated from: may be generated for display.</description>
+      <description>Separated from</description>
     </indicator>
     <subfield code="a" repeatable="false">
       <description>Main entry heading</description>
@@ -6649,13 +8183,13 @@
       <description>Place, publisher, and date of publication</description>
     </subfield>
     <subfield code="g" repeatable="true">
-      <description>Relationship information</description>
+      <description>Related parts</description>
     </subfield>
     <subfield code="h" repeatable="false">
       <description>Physical description</description>
     </subfield>
-    <subfield code="i" repeatable="false">
-      <description>Display text</description>
+    <subfield code="i" repeatable="true">
+      <description>Relationship information</description>
     </subfield>
     <subfield code="k" repeatable="true">
       <description>Series data for related item</description>
@@ -6704,40 +8238,40 @@
     </subfield>
   </field>
   <field tag="785" repeatable="true">
-    <name>SUCCEEDING ENTRY</name>
+    <name>Succeeding Entry</name>
     <description>Information concerning the immediate successor to the target item (chronological relationship). When a note is generated from this field, the introductory phrase may be generated based on the value in the second indicator position for display.</description>
     <indicator position="1" value="0">
       <description>Display note</description>
     </indicator>
     <indicator position="1" value="1">
-      <description>Do not display note A textual note is contained in field 580 (Linking Entry Complexity Note).</description>
+      <description>Do not display note</description>
     </indicator>
     <indicator position="2" value="0">
-      <description>Continued byContinued by: may be generated for display.</description>
+      <description>Continued by</description>
     </indicator>
     <indicator position="2" value="1">
-      <description>Continued in part byContinued in part by: may be generated for display.</description>
+      <description>Continued in part by</description>
     </indicator>
     <indicator position="2" value="2">
-      <description>Superseded bySuperseded by: may be generated for display.</description>
+      <description>Superseded by</description>
     </indicator>
     <indicator position="2" value="3">
-      <description>Superseded in part bySuperseded in part by: may be generated for display.</description>
+      <description>Superseded in part by</description>
     </indicator>
     <indicator position="2" value="4">
-      <description>Absorbed byAbsorbed by: may be generated for display.</description>
+      <description>Absorbed by</description>
     </indicator>
     <indicator position="2" value="5">
-      <description>Absorbed in part byAbsorbed in part by: may be generated for display.</description>
+      <description>Absorbed in part by</description>
     </indicator>
     <indicator position="2" value="6">
-      <description>Split into... and...Split into:... and... may be generated for display.</description>
+      <description>Split into ... and ...</description>
     </indicator>
     <indicator position="2" value="7">
-      <description>Merged with... to form ...Merged with:... to form... may be generated for display.</description>
+      <description>Merged with ... to form ...</description>
     </indicator>
     <indicator position="2" value="8">
-      <description>Changed back toChanged back to: may be generated for display.</description>
+      <description>Changed back to</description>
     </indicator>
     <subfield code="a" repeatable="false">
       <description>Main entry heading</description>
@@ -6752,13 +8286,13 @@
       <description>Place, publisher, and date of publication</description>
     </subfield>
     <subfield code="g" repeatable="true">
-      <description>Relationship information</description>
+      <description>Related parts</description>
     </subfield>
     <subfield code="h" repeatable="false">
       <description>Physical description</description>
     </subfield>
-    <subfield code="i" repeatable="false">
-      <description>Display text</description>
+    <subfield code="i" repeatable="true">
+      <description>Relationship information</description>
     </subfield>
     <subfield code="k" repeatable="true">
       <description>Series data for related item</description>
@@ -6807,13 +8341,13 @@
     </subfield>
   </field>
   <field tag="786" repeatable="true">
-    <name>DATA SOURCE ENTRY</name>
+    <name>Data Source Entry</name>
     <description>Information pertaining to a data source to which the described item is related. It may contain information about other files, printed sources, or collection procedures.</description>
     <indicator position="1" value="0">
       <description>Display note</description>
     </indicator>
     <indicator position="1" value="1">
-      <description>Do not display note A textual note is contained in field 580 (Linking Entry Complexity Note).</description>
+      <description>Do not display note</description>
     </indicator>
     <indicator position="2" value="#">
       <description>Data source</description>
@@ -6834,13 +8368,13 @@
       <description>Place, publisher, and date of publication</description>
     </subfield>
     <subfield code="g" repeatable="true">
-      <description>Relationship information</description>
+      <description>Related parts</description>
     </subfield>
     <subfield code="h" repeatable="false">
       <description>Physical description</description>
     </subfield>
-    <subfield code="i" repeatable="false">
-      <description>Display text</description>
+    <subfield code="i" repeatable="true">
+      <description>Relationship information</description>
     </subfield>
     <subfield code="j" repeatable="false">
       <description>Period of content</description>
@@ -6898,13 +8432,13 @@
     </subfield>
   </field>
   <field tag="787" repeatable="true">
-    <name>NONSPECIFIC RELATIONSHIP ENTRY</name>
+    <name>Other Relationship Entry</name>
     <description>Information concerning the work related to the target item when the relationship does not fit any of those defined in fields 760-785.</description>
     <indicator position="1" value="0">
       <description>Display note</description>
     </indicator>
     <indicator position="1" value="1">
-      <description>Do not display note A textual note is contained in field 580 (Linking Entry Complexity Note).</description>
+      <description>Do not display note</description>
     </indicator>
     <indicator position="2" value="#">
       <description>Related item</description>
@@ -6925,13 +8459,13 @@
       <description>Place, publisher, and date of publication</description>
     </subfield>
     <subfield code="g" repeatable="true">
-      <description>Relationship information</description>
+      <description>Related parts</description>
     </subfield>
     <subfield code="h" repeatable="false">
       <description>Physical description</description>
     </subfield>
-    <subfield code="i" repeatable="false">
-      <description>Display text</description>
+    <subfield code="i" repeatable="true">
+      <description>Relationship information</description>
     </subfield>
     <subfield code="k" repeatable="true">
       <description>Series data for related item</description>
@@ -6980,8 +8514,8 @@
     </subfield>
   </field>
   <field tag="800" repeatable="true">
-    <name>SERIES ADDED ENTRY--PERSONAL NAME</name>
-    <description>An author/title series added entry in which the author portion is a personal name.</description>
+    <name>Series Added Entry-Personal Name</name>
+    <description>Author/title series added entry in which the author portion is a personal name.</description>
     <indicator position="1" value="0">
       <description>Forename</description>
     </indicator>
@@ -6991,6 +8525,9 @@
     <indicator position="1" value="3">
       <description>Family name</description>
     </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>Personal name</description>
     </subfield>
@@ -7054,9 +8591,24 @@
     <subfield code="v" repeatable="false">
       <description>Volume/sequential designation</description>
     </subfield>
+    <subfield code="w" repeatable="true">
+      <description>Bibliographic record control number</description>
+    </subfield>
+    <subfield code="x" repeatable="false">
+      <description>International Standard Serial Number</description>
+    </subfield>
+    <subfield code="0" repeatable="true">
+      <description>Authority record control number</description>
+    </subfield>
+    <subfield code="3" repeatable="false">
+      <description>Materials specified</description>
+    </subfield>
     <subfield code="4" repeatable="true">
       <description>Relator code</description>
     </subfield>
+    <subfield code="5" repeatable="true">
+      <description>Institution to which field applies</description>
+    </subfield>
     <subfield code="6" repeatable="false">
       <description>Linkage</description>
     </subfield>
@@ -7065,8 +8617,8 @@
     </subfield>
   </field>
   <field tag="810" repeatable="true">
-    <name>SERIES ADDED ENTRY--CORPORATE NAME</name>
-    <description>An author/title series added entry in which the author portion is a corporate name.</description>
+    <name>Series Added Entry-Corporate Name</name>
+    <description>Author/title series added entry in which the author portion is a corporate name.</description>
     <indicator position="1" value="0">
       <description>Inverted name</description>
     </indicator>
@@ -7076,6 +8628,9 @@
     <indicator position="1" value="2">
       <description>Name in direct order</description>
     </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>Corporate name or jurisdiction name as entry element</description>
     </subfield>
@@ -7133,9 +8688,24 @@
     <subfield code="v" repeatable="false">
       <description>Volume/sequential designation</description>
     </subfield>
+    <subfield code="w" repeatable="true">
+      <description>Bibliographic record control number</description>
+    </subfield>
+    <subfield code="x" repeatable="false">
+      <description>International Standard Serial Number</description>
+    </subfield>
+    <subfield code="0" repeatable="true">
+      <description>Authority record control number</description>
+    </subfield>
+    <subfield code="3" repeatable="false">
+      <description>Materials specified</description>
+    </subfield>
     <subfield code="4" repeatable="true">
       <description>Relator code</description>
     </subfield>
+    <subfield code="5" repeatable="true">
+      <description>Institution to which field applies</description>
+    </subfield>
     <subfield code="6" repeatable="false">
       <description>Linkage</description>
     </subfield>
@@ -7144,8 +8714,8 @@
     </subfield>
   </field>
   <field tag="811" repeatable="true">
-    <name>SERIES ADDED ENTRY--MEETING NAME</name>
-    <description>An author/title series added entry in which the author portion is a meeting name.</description>
+    <name>Series Added Entry-Meeting Name</name>
+    <description>Author/title series added entry in which the author portion is a meeting name or conference name.</description>
     <indicator position="1" value="0">
       <description>Inverted name</description>
     </indicator>
@@ -7155,6 +8725,9 @@
     <indicator position="1" value="2">
       <description>Name in direct order</description>
     </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>Meeting name or jurisdiction name as entry element</description>
     </subfield>
@@ -7206,9 +8779,24 @@
     <subfield code="v" repeatable="false">
       <description>Volume/sequential designation</description>
     </subfield>
+    <subfield code="w" repeatable="true">
+      <description>Bibliographic record control number</description>
+    </subfield>
+    <subfield code="x" repeatable="false">
+      <description>International Standard Serial Number</description>
+    </subfield>
+    <subfield code="0" repeatable="true">
+      <description>Authority record control number</description>
+    </subfield>
+    <subfield code="3" repeatable="false">
+      <description>Materials specified</description>
+    </subfield>
     <subfield code="4" repeatable="true">
       <description>Relator code</description>
     </subfield>
+    <subfield code="5" repeatable="true">
+      <description>Institution to which field applies</description>
+    </subfield>
     <subfield code="6" repeatable="false">
       <description>Linkage</description>
     </subfield>
@@ -7217,11 +8805,41 @@
     </subfield>
   </field>
   <field tag="830" repeatable="true">
-    <name>SERIES ADDED ENTRY--UNIFORM TITLE</name>
-    <description>A series added entry consisting of a series title alone.</description>
-    <indicator position="2" value="0-9">
-      <description>Number of nonfiling characters</description>
+    <name>Series Added Entry-Uniform Title</name>
+    <description>Series added entry consisting of a series title alone.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
     </indicator>
+    <indicator position="2" value="0">
+      <description>No nonfiling characters</description>
+    </indicator>
+    <indicator position="2" value="1">
+      <description>Number of nonfiling characters - 1</description>
+    </indicator>
+    <indicator position="2" value="2">
+      <description>Number of nonfiling characters - 2</description>
+    </indicator>
+    <indicator position="2" value="3">
+      <description>Number of nonfiling characters - 3</description>
+    </indicator>
+    <indicator position="2" value="4">
+      <description>Number of nonfiling characters - 4</description>
+    </indicator>
+    <indicator position="2" value="5">
+      <description>Number of nonfiling characters - 5</description>
+    </indicator>
+    <indicator position="2" value="6">
+      <description>Number of nonfiling characters - 6</description>
+    </indicator>
+    <indicator position="2" value="7">
+      <description>Number of nonfiling characters - 7</description>
+    </indicator>
+    <indicator position="2" value="8">
+      <description>Number of nonfiling characters - 8</description>
+    </indicator>
+    <indicator position="2" value="9">
+      <description>Number of nonfiling characters - 9</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>Uniform title</description>
     </subfield>
@@ -7267,6 +8885,21 @@
     <subfield code="v" repeatable="false">
       <description>Volume/sequential designation</description>
     </subfield>
+    <subfield code="w" repeatable="true">
+      <description>Bibliographic record control number</description>
+    </subfield>
+    <subfield code="x" repeatable="false">
+      <description>International Standard Serial Number</description>
+    </subfield>
+    <subfield code="0" repeatable="true">
+      <description>Authority record control number</description>
+    </subfield>
+    <subfield code="3" repeatable="false">
+      <description>Materials specified</description>
+    </subfield>
+    <subfield code="5" repeatable="true">
+      <description>Institution to which field applies</description>
+    </subfield>
     <subfield code="6" repeatable="false">
       <description>Linkage</description>
     </subfield>
@@ -7275,58 +8908,157 @@
     </subfield>
   </field>
   <field tag="841" repeatable="false">
-    <name>HOLDINGS CODED DATA VALUES</name>
-    <description>[Described in full under field 841 in the MARC 21 Concise Format for Holdings Data.]</description>
-    <subfield code="a" repeatable="true">
-      <description>Holding institution</description>
+    <name>Holdings Coded Data Values</name>
+    <description>When holdings data are embedded in a bibliographic record, this field contains certain coded information that would apply to the holdings information if it were in a separate holdings record in field 008 (Fixed-Length Data Elements).</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Type of record</description>
     </subfield>
-    <subfield code="8" repeatable="true">
-      <description>Field link and sequence number</description>
+    <subfield code="b" repeatable="false">
+      <description>Fixed-length data elements</description>
     </subfield>
+    <subfield code="e" repeatable="false">
+      <description>Encoding level</description>
+    </subfield>
   </field>
   <field tag="842" repeatable="false">
-    <name>TEXTUAL PHYSICAL FORM DESIGNATOR</name>
-    <description>[Described in full under field 842 in the MARC 21 Concise Format for Holdings Data.]</description>
-    <subfield code="a" repeatable="true">
-      <description>Holding institution</description>
+    <name>Textual Physical Form Designator</name>
+    <description>Designation in textual form of the physical form of the item. The physical form designator specifies the physical medium or form, or type of material of the unit held. The general physical form designator in coded form is recorded in field 007 (Physical Description Fixed Field).</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Textual physical form designator</description>
     </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
     <subfield code="8" repeatable="true">
       <description>Field link and sequence number</description>
     </subfield>
   </field>
   <field tag="843" repeatable="true">
-    <name>REPRODUCTION NOTE</name>
-    <description>[Described in full under field 843 in the MARC 21 Concise Format for Holdings Data.]</description>
-    <subfield code="a" repeatable="true">
-      <description>Holding institution</description>
+    <name>Reproduction Note</name>
+    <description>Description of an item that is a reproduction of original materials. Used when an institution chooses to have the main portion of the bibliographic record description reflect the original and the notes in field 843 reflect information about the copy.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Type of reproduction</description>
     </subfield>
+    <subfield code="b" repeatable="true">
+      <description>Place of reproduction</description>
+    </subfield>
+    <subfield code="c" repeatable="true">
+      <description>Agency responsible for reproduction</description>
+    </subfield>
+    <subfield code="d" repeatable="false">
+      <description>Date of reproduction</description>
+    </subfield>
+    <subfield code="e" repeatable="false">
+      <description>Physical description of reproduction</description>
+    </subfield>
+    <subfield code="f" repeatable="true">
+      <description>Series statement of reproduction</description>
+    </subfield>
+    <subfield code="m" repeatable="true">
+      <description>Dates of publication and/or sequential designation of issues reproduced</description>
+    </subfield>
+    <subfield code="n" repeatable="true">
+      <description>Note about reproduction</description>
+    </subfield>
+    <subfield code="3" repeatable="false">
+      <description>Materials specified</description>
+    </subfield>
+    <subfield code="5" repeatable="false">
+      <description>Institution to which field applies</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="7" repeatable="false">
+      <description>Fixed-length data elements of reproduction</description>
+    </subfield>
     <subfield code="8" repeatable="true">
       <description>Field link and sequence number</description>
     </subfield>
   </field>
   <field tag="844" repeatable="false">
-    <name>NAME OF UNIT</name>
-    <description>[Described in full under field 844 in the MARC 21 Concise Format for Holdings Data.]</description>
-    <subfield code="a" repeatable="true">
-      <description>Holding institution</description>
+    <name>Name of Unit</name>
+    <description>Bibliographic title or a supplied designation describing a basic bibliographic unit, supplementary material, or an index. A supplement or index designation used as a caption is contained in fields 853-855 (Captions and Pattern), subfield $a-$h (Enumeration captions).</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Name of unit</description>
     </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
     <subfield code="8" repeatable="true">
       <description>Field link and sequence number</description>
     </subfield>
   </field>
   <field tag="845" repeatable="true">
-    <name>TERMS GOVERNING USE AND REPRODUCTION NOTE</name>
-    <description>[Described in full under field 845 in the MARC 21 Concise Format for Holdings Data.]</description>
-    <subfield code="a" repeatable="true">
-      <description>Holding institution</description>
+    <name>Terms Governing Use and Reproduction Note</name>
+    <description>Terms governing the use and reproduction of a bibliographic item when the holding organization will lend (008/20, Lending policy, code a) and reproduce (008/21, Reproduction policy, code a) the item.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="false">
+      <description>Terms governing use and reproduction</description>
     </subfield>
+    <subfield code="b" repeatable="false">
+      <description>Jurisdiction</description>
+    </subfield>
+    <subfield code="c" repeatable="false">
+      <description>Authorization</description>
+    </subfield>
+    <subfield code="d" repeatable="false">
+      <description>Authorized users</description>
+    </subfield>
+    <subfield code="u" repeatable="true">
+      <description>Uniform Resource Identifier</description>
+    </subfield>
+    <subfield code="3" repeatable="false">
+      <description>Materials specified</description>
+    </subfield>
+    <subfield code="5" repeatable="false">
+      <description>Institution to which field applies</description>
+    </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
     <subfield code="8" repeatable="true">
       <description>Field link and sequence number</description>
     </subfield>
   </field>
   <field tag="850" repeatable="true">
-    <name>HOLDING INSTITUTION</name>
+    <name>Holding Institution</name>
     <description>Information concerning holdings of the described item by the specified institution.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="true">
       <description>Holding institution</description>
     </subfield>
@@ -7335,7 +9067,7 @@
     </subfield>
   </field>
   <field tag="852" repeatable="true">
-    <name>LOCATION</name>
+    <name>Location</name>
     <description>Identifies the organization holding the item or from which it is available. May also contain detailed information about how to locate the item in a collection.</description>
     <indicator position="1" value="#">
       <description>No information provided</description>
@@ -7356,7 +9088,7 @@
       <description>Shelving control number</description>
     </indicator>
     <indicator position="1" value="5">
-      <description>Title Indicates that the item is shelved by a title. If necessary, this title is contained in subfield $l (Shelving form of title).</description>
+      <description>Title</description>
     </indicator>
     <indicator position="1" value="6">
       <description>Shelved separately</description>
@@ -7374,10 +9106,10 @@
       <description>Not enumeration</description>
     </indicator>
     <indicator position="2" value="1">
-      <description>Primary enumeration This value is also used when only one numbering scheme is applicable.</description>
+      <description>Primary enumeration</description>
     </indicator>
     <indicator position="2" value="2">
-      <description>Alternative enumeration Item carries two numbering schemes and is shelved by the secondary scheme.</description>
+      <description>Alternative enumeration</description>
     </indicator>
     <subfield code="a" repeatable="false">
       <description>Location</description>
@@ -7388,6 +9120,9 @@
     <subfield code="c" repeatable="true">
       <description>Shelving location</description>
     </subfield>
+    <subfield code="d" repeatable="true">
+      <description>Former shelving location</description>
+    </subfield>
     <subfield code="e" repeatable="true">
       <description>Address</description>
     </subfield>
@@ -7453,137 +9188,322 @@
     </subfield>
   </field>
   <field tag="853" repeatable="true">
-    <name>CAPTIONS AND PATTERN--BASIC BIBLIOGRAPHIC UNIT</name>
-    <description>[Described in full under field 853 in the MARC 21 Concise Format for Holdings Data.]</description>
-    <indicator position="1" value="#">
-      <description>No information provided</description>
-    </indicator>
+    <name>Captions and Pattern - Basic Bibliographic Unit</name>
+    <description>Captions that identify the enumeration and chronology levels and codes that define the publication pattern of the holdings described in the 863-865 Enumeration and Chronology fields. Any related 853-855 and 863-865 fields are linked by a number in subfield $8 (Field link and sequence number).</description>
     <indicator position="1" value="0">
-      <description>Email Access to the electronic resource is through electronic mail (email).</description>
+      <description>Cannot compress or expand</description>
     </indicator>
     <indicator position="1" value="1">
-      <description>FTP</description>
+      <description>Can compress but not expand</description>
     </indicator>
     <indicator position="1" value="2">
-      <description>Remote login (Telnet)</description>
+      <description>Can compress or expand</description>
     </indicator>
     <indicator position="1" value="3">
-      <description>Dial-up Indicates that access to the electronic resource is through a conventional telephone line.</description>
+      <description>Unknown</description>
     </indicator>
-    <indicator position="1" value="4">
-      <description>HTTP Indicates that access to the electronic resource is through the Hypertext Transfer Protocol.</description>
+    <indicator position="2" value="0">
+      <description>Captions verified; all levels present</description>
     </indicator>
-    <indicator position="1" value="7">
-      <description>Method specified in subfield $2</description>
+    <indicator position="2" value="1">
+      <description>Captions verified; all levels may not be present</description>
     </indicator>
-    <indicator position="2" value="#">
-      <description>No information provided</description>
+    <indicator position="2" value="2">
+      <description>Captions unverified; all levels present</description>
     </indicator>
+    <indicator position="2" value="3">
+      <description>Captions unverified; all levels may not be present</description>
+    </indicator>
+    <subfield code="a" repeatable="true">
+      <description>First level of enumeration</description>
+    </subfield>
+    <subfield code="b" repeatable="true">
+      <description>Second level of enumeration</description>
+    </subfield>
+    <subfield code="c" repeatable="true">
+      <description>Third level of enumeration</description>
+    </subfield>
+    <subfield code="d" repeatable="true">
+      <description>Fourth level of enumeration</description>
+    </subfield>
+    <subfield code="e" repeatable="true">
+      <description>Fifth level of enumeration</description>
+    </subfield>
+    <subfield code="f" repeatable="true">
+      <description>Sixth level of enumeration</description>
+    </subfield>
+    <subfield code="g" repeatable="true">
+      <description>Alternative numbering scheme, first level of enumeration</description>
+    </subfield>
+    <subfield code="h" repeatable="true">
+      <description>Alternative numbering scheme, second level of enumeration</description>
+    </subfield>
+    <subfield code="i" repeatable="true">
+      <description>First level of chronology</description>
+    </subfield>
+    <subfield code="j" repeatable="true">
+      <description>Second level of chronology</description>
+    </subfield>
+    <subfield code="k" repeatable="true">
+      <description>Third level of chronology</description>
+    </subfield>
+    <subfield code="l" repeatable="true">
+      <description>Fourth level of chronology</description>
+    </subfield>
+    <subfield code="m" repeatable="true">
+      <description>Alternative numbering scheme, chronology</description>
+    </subfield>
+    <subfield code="n" repeatable="true">
+      <description>Pattern note</description>
+    </subfield>
+    <subfield code="o" repeatable="true">
+      <description>Type of unit</description>
+    </subfield>
+    <subfield code="p" repeatable="true">
+      <description>Number of pieces per issuance</description>
+    </subfield>
+    <subfield code="t" repeatable="true">
+      <description>Copy</description>
+    </subfield>
+    <subfield code="u" repeatable="true">
+      <description>Bibliographic units per next higher level</description>
+    </subfield>
+    <subfield code="v" repeatable="true">
+      <description>Numbering continuity</description>
+    </subfield>
+    <subfield code="w" repeatable="true">
+      <description>Frequency</description>
+    </subfield>
+    <subfield code="x" repeatable="true">
+      <description>Calendar change</description>
+    </subfield>
+    <subfield code="y" repeatable="true">
+      <description>Regularity pattern</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Numbering scheme</description>
+    </subfield>
+    <subfield code="2" repeatable="true">
+      <description>Source of caption abbreviation</description>
+    </subfield>
+    <subfield code="3" repeatable="true">
+      <description>Materials specified</description>
+    </subfield>
+    <subfield code="6" repeatable="true">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="854" repeatable="true">
+    <name>Captions and Pattern - Supplementary Material</name>
+    <description>Captions that identify the enumeration and chronology levels and codes that define the publication pattern of the holdings described in the 863-865 Enumeration and Chronology fields. Any related 853-855 and 863-865 fields are linked by a number in subfield $8 (Field link and sequence number).</description>
+    <indicator position="1" value="0">
+      <description>Cannot compress or expand</description>
+    </indicator>
+    <indicator position="1" value="1">
+      <description>Can compress but not expand</description>
+    </indicator>
+    <indicator position="1" value="2">
+      <description>Can compress or expand</description>
+    </indicator>
+    <indicator position="1" value="3">
+      <description>Unknown</description>
+    </indicator>
     <indicator position="2" value="0">
-      <description>Resource Indicates that the electronic location in field 856 is for the same resource described by the record as a whole. In this case, the item represented by the bibliographic record is an electronic resource. If the data in field 856 relates to a constituent unit of the resource represented by the record, subfield $3 is used to specify the portion(s) to which the field applies.</description>
+      <description>Captions verified; all levels present</description>
     </indicator>
     <indicator position="2" value="1">
-      <description>Version of resource Indicates that the location in field 856 is for an electronic version of the resource described by the record. In this case, the item represented by the bibliographic record is not electronic but an electronic version is available. If the data in field 856 relates to a constituent unit of the resource represented by the record, subfield $3 is used to specify the portion(s) to which the field applies.</description>
+      <description>Captions verified; all levels may not be present</description>
     </indicator>
     <indicator position="2" value="2">
-      <description>Related resource Indicates that the location in field 856 is for an electronic resource that is related to the item described by the record. In this case, the item represented by the bibliographic record is not the electronic resource itself. Subfield $3 can be used to further characterize the relationship between the electronic item identified in field 856 and the item represented by the bibliographic record as a whole.</description>
+      <description>Captions unverified; all levels present</description>
     </indicator>
-    <indicator position="2" value="8">
-      <description>No display constant generated</description>
+    <indicator position="2" value="3">
+      <description>Captions unverified; all levels may not be present</description>
     </indicator>
     <subfield code="a" repeatable="true">
-      <description>Host name</description>
+      <description>First level of enumeration</description>
     </subfield>
     <subfield code="b" repeatable="true">
-      <description>Access number</description>
+      <description>Second level of enumeration</description>
     </subfield>
     <subfield code="c" repeatable="true">
-      <description>Compression information</description>
+      <description>Third level of enumeration</description>
     </subfield>
     <subfield code="d" repeatable="true">
-      <description>Path</description>
+      <description>Fourth level of enumeration</description>
     </subfield>
+    <subfield code="e" repeatable="true">
+      <description>Fifth level of enumeration</description>
+    </subfield>
     <subfield code="f" repeatable="true">
-      <description>Electronic name</description>
+      <description>Sixth level of enumeration</description>
     </subfield>
-    <subfield code="h" repeatable="false">
-      <description>Processor of request</description>
+    <subfield code="g" repeatable="true">
+      <description>Alternative numbering scheme, first level of enumeration</description>
     </subfield>
+    <subfield code="h" repeatable="true">
+      <description>Alternative numbering scheme, second level of enumeration</description>
+    </subfield>
     <subfield code="i" repeatable="true">
-      <description>Instruction</description>
+      <description>First level of chronology</description>
     </subfield>
-    <subfield code="j" repeatable="false">
-      <description>Bits per second</description>
+    <subfield code="j" repeatable="true">
+      <description>Second level of chronology</description>
     </subfield>
-    <subfield code="k" repeatable="false">
-      <description>Password</description>
+    <subfield code="k" repeatable="true">
+      <description>Third level of chronology</description>
     </subfield>
-    <subfield code="l" repeatable="false">
-      <description>Logon</description>
+    <subfield code="l" repeatable="true">
+      <description>Fourth level of chronology</description>
     </subfield>
     <subfield code="m" repeatable="true">
-      <description>Contact for access assistance</description>
+      <description>Alternative numbering scheme, chronology</description>
     </subfield>
-    <subfield code="n" repeatable="false">
-      <description>Name of location of host</description>
+    <subfield code="n" repeatable="true">
+      <description>Pattern note</description>
     </subfield>
-    <subfield code="o" repeatable="false">
-      <description>Operating system</description>
+    <subfield code="o" repeatable="true">
+      <description>Type of unit</description>
     </subfield>
-    <subfield code="p" repeatable="false">
-      <description>Port</description>
+    <subfield code="p" repeatable="true">
+      <description>Number of pieces per issuance</description>
     </subfield>
-    <subfield code="q" repeatable="false">
-      <description>Electronic format type</description>
+    <subfield code="t" repeatable="true">
+      <description>Copy</description>
     </subfield>
-    <subfield code="r" repeatable="false">
-      <description>Settings</description>
+    <subfield code="u" repeatable="true">
+      <description>Bibliographic units per next higher level</description>
     </subfield>
-    <subfield code="s" repeatable="true">
-      <description>File size</description>
+    <subfield code="v" repeatable="true">
+      <description>Numbering continuity</description>
     </subfield>
+    <subfield code="w" repeatable="true">
+      <description>Frequency</description>
+    </subfield>
+    <subfield code="x" repeatable="true">
+      <description>Calendar change</description>
+    </subfield>
+    <subfield code="y" repeatable="true">
+      <description>Regularity pattern</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Numbering scheme</description>
+    </subfield>
+    <subfield code="2" repeatable="true">
+      <description>Source of caption abbreviation</description>
+    </subfield>
+    <subfield code="3" repeatable="true">
+      <description>Materials specified</description>
+    </subfield>
+    <subfield code="6" repeatable="true">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
+  </field>
+  <field tag="855" repeatable="true">
+    <name>Captions and Pattern - Indexes</name>
+    <description>Captions that identify the enumeration and chronology levels and codes that define the publication pattern of the holdings described in the 863-865 Enumeration and Chronology fields. Any related 853-855 and 863-865 fields are linked by a number in subfield $8 (Field link and sequence number).</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="true">
+      <description>First level of enumeration</description>
+    </subfield>
+    <subfield code="b" repeatable="true">
+      <description>Second level of enumeration</description>
+    </subfield>
+    <subfield code="c" repeatable="true">
+      <description>Third level of enumeration</description>
+    </subfield>
+    <subfield code="d" repeatable="true">
+      <description>Fourth level of enumeration</description>
+    </subfield>
+    <subfield code="e" repeatable="true">
+      <description>Fifth level of enumeration</description>
+    </subfield>
+    <subfield code="f" repeatable="true">
+      <description>Sixth level of enumeration</description>
+    </subfield>
+    <subfield code="g" repeatable="true">
+      <description>Alternative numbering scheme, first level of enumeration</description>
+    </subfield>
+    <subfield code="h" repeatable="true">
+      <description>Alternative numbering scheme, second level of enumeration</description>
+    </subfield>
+    <subfield code="i" repeatable="true">
+      <description>First level of chronology</description>
+    </subfield>
+    <subfield code="j" repeatable="true">
+      <description>Second level of chronology</description>
+    </subfield>
+    <subfield code="k" repeatable="true">
+      <description>Third level of chronology</description>
+    </subfield>
+    <subfield code="l" repeatable="true">
+      <description>Fourth level of chronology</description>
+    </subfield>
+    <subfield code="m" repeatable="true">
+      <description>Alternative numbering scheme, chronology</description>
+    </subfield>
+    <subfield code="n" repeatable="true">
+      <description>Pattern note</description>
+    </subfield>
+    <subfield code="o" repeatable="true">
+      <description>Type of unit</description>
+    </subfield>
+    <subfield code="p" repeatable="true">
+      <description>Number of pieces per issuance</description>
+    </subfield>
     <subfield code="t" repeatable="true">
-      <description>Terminal emulation</description>
+      <description>Copy</description>
     </subfield>
     <subfield code="u" repeatable="true">
-      <description>Uniform Resource Identifier</description>
+      <description>Bibliographic units per next higher level</description>
     </subfield>
     <subfield code="v" repeatable="true">
-      <description>Hours access method available</description>
+      <description>Numbering continuity</description>
     </subfield>
     <subfield code="w" repeatable="true">
-      <description>Record control number</description>
+      <description>Frequency</description>
     </subfield>
     <subfield code="x" repeatable="true">
-      <description>Nonpublic note</description>
+      <description>Calendar change</description>
     </subfield>
     <subfield code="y" repeatable="true">
-      <description>Link text</description>
+      <description>Regularity pattern</description>
     </subfield>
     <subfield code="z" repeatable="true">
-      <description>Public note</description>
+      <description>Numbering scheme</description>
     </subfield>
-    <subfield code="2" repeatable="false">
-      <description>Access method</description>
+    <subfield code="2" repeatable="true">
+      <description>Source of caption abbreviation</description>
     </subfield>
-    <subfield code="3" repeatable="false">
+    <subfield code="3" repeatable="true">
       <description>Materials specified</description>
     </subfield>
-    <subfield code="6" repeatable="false">
+    <subfield code="6" repeatable="true">
       <description>Linkage</description>
     </subfield>
     <subfield code="8" repeatable="true">
       <description>Field link and sequence number</description>
     </subfield>
   </field>
-  <field tag="854" repeatable="true">
-    <name>CAPTIONS AND PATTERN--SUPPLEMENTARY MATERIAL</name>
-    <description>[Described in full under field 854 in the MARC 21 Concise Format for Holdings Data.]</description>
+  <field tag="856" repeatable="true">
+    <name>Electronic Location and Access</name>
+    <description>Information needed to locate and access an electronic resource. The field may be used in a bibliographic record for a resource when that resource or a subset of it is available electronically. In addition, it may be used to locate and access an electronic version of a non-electronic resource described in the bibliographic record or a related electronic resource.</description>
     <indicator position="1" value="#">
       <description>No information provided</description>
     </indicator>
     <indicator position="1" value="0">
-      <description>Email Access to the electronic resource is through electronic mail (email).</description>
+      <description>Email</description>
     </indicator>
     <indicator position="1" value="1">
       <description>FTP</description>
@@ -7592,10 +9512,10 @@
       <description>Remote login (Telnet)</description>
     </indicator>
     <indicator position="1" value="3">
-      <description>Dial-up Indicates that access to the electronic resource is through a conventional telephone line.</description>
+      <description>Dial-up</description>
     </indicator>
     <indicator position="1" value="4">
-      <description>HTTP Indicates that access to the electronic resource is through the Hypertext Transfer Protocol.</description>
+      <description>HTTP</description>
     </indicator>
     <indicator position="1" value="7">
       <description>Method specified in subfield $2</description>
@@ -7604,13 +9524,13 @@
       <description>No information provided</description>
     </indicator>
     <indicator position="2" value="0">
-      <description>Resource Indicates that the electronic location in field 856 is for the same resource described by the record as a whole. In this case, the item represented by the bibliographic record is an electronic resource. If the data in field 856 relates to a constituent unit of the resource represented by the record, subfield $3 is used to specify the portion(s) to which the field applies.</description>
+      <description>Resource</description>
     </indicator>
     <indicator position="2" value="1">
-      <description>Version of resource Indicates that the location in field 856 is for an electronic version of the resource described by the record. In this case, the item represented by the bibliographic record is not electronic but an electronic version is available. If the data in field 856 relates to a constituent unit of the resource represented by the record, subfield $3 is used to specify the portion(s) to which the field applies.</description>
+      <description>Version of resource</description>
     </indicator>
     <indicator position="2" value="2">
-      <description>Related resource Indicates that the location in field 856 is for an electronic resource that is related to the item described by the record. In this case, the item represented by the bibliographic record is not the electronic resource itself. Subfield $3 can be used to further characterize the relationship between the electronic item identified in field 856 and the item represented by the bibliographic record as a whole.</description>
+      <description>Related resource</description>
     </indicator>
     <indicator position="2" value="8">
       <description>No display constant generated</description>
@@ -7700,416 +9620,667 @@
       <description>Field link and sequence number</description>
     </subfield>
   </field>
-  <field tag="855" repeatable="true">
-    <name>CAPTIONS AND PATTERN--INDEXES</name>
-    <description>[Described in full under field 855 in the MARC 21 Concise Format for Holdings Data.]</description>
+  <field tag="863" repeatable="true">
+    <name>Enumeration and Chronology - Basic Bibliographic Unit</name>
+    <description>Description of the holdings of a bibliographic item in the collections of the reporting organization. The captions that identify the enumeration and chronology levels and the codes that define the publication pattern of the holdings are contained in the Captions and Pattern fields (853-855) that are linked to the 863-865 fields by a number in subfield $8 (Field link and sequence number).</description>
     <indicator position="1" value="#">
       <description>No information provided</description>
     </indicator>
-    <indicator position="1" value="0">
-      <description>Email Access to the electronic resource is through electronic mail (email).</description>
-    </indicator>
-    <indicator position="1" value="1">
-      <description>FTP</description>
-    </indicator>
-    <indicator position="1" value="2">
-      <description>Remote login (Telnet)</description>
-    </indicator>
     <indicator position="1" value="3">
-      <description>Dial-up Indicates that access to the electronic resource is through a conventional telephone line.</description>
+      <description>Holdings level 3</description>
     </indicator>
     <indicator position="1" value="4">
-      <description>HTTP Indicates that access to the electronic resource is through the Hypertext Transfer Protocol.</description>
+      <description>Holdings level 4</description>
     </indicator>
-    <indicator position="1" value="7">
-      <description>Method specified in subfield $2</description>
+    <indicator position="1" value="5">
+      <description>Holdings level 4 with piece designation</description>
     </indicator>
     <indicator position="2" value="#">
       <description>No information provided</description>
     </indicator>
     <indicator position="2" value="0">
-      <description>Resource Indicates that the electronic location in field 856 is for the same resource described by the record as a whole. In this case, the item represented by the bibliographic record is an electronic resource. If the data in field 856 relates to a constituent unit of the resource represented by the record, subfield $3 is used to specify the portion(s) to which the field applies.</description>
+      <description>Compressed</description>
     </indicator>
     <indicator position="2" value="1">
-      <description>Version of resource Indicates that the location in field 856 is for an electronic version of the resource described by the record. In this case, the item represented by the bibliographic record is not electronic but an electronic version is available. If the data in field 856 relates to a constituent unit of the resource represented by the record, subfield $3 is used to specify the portion(s) to which the field applies.</description>
+      <description>Uncompressed</description>
     </indicator>
     <indicator position="2" value="2">
-      <description>Related resource Indicates that the location in field 856 is for an electronic resource that is related to the item described by the record. In this case, the item represented by the bibliographic record is not the electronic resource itself. Subfield $3 can be used to further characterize the relationship between the electronic item identified in field 856 and the item represented by the bibliographic record as a whole.</description>
+      <description>Compressed, use textual display</description>
     </indicator>
-    <indicator position="2" value="8">
-      <description>No display constant generated</description>
+    <indicator position="2" value="3">
+      <description>Uncompressed, use textual display</description>
     </indicator>
+    <indicator position="2" value="4">
+      <description>Item(s) not published</description>
+    </indicator>
     <subfield code="a" repeatable="true">
-      <description>Host name</description>
+      <description>First level of enumeration</description>
     </subfield>
     <subfield code="b" repeatable="true">
-      <description>Access number</description>
+      <description>Second level of enumeration</description>
     </subfield>
     <subfield code="c" repeatable="true">
-      <description>Compression information</description>
+      <description>Third level of enumeration</description>
     </subfield>
     <subfield code="d" repeatable="true">
-      <description>Path</description>
+      <description>Fourth level of enumeration</description>
     </subfield>
+    <subfield code="e" repeatable="true">
+      <description>Fifth level of enumeration</description>
+    </subfield>
     <subfield code="f" repeatable="true">
-      <description>Electronic name</description>
+      <description>Sixth level of enumeration</description>
     </subfield>
-    <subfield code="h" repeatable="false">
-      <description>Processor of request</description>
+    <subfield code="g" repeatable="true">
+      <description>Alternative numbering scheme, first level of enumeration</description>
     </subfield>
+    <subfield code="h" repeatable="true">
+      <description>Alternative numbering scheme, second level of enumeration</description>
+    </subfield>
     <subfield code="i" repeatable="true">
-      <description>Instruction</description>
+      <description>First level of chronology</description>
     </subfield>
-    <subfield code="j" repeatable="false">
-      <description>Bits per second</description>
+    <subfield code="j" repeatable="true">
+      <description>Second level of chronology</description>
     </subfield>
-    <subfield code="k" repeatable="false">
-      <description>Password</description>
+    <subfield code="k" repeatable="true">
+      <description>Third level of chronology</description>
     </subfield>
-    <subfield code="l" repeatable="false">
-      <description>Logon</description>
+    <subfield code="l" repeatable="true">
+      <description>Fourth level of chronology</description>
     </subfield>
     <subfield code="m" repeatable="true">
-      <description>Contact for access assistance</description>
+      <description>Alternative numbering scheme, chronology</description>
     </subfield>
-    <subfield code="n" repeatable="false">
-      <description>Name of location of host</description>
+    <subfield code="n" repeatable="true">
+      <description>Converted Gregorian year</description>
     </subfield>
-    <subfield code="o" repeatable="false">
-      <description>Operating system</description>
+    <subfield code="o" repeatable="true">
+      <description>Type of unit</description>
     </subfield>
-    <subfield code="p" repeatable="false">
-      <description>Port</description>
+    <subfield code="p" repeatable="true">
+      <description>Piece designation</description>
     </subfield>
-    <subfield code="q" repeatable="false">
-      <description>Electronic format type</description>
+    <subfield code="q" repeatable="true">
+      <description>Piece physical condition</description>
     </subfield>
-    <subfield code="r" repeatable="false">
-      <description>Settings</description>
-    </subfield>
     <subfield code="s" repeatable="true">
-      <description>File size</description>
+      <description>Copyright article-fee code</description>
     </subfield>
     <subfield code="t" repeatable="true">
-      <description>Terminal emulation</description>
+      <description>Copy number</description>
     </subfield>
-    <subfield code="u" repeatable="true">
-      <description>Uniform Resource Identifier</description>
-    </subfield>
     <subfield code="v" repeatable="true">
-      <description>Hours access method available</description>
+      <description>Issuing date</description>
     </subfield>
     <subfield code="w" repeatable="true">
-      <description>Record control number</description>
+      <description>Break indicator</description>
     </subfield>
     <subfield code="x" repeatable="true">
       <description>Nonpublic note</description>
     </subfield>
-    <subfield code="y" repeatable="true">
-      <description>Link text</description>
-    </subfield>
     <subfield code="z" repeatable="true">
       <description>Public note</description>
     </subfield>
-    <subfield code="2" repeatable="false">
-      <description>Access method</description>
-    </subfield>
-    <subfield code="3" repeatable="false">
-      <description>Materials specified</description>
-    </subfield>
-    <subfield code="6" repeatable="false">
+    <subfield code="6" repeatable="true">
       <description>Linkage</description>
     </subfield>
     <subfield code="8" repeatable="true">
       <description>Field link and sequence number</description>
     </subfield>
   </field>
-  <field tag="856" repeatable="true">
-    <name>ELECTRONIC LOCATION AND ACCESS</name>
-    <description>The information needed to locate and access an electronic resource. The field may be used in a bibliographic record for a resource when that resource or a subset of it is available electronically. In addition, it may be used to locate and access an electronic version of a non-electronic resource described in the bibliographic record or a related electronic resource.</description>
+  <field tag="864" repeatable="true">
+    <name>Enumeration and Chronology - Supplementary Material</name>
+    <description>Description of the holdings of a bibliographic item in the collections of the reporting organization. The captions that identify the enumeration and chronology levels and the codes that define the publication pattern of the holdings are contained in the Captions and Pattern fields (853-855) that are linked to the 863-865 fields by a number in subfield $8 (Field link and sequence number).</description>
     <indicator position="1" value="#">
       <description>No information provided</description>
     </indicator>
-    <indicator position="1" value="0">
-      <description>Email Access to the electronic resource is through electronic mail (email).</description>
-    </indicator>
-    <indicator position="1" value="1">
-      <description>FTP</description>
-    </indicator>
-    <indicator position="1" value="2">
-      <description>Remote login (Telnet)</description>
-    </indicator>
     <indicator position="1" value="3">
-      <description>Dial-up Indicates that access to the electronic resource is through a conventional telephone line.</description>
+      <description>Holdings level 3</description>
     </indicator>
     <indicator position="1" value="4">
-      <description>HTTP Indicates that access to the electronic resource is through the Hypertext Transfer Protocol.</description>
+      <description>Holdings level 4</description>
     </indicator>
-    <indicator position="1" value="7">
-      <description>Method specified in subfield $2</description>
+    <indicator position="1" value="5">
+      <description>Holdings level 4 with piece designation</description>
     </indicator>
     <indicator position="2" value="#">
       <description>No information provided</description>
     </indicator>
     <indicator position="2" value="0">
-      <description>Resource Indicates that the electronic location in field 856 is for the same resource described by the record as a whole. In this case, the item represented by the bibliographic record is an electronic resource. If the data in field 856 relates to a constituent unit of the resource represented by the record, subfield $3 is used to specify the portion(s) to which the field applies.</description>
+      <description>Compressed</description>
     </indicator>
     <indicator position="2" value="1">
-      <description>Version of resource Indicates that the location in field 856 is for an electronic version of the resource described by the record. In this case, the item represented by the bibliographic record is not electronic but an electronic version is available. If the data in field 856 relates to a constituent unit of the resource represented by the record, subfield $3 is used to specify the portion(s) to which the field applies.</description>
+      <description>Uncompressed</description>
     </indicator>
     <indicator position="2" value="2">
-      <description>Related resource Indicates that the location in field 856 is for an electronic resource that is related to the item described by the record. In this case, the item represented by the bibliographic record is not the electronic resource itself. Subfield $3 can be used to further characterize the relationship between the electronic item identified in field 856 and the item represented by the bibliographic record as a whole.</description>
+      <description>Compressed, use textual display</description>
     </indicator>
-    <indicator position="2" value="8">
-      <description>No display constant generated</description>
+    <indicator position="2" value="3">
+      <description>Uncompressed, use textual display</description>
     </indicator>
+    <indicator position="2" value="4">
+      <description>Item(s) not published</description>
+    </indicator>
     <subfield code="a" repeatable="true">
-      <description>Host name</description>
+      <description>First level of enumeration</description>
     </subfield>
     <subfield code="b" repeatable="true">
-      <description>Access number</description>
+      <description>Second level of enumeration</description>
     </subfield>
     <subfield code="c" repeatable="true">
-      <description>Compression information</description>
+      <description>Third level of enumeration</description>
     </subfield>
     <subfield code="d" repeatable="true">
-      <description>Path</description>
+      <description>Fourth level of enumeration</description>
     </subfield>
+    <subfield code="e" repeatable="true">
+      <description>Fifth level of enumeration</description>
+    </subfield>
     <subfield code="f" repeatable="true">
-      <description>Electronic name</description>
+      <description>Sixth level of enumeration</description>
     </subfield>
-    <subfield code="h" repeatable="false">
-      <description>Processor of request</description>
+    <subfield code="g" repeatable="true">
+      <description>Alternative numbering scheme, first level of enumeration</description>
     </subfield>
+    <subfield code="h" repeatable="true">
+      <description>Alternative numbering scheme, second level of enumeration</description>
+    </subfield>
     <subfield code="i" repeatable="true">
-      <description>Instruction</description>
+      <description>First level of chronology</description>
     </subfield>
-    <subfield code="j" repeatable="false">
-      <description>Bits per second</description>
+    <subfield code="j" repeatable="true">
+      <description>Second level of chronology</description>
     </subfield>
-    <subfield code="k" repeatable="false">
-      <description>Password</description>
+    <subfield code="k" repeatable="true">
+      <description>Third level of chronology</description>
     </subfield>
-    <subfield code="l" repeatable="false">
-      <description>Logon</description>
+    <subfield code="l" repeatable="true">
+      <description>Fourth level of chronology</description>
     </subfield>
     <subfield code="m" repeatable="true">
-      <description>Contact for access assistance</description>
+      <description>Alternative numbering scheme, chronology</description>
     </subfield>
-    <subfield code="n" repeatable="false">
-      <description>Name of location of host</description>
+    <subfield code="n" repeatable="true">
+      <description>Converted Gregorian year</description>
     </subfield>
-    <subfield code="o" repeatable="false">
-      <description>Operating system</description>
+    <subfield code="o" repeatable="true">
+      <description>Type of unit</description>
     </subfield>
-    <subfield code="p" repeatable="false">
-      <description>Port</description>
+    <subfield code="p" repeatable="true">
+      <description>Piece designation</description>
     </subfield>
-    <subfield code="q" repeatable="false">
-      <description>Electronic format type</description>
+    <subfield code="q" repeatable="true">
+      <description>Piece physical condition</description>
     </subfield>
-    <subfield code="r" repeatable="false">
-      <description>Settings</description>
-    </subfield>
     <subfield code="s" repeatable="true">
-      <description>File size</description>
+      <description>Copyright article-fee code</description>
     </subfield>
     <subfield code="t" repeatable="true">
-      <description>Terminal emulation</description>
+      <description>Copy number</description>
     </subfield>
-    <subfield code="u" repeatable="true">
-      <description>Uniform Resource Identifier</description>
-    </subfield>
     <subfield code="v" repeatable="true">
-      <description>Hours access method available</description>
+      <description>Issuing date</description>
     </subfield>
     <subfield code="w" repeatable="true">
-      <description>Record control number</description>
+      <description>Break indicator</description>
     </subfield>
     <subfield code="x" repeatable="true">
       <description>Nonpublic note</description>
     </subfield>
-    <subfield code="y" repeatable="true">
-      <description>Link text</description>
-    </subfield>
     <subfield code="z" repeatable="true">
       <description>Public note</description>
     </subfield>
-    <subfield code="2" repeatable="false">
-      <description>Access method</description>
-    </subfield>
-    <subfield code="3" repeatable="false">
-      <description>Materials specified</description>
-    </subfield>
-    <subfield code="6" repeatable="false">
+    <subfield code="6" repeatable="true">
       <description>Linkage</description>
     </subfield>
     <subfield code="8" repeatable="true">
       <description>Field link and sequence number</description>
     </subfield>
   </field>
-  <field tag="863" repeatable="true">
-    <name>ENUMERATION AND CHRONOLOGY--BASIC BIBLIOGRAPHIC UNIT</name>
-    <description>[Described in full under field 863 in the MARC 21 Concise Format for Holdings Data.]</description>
-    <subfield code="6" repeatable="false">
-      <description>Linkage</description>
+  <field tag="865" repeatable="true">
+    <name>Enumeration and Chronology - Indexes</name>
+    <description>Description of the holdings of a bibliographic item in the collections of the reporting organization. The captions that identify the enumeration and chronology levels and the codes that define the publication pattern of the holdings are contained in the Captions and Pattern fields (853-855) that are linked to the 863-865 fields by a number in subfield $8 (Field link and sequence number).</description>
+    <indicator position="1" value="#">
+      <description>No information provided</description>
+    </indicator>
+    <indicator position="1" value="4">
+      <description>Holdings level 4</description>
+    </indicator>
+    <indicator position="1" value="5">
+      <description>Holdings level 4 with piece designation</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>No information provided</description>
+    </indicator>
+    <indicator position="2" value="1">
+      <description>Uncompressed</description>
+    </indicator>
+    <indicator position="2" value="3">
+      <description>Uncompressed, use textual display</description>
+    </indicator>
+    <subfield code="a" repeatable="true">
+      <description>First level of enumeration</description>
     </subfield>
-    <subfield code="" repeatable="false">
-      <description/>
+    <subfield code="b" repeatable="true">
+      <description>Second level of enumeration</description>
     </subfield>
-    <subfield code="" repeatable="false">
-      <description/>
+    <subfield code="c" repeatable="true">
+      <description>Third level of enumeration</description>
     </subfield>
-    <subfield code="" repeatable="false">
-      <description/>
+    <subfield code="d" repeatable="true">
+      <description>Fourth level of enumeration</description>
     </subfield>
-  </field>
-  <field tag="864" repeatable="true">
-    <name>ENUMERATION AND CHRONOLOGY--SUPPLEMENTARY MATERIAL</name>
-    <description>[Described in full under field 864 in the MARC 21 Concise Format for Holdings Data.]</description>
-    <subfield code="6" repeatable="false">
-      <description>Linkage</description>
+    <subfield code="e" repeatable="true">
+      <description>Fifth level of enumeration</description>
     </subfield>
-    <subfield code="" repeatable="false">
-      <description/>
+    <subfield code="f" repeatable="true">
+      <description>Sixth level of enumeration</description>
     </subfield>
-    <subfield code="" repeatable="false">
-      <description/>
+    <subfield code="g" repeatable="true">
+      <description>Alternative numbering scheme, first level of enumeration</description>
     </subfield>
-    <subfield code="" repeatable="false">
-      <description/>
+    <subfield code="h" repeatable="true">
+      <description>Alternative numbering scheme, second level of enumeration</description>
     </subfield>
-  </field>
-  <field tag="865" repeatable="true">
-    <name>ENUMERATION AND CHRONOLOGY--INDEXES</name>
-    <description>[Described in full under field 865 in the MARC 21 Concise Format for Holdings Data.]</description>
-    <subfield code="6" repeatable="false">
-      <description>Linkage</description>
+    <subfield code="i" repeatable="true">
+      <description>First level of chronology</description>
     </subfield>
-    <subfield code="" repeatable="false">
-      <description/>
+    <subfield code="j" repeatable="true">
+      <description>Second level of chronology</description>
     </subfield>
-    <subfield code="" repeatable="false">
-      <description/>
+    <subfield code="k" repeatable="true">
+      <description>Third level of chronology</description>
     </subfield>
-    <subfield code="" repeatable="false">
-      <description/>
+    <subfield code="l" repeatable="true">
+      <description>Fourth level of chronology</description>
     </subfield>
+    <subfield code="m" repeatable="true">
+      <description>Alternative numbering scheme, chronology</description>
+    </subfield>
+    <subfield code="n" repeatable="true">
+      <description>Converted Gregorian year</description>
+    </subfield>
+    <subfield code="o" repeatable="true">
+      <description>Type of unit</description>
+    </subfield>
+    <subfield code="p" repeatable="true">
+      <description>Piece designation</description>
+    </subfield>
+    <subfield code="q" repeatable="true">
+      <description>Piece physical condition</description>
+    </subfield>
+    <subfield code="s" repeatable="true">
+      <description>Copyright article-fee code</description>
+    </subfield>
+    <subfield code="t" repeatable="true">
+      <description>Copy number</description>
+    </subfield>
+    <subfield code="v" repeatable="true">
+      <description>Issuing date</description>
+    </subfield>
+    <subfield code="w" repeatable="true">
+      <description>Break indicator</description>
+    </subfield>
+    <subfield code="x" repeatable="true">
+      <description>Nonpublic note</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Public note</description>
+    </subfield>
+    <subfield code="6" repeatable="true">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
   </field>
   <field tag="866" repeatable="true">
-    <name>TEXTUAL HOLDINGS--BASIC BIBLIOGRAPHIC UNIT</name>
-    <description>[Described in full under field 866 in the MARC 21 Concise Format for Holdings Data.]</description>
-    <subfield code="6" repeatable="false">
-      <description>Linkage</description>
+    <name>Textual Holdings - Basic Bibliographic Unit</name>
+    <description>Textual description which may include both the captions and enumeration and chronology for the holdings of a bibliographic item in the collections of the reporting organization. These fields are normally not used in holdings for single-part items. They may be used the coded 853-855 Captions and Pattern and 863-865 Enumeration and Chronology fields for multipart and serial items when those fields cannot be used adequately to describe the holdings. The 866-868 fields may also be used an Enumeration and Chronology field and any related Captions and Pattern field to record and generate an alternative display for all or part of the enumeration and chronology and captions and pattern fields.</description>
+    <indicator position="1" value="#">
+      <description>No information provided</description>
+    </indicator>
+    <indicator position="1" value="3">
+      <description>Holdings level 3</description>
+    </indicator>
+    <indicator position="1" value="4">
+      <description>Holdings level 4</description>
+    </indicator>
+    <indicator position="1" value="5">
+      <description>Holdings level 4 with piece designation</description>
+    </indicator>
+    <indicator position="2" value="0">
+      <description>Non-standard</description>
+    </indicator>
+    <indicator position="2" value="1">
+      <description>ANSI/NISO Z39.71 or ISO 10324</description>
+    </indicator>
+    <indicator position="2" value="2">
+      <description>ANSI Z39.42</description>
+    </indicator>
+    <indicator position="2" value="7">
+      <description>Source specified in subfield $2</description>
+    </indicator>
+    <subfield code="a" repeatable="true">
+      <description>Textual holdings</description>
     </subfield>
-    <subfield code="" repeatable="false">
-      <description/>
+    <subfield code="x" repeatable="true">
+      <description>Nonpublic note</description>
     </subfield>
-    <subfield code="" repeatable="false">
-      <description/>
+    <subfield code="z" repeatable="true">
+      <description>Public note</description>
     </subfield>
-    <subfield code="" repeatable="false">
-      <description/>
+    <subfield code="2" repeatable="true">
+      <description>Source of notation</description>
     </subfield>
+    <subfield code="6" repeatable="true">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
   </field>
   <field tag="867" repeatable="true">
-    <name>TEXTUAL HOLDINGS--SUPPLEMENTARY MATERIAL</name>
-    <description>[Described in full under field 867 in the MARC 21 Concise Format for Holdings Data.]</description>
-    <subfield code="6" repeatable="false">
-      <description>Linkage</description>
+    <name>Textual Holdings - Supplementary Material</name>
+    <description>Textual description which may include both the captions and enumeration and chronology for the holdings of a bibliographic item in the collections of the reporting organization. These fields are normally not used in holdings for single-part items. They may be used the coded 853-855 Captions and Pattern and 863-865 Enumeration and Chronology fields for multipart and serial items when those fields cannot be used adequately to describe the holdings. The 866-868 fields may also be used an Enumeration and Chronology field and any related Captions and Pattern field to record and generate an alternative display for all or part of the enumeration and chronology and captions and pattern fields.</description>
+    <indicator position="1" value="#">
+      <description>No information provided</description>
+    </indicator>
+    <indicator position="1" value="3">
+      <description>Holdings level 3</description>
+    </indicator>
+    <indicator position="1" value="4">
+      <description>Holdings level 4</description>
+    </indicator>
+    <indicator position="1" value="5">
+      <description>Holdings level 4 with piece designation</description>
+    </indicator>
+    <indicator position="2" value="0">
+      <description>Non-standard</description>
+    </indicator>
+    <indicator position="2" value="1">
+      <description>ANSI/NISO Z39.71 or ISO 10324</description>
+    </indicator>
+    <indicator position="2" value="2">
+      <description>ANSI Z39.42</description>
+    </indicator>
+    <indicator position="2" value="7">
+      <description>Source specified in subfield $2</description>
+    </indicator>
+    <subfield code="a" repeatable="true">
+      <description>Textual holdings</description>
     </subfield>
-    <subfield code="" repeatable="false">
-      <description/>
+    <subfield code="x" repeatable="true">
+      <description>Nonpublic note</description>
     </subfield>
-    <subfield code="" repeatable="false">
-      <description/>
+    <subfield code="z" repeatable="true">
+      <description>Public note</description>
     </subfield>
-    <subfield code="" repeatable="false">
-      <description/>
+    <subfield code="2" repeatable="true">
+      <description>Source of notation</description>
     </subfield>
+    <subfield code="6" repeatable="true">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
   </field>
   <field tag="868" repeatable="true">
-    <name>TEXTUAL HOLDINGS--INDEXES</name>
-    <description>[Described in full under field 868 in the MARC 21 Concise Format for Holdings Data.]</description>
-    <subfield code="6" repeatable="false">
-      <description>Linkage</description>
+    <name>Textual Holdings - Indexes</name>
+    <description>Textual description which may include both the captions and enumeration and chronology for the holdings of a bibliographic item in the collections of the reporting organization. These fields are normally not used in holdings for single-part items. They may be used the coded 853-855 Captions and Pattern and 863-865 Enumeration and Chronology fields for multipart and serial items when those fields cannot be used adequately to describe the holdings. The 866-868 fields may also be used an Enumeration and Chronology field and any related Captions and Pattern field to record and generate an alternative display for all or part of the enumeration and chronology and captions and pattern fields.</description>
+    <indicator position="1" value="#">
+      <description>No information provided</description>
+    </indicator>
+    <indicator position="1" value="3">
+      <description>Holdings level 3</description>
+    </indicator>
+    <indicator position="1" value="4">
+      <description>Holdings level 4</description>
+    </indicator>
+    <indicator position="1" value="5">
+      <description>Holdings level 4 with piece designation</description>
+    </indicator>
+    <indicator position="2" value="0">
+      <description>Non-standard</description>
+    </indicator>
+    <indicator position="2" value="1">
+      <description>ANSI/NISO Z39.71 or ISO 10324</description>
+    </indicator>
+    <indicator position="2" value="2">
+      <description>ANSI Z39.42</description>
+    </indicator>
+    <indicator position="2" value="7">
+      <description>Source specified in subfield $2</description>
+    </indicator>
+    <subfield code="a" repeatable="true">
+      <description>Textual holdings</description>
     </subfield>
-    <subfield code="" repeatable="false">
-      <description/>
+    <subfield code="x" repeatable="true">
+      <description>Nonpublic note</description>
     </subfield>
-    <subfield code="" repeatable="false">
-      <description/>
+    <subfield code="z" repeatable="true">
+      <description>Public note</description>
     </subfield>
-    <subfield code="" repeatable="false">
-      <description/>
+    <subfield code="2" repeatable="true">
+      <description>Source of notation</description>
     </subfield>
+    <subfield code="6" repeatable="true">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
   </field>
   <field tag="876" repeatable="true">
-    <name>ITEM INFORMATION--BASIC BIBLIOGRAPHIC UNIT</name>
-    <description>[Described in full under field 876 in the MARC 21 Concise Format for Holdings Data.]</description>
-    <subfield code="6" repeatable="false">
-      <description>Linkage</description>
+    <name>Item Information - Basic Bibliographic Unit</name>
+    <description>Item level information about the pieces to the item specified in the holdings record. They contain various data elements that it may be desirable to record for specific items for use in acquisition or circulation applications, among others.</description>
+    <indicator position="1" value="#">
+        <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+        <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="true">
+      <description>Internal item number</description>
     </subfield>
-    <subfield code="" repeatable="false">
-      <description/>
+    <subfield code="b" repeatable="true">
+      <description>Invalid or canceled internal item number</description>
     </subfield>
-    <subfield code="" repeatable="false">
-      <description/>
+    <subfield code="c" repeatable="true">
+      <description>Cost</description>
     </subfield>
-    <subfield code="" repeatable="false">
-      <description/>
+    <subfield code="d" repeatable="true">
+      <description>Date acquired</description>
     </subfield>
+    <subfield code="e" repeatable="true">
+      <description>Source of acquisition</description>
+    </subfield>
+    <subfield code="h" repeatable="true">
+      <description>Use restrictions</description>
+    </subfield>
+    <subfield code="j" repeatable="true">
+      <description>Item status</description>
+    </subfield>
+    <subfield code="l" repeatable="true">
+      <description>Temporary location</description>
+    </subfield>
+    <subfield code="p" repeatable="true">
+      <description>Piece designation</description>
+    </subfield>
+    <subfield code="r" repeatable="true">
+      <description>Invalid or canceled piece designation</description>
+    </subfield>
+    <subfield code="t" repeatable="true">
+      <description>Copy number</description>
+    </subfield>
+    <subfield code="x" repeatable="true">
+      <description>Nonpublic note</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Public note</description>
+    </subfield>
+    <subfield code="3" repeatable="true">
+      <description>Materials specified</description>
+    </subfield>
+    <subfield code="6" repeatable="true">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
   </field>
   <field tag="877" repeatable="true">
-    <name>ITEM INFORMATION--SUPPLEMENTARY MATERIAL</name>
-    <description>[Described in full under field 877 in the MARC 21 Concise Format for Holdings Data.]</description>
-    <subfield code="6" repeatable="false">
-      <description>Linkage</description>
+    <name>Item Information - Supplementary Material</name>
+    <description>Item level information about the pieces to the item specified in the holdings record. They contain various data elements that it may be desirable to record for specific items for use in acquisition or circulation applications, among others.</description>
+    <indicator position="1" value="#">
+        <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+        <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="true">
+      <description>Internal item number</description>
     </subfield>
-    <subfield code="" repeatable="false">
-      <description/>
+    <subfield code="b" repeatable="true">
+      <description>Invalid or canceled internal item number</description>
     </subfield>
-    <subfield code="" repeatable="false">
-      <description/>
+    <subfield code="c" repeatable="true">
+      <description>Cost</description>
     </subfield>
-    <subfield code="" repeatable="false">
-      <description/>
+    <subfield code="d" repeatable="true">
+      <description>Date acquired</description>
     </subfield>
+    <subfield code="e" repeatable="true">
+      <description>Source of acquisition</description>
+    </subfield>
+    <subfield code="h" repeatable="true">
+      <description>Use restrictions</description>
+    </subfield>
+    <subfield code="j" repeatable="true">
+      <description>Item status</description>
+    </subfield>
+    <subfield code="l" repeatable="true">
+      <description>Temporary location</description>
+    </subfield>
+    <subfield code="p" repeatable="true">
+      <description>Piece designation</description>
+    </subfield>
+    <subfield code="r" repeatable="true">
+      <description>Invalid or canceled piece designation</description>
+    </subfield>
+    <subfield code="t" repeatable="true">
+      <description>Copy number</description>
+    </subfield>
+    <subfield code="x" repeatable="true">
+      <description>Nonpublic note</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Public note</description>
+    </subfield>
+    <subfield code="3" repeatable="true">
+      <description>Materials specified</description>
+    </subfield>
+    <subfield code="6" repeatable="true">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
   </field>
   <field tag="878" repeatable="true">
-    <name>ITEM INFORMATION--INDEXES</name>
-    <description>[Described in full under field 878 in the MARC 21 Concise Format for Holdings Data.]</description>
-    <subfield code="6" repeatable="false">
-      <description>Linkage</description>
+    <name>Item Information - Indexes</name>
+    <description>Item level information about the pieces to the item specified in the holdings record. They contain various data elements that it may be desirable to record for specific items for use in acquisition or circulation applications, among others.</description>
+    <indicator position="1" value="#">
+        <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+        <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="true">
+      <description>Internal item number</description>
     </subfield>
-    <subfield code="" repeatable="false">
-      <description/>
+    <subfield code="b" repeatable="true">
+      <description>Invalid or canceled internal item number</description>
     </subfield>
-    <subfield code="" repeatable="false">
-      <description/>
+    <subfield code="c" repeatable="true">
+      <description>Cost</description>
     </subfield>
-    <subfield code="" repeatable="false">
-      <description/>
+    <subfield code="d" repeatable="true">
+      <description>Date acquired</description>
     </subfield>
+    <subfield code="e" repeatable="true">
+      <description>Source of acquisition</description>
+    </subfield>
+    <subfield code="h" repeatable="true">
+      <description>Use restrictions</description>
+    </subfield>
+    <subfield code="j" repeatable="true">
+      <description>Item status</description>
+    </subfield>
+    <subfield code="l" repeatable="true">
+      <description>Temporary location</description>
+    </subfield>
+    <subfield code="p" repeatable="true">
+      <description>Piece designation</description>
+    </subfield>
+    <subfield code="r" repeatable="true">
+      <description>Invalid or canceled piece designation</description>
+    </subfield>
+    <subfield code="t" repeatable="true">
+      <description>Copy number</description>
+    </subfield>
+    <subfield code="x" repeatable="true">
+      <description>Nonpublic note</description>
+    </subfield>
+    <subfield code="z" repeatable="true">
+      <description>Public note</description>
+    </subfield>
+    <subfield code="3" repeatable="true">
+      <description>Materials specified</description>
+    </subfield>
+    <subfield code="6" repeatable="true">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
   </field>
   <field tag="880" repeatable="true">
-    <name>ALTERNATE GRAPHIC REPRESENTATION</name>
-    <description>The fully content-designated representation, in a different script, of another field in the same record. Field 880 is linked to the associated regular field by subfield $6 (Linkage). The first and second indicator positions in field 880 have the same definition and values as the indicators in the associated field. The subfield codes in field 880 are the same as those defined in the associated field except for subfield $6. The data in field 880 may be in more than one script.</description>
+    <name>Alternate Graphic Representation</name>
+    <description>Fully content-designated representation, in a different script, of another field in the same record. Field 880 is linked to the associated regular field by subfield $6 (Linkage). A subfield $6 in the associated field also links that field to the 880 field. The data in field 880 may be in more than one script.</description>
     <subfield code="6" repeatable="false">
       <description>Linkage</description>
     </subfield>
-    <subfield code="" repeatable="false">
-      <description/>
+  </field>
+  <field tag="882" repeatable="false">
+    <name>Replacement Record Information</name>
+    <description>Information about the replacement bibliographic record in a deleted record. The replacement title(s) may be contained in subfield(s) $a.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <subfield code="a" repeatable="true">
+      <description>Replacement title</description>
     </subfield>
-    <subfield code="" repeatable="false">
-      <description/>
+    <subfield code="i" repeatable="true">
+      <description>Explanatory text</description>
     </subfield>
-    <subfield code="" repeatable="false">
-      <description/>
+    <subfield code="w" repeatable="true">
+      <description>Replacement bibliographic record control number</description>
     </subfield>
+    <subfield code="6" repeatable="false">
+      <description>Linkage</description>
+    </subfield>
+    <subfield code="8" repeatable="true">
+      <description>Field link and sequence number</description>
+    </subfield>
   </field>
   <field tag="886" repeatable="true">
-    <name>FOREIGN MARC INFORMATION FIELD</name>
+    <name>Foreign MARC Information Field</name>
     <description>Used when converting foreign MARC records into the MARC format. Contains data from a foreign MARC record for which there is no corresponding MARC field.</description>
     <indicator position="1" value="0">
       <description>Leader</description>
@@ -8120,6 +10291,9 @@
     <indicator position="1" value="2">
       <description>Variable data fields (010-999)</description>
     </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>Tag of the foreign MARC field</description>
     </subfield>
@@ -8129,16 +10303,16 @@
     <subfield code="2" repeatable="false">
       <description>Source of data</description>
     </subfield>
-    <subfield code="a" repeatable="true">
-      <description>Foreign MARC subfield</description>
-    </subfield>
-    <subfield code="0" repeatable="true">
-      <description>Foreign MARC subfield</description>
-    </subfield>
   </field>
   <field tag="887" repeatable="true">
-    <name>NON-MARC INFORMATION FIELD</name>
-    <description>Contains data from non-MARC records for which there are no corresponding MARC 21 fields. Used when converting non-MARC records into the MARC 21 format.</description>
+    <name>Non-MARC Information Field</name>
+    <description>Data from non-MARC records for which there are no corresponding MARC 21 fields. Used when converting non-MARC records into the MARC 21 format.</description>
+    <indicator position="1" value="#">
+      <description>Undefined</description>
+    </indicator>
+    <indicator position="2" value="#">
+      <description>Undefined</description>
+    </indicator>
     <subfield code="a" repeatable="false">
       <description>Content of non-MARC field</description>
     </subfield>

Modified: branches/serials-integration/Open-ILS/xul/staff_client/server/locale/en-US/patron.properties
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/server/locale/en-US/patron.properties	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/xul/staff_client/server/locale/en-US/patron.properties	2010-10-18 13:46:56 UTC (rev 18371)
@@ -42,6 +42,12 @@
 staff.patron.bill_history.handle_void.btn_yes=Yes
 staff.patron.bill_history.handle_void.btn_no=No
 staff.patron.bill_history.handle_void.confirm_message=Check here to confirm this message
+staff.patron.bills.handle_refund.message_plural=Are you sure you would like to refund excess payment on bills %1$s?  This action will simply put the amount in the Payment Pending column as a negative value.  You must still select Apply Payment!  Certain types of payments may not be refunded.  The refund may be applied to checked transactions that follow the refunded transaction.
+staff.patron.bills.handle_refund.message_singular=Are you sure you would like to refund excess payment on bill %1$s?  This action will simply put the amount in the Payment Pending column as a negative value.  You must still select Apply Payment!  Certain types of payments may not be refunded.  The refund may be applied to checked transactions that follow the refunded transaction.
+staff.patron.bills.handle_refund.title=Refund Excess Payment
+staff.patron.bills.handle_refund.btn_yes=Yes
+staff.patron.bills.handle_refund.btn_no=No
+staff.patron.bills.handle_refund.confirm_message=Check here to confirm this message
 staff.patron.bill_history.print_bills.print_error=printing bills
 staff.patron.bill_history.column.xact_type.label=Transaction Type
 staff.patron.bill_history.column.last_billing_type.label=Last Billing Type
@@ -335,6 +341,8 @@
 staff.patron.search_result.init.search_print=patron search print
 staff.patron.search_result.init.search_clipboard=patron search clipboard
 staff.patron.search_result.init.search_saving_columns=patron search saving columns
+staff.patron.search_result.mailing_address_column_label_prefix=Mailing Addr: 
+staff.patron.search_result.billing_address_column_label_prefix=Billing Addr: 
 staff.patron.summary.patron_bill.money=$ %1$s
 staff.patron.summary.retrieve.no_barcode=summary: No barcode or ID
 staff.patron.summary.patron_net_access=Internet

Modified: branches/serials-integration/Open-ILS/xul/staff_client/server/locale/en-US/serial.properties
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/server/locale/en-US/serial.properties	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/xul/staff_client/server/locale/en-US/serial.properties	2010-10-18 13:46:56 UTC (rev 18371)
@@ -53,3 +53,32 @@
 staff.serial.manage_subs.delete_ssub.confirm.plural=Are you sure you would like to delete these %1$s subscriptions?
 staff.serial.manage_subs.delete_ssub.title=Delete Subscriptions?
 staff.serial.manage_subs.delete_ssub.override=Override Delete Failure? Doing so will delete all related data as well!
+batch_receive.bib_lookup.empty=Enter a search term.
+batch_receive.bib_lookup.multiple=Multiple matching records found. Please use a more specific identifier, or use the catalog to find the exact record you want.
+batch_receive.bib_lookup.not_found=No matching records found with any subscriptions attached.
+batch_receive.issuance_lookup.error=Problem retrieving issuances related to subscription.
+batch_receive.issuance_lookup.none=There are no receivable issuances.
+batch_receive.item_lookup.none=Could not retrieve receivable items for this issuance.
+batch_receive.autogen_barcodes.questionable=There are already barcodes entered further down the list than the one you just entered.\nFill the intervening fields with auto-generated barcodes?
+batch_receive.autogen_barcodes.remove=Clear the barcodes that have already been auto-generated?
+batch_receive.none=[None]
+batch_receive.apply=Apply
+batch_receive.receive_time_note=Receive-time Note
+batch_receive.cn_for_lib=Do you want to use this call number at %1$s?\nIt doesn't exist there, and it will have to be created.
+batch_receive.missing_units=You have not provided barcodes and call numbers for all of the selected items.  Choose OK to receive those items anyway, or choose Cancel to supply the missing information.
+batch_receive.missing_cn=You cannot assign a barcode without selecting a call number. Please correct the non-conforming units.
+pattern_wizard.enumeration.a=First level
+pattern_wizard.enumeration.b=Second level
+pattern_wizard.enumeration.c=Third level
+pattern_wizard.enumeration.d=Fourth level
+pattern_wizard.enumeration.e=Fifth level
+pattern_wizard.enumeration.f=Sixth level
+pattern_wizard.enumeration.g=First alternate
+pattern_wizard.enumeration.h=Second alternate
+pattern_wizard.chronology.i=First level
+pattern_wizard.chronology.j=Second level
+pattern_wizard.chronology.k=Third level
+pattern_wizard.chronology.l=Fourth level
+pattern_wizard.chronology.m=Alternative numbering scheme
+pattern_wizard.not_removable_row=You cannot remove this row because it's not at the end of the sequence.  Remove later rows first.
+pattern_wizard.bad_date_value=That is not a valid day for that month.

Modified: branches/serials-integration/Open-ILS/xul/staff_client/server/patron/bill2.js
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/server/patron/bill2.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/xul/staff_client/server/patron/bill2.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -78,6 +78,12 @@
             false
         );
 
+        $('refund').addEventListener(
+            'command',
+            handle_refund,
+            false
+        );
+
         $('opac').addEventListener(
             'command',
             handle_opac,
@@ -95,7 +101,7 @@
             function(ev) {
                 if ($('payment_type').value == 'credit_payment') {
                     JSAN.use('util.money');
-                    JSAN.use('patron.util'); g.patron = patron.util.retrieve_au_via_id(ses(),g.patron_id);
+                    JSAN.use('patron.util'); g.patron = patron.util.retrieve_fleshed_au_via_id(ses(),g.patron_id,null);
                     var proposed = util.money.dollars_float_to_cents_integer(ev.target.value);
                     var available = util.money.dollars_float_to_cents_integer(g.patron.credit_forward_balance());
                     if (proposed > available) {
@@ -319,6 +325,33 @@
     }
 }
 
+function handle_refund() {
+    if(g.bill_list_selection.length > 1) {
+        var msg = $("patronStrings").getFormattedString('staff.patron.bills.handle_refund.message_plural', [g.bill_list_selection]);
+    } else {
+        var msg = $("patronStrings").getFormattedString('staff.patron.bills.handle_refund.message_singular', [g.bill_list_selection]);
+    }
+        
+    var r = g.error.yns_alert(msg,
+        $("patronStrings").getString('staff.patron.bills.handle_refund.title'),
+        $("patronStrings").getString('staff.patron.bills.handle_refund.btn_yes'),
+        $("patronStrings").getString('staff.patron.bills.handle_refund.btn_no'),null,
+        $("patronStrings").getString('staff.patron.bills.handle_refund.confirm_message'));
+    if (r == 0) {
+        for (var i = 0; i < g.bill_list_selection.length; i++) {
+            var bill_id = g.bill_list_selection[i];
+            //alert('g.check_map['+bill_id+'] = '+g.check_map[bill_id]+' bill_map['+bill_id+'] = ' + js2JSON(g.bill_map[bill_id]));
+            g.check_map[bill_id] = true;
+            var row_params = g.row_map[bill_id];
+            row_params.row.my.checked = true;
+            g.bill_list.refresh_row(row_params);
+        }
+    }
+    tally_all();
+    distribute_payment();
+}
+
+
 function check_all() {
     try {
         for (var i in g.bill_map) {
@@ -438,6 +471,7 @@
             $('details').setAttribute('disabled', g.bill_list_selection.length == 0);
             $('add').setAttribute('disabled', g.bill_list_selection.length == 0);
             $('voidall').setAttribute('disabled', g.bill_list_selection.length == 0);
+            $('refund').setAttribute('disabled', g.bill_list_selection.length == 0);
             $('opac').setAttribute('disabled', g.bill_list_selection.length == 0);
             $('copy_details').setAttribute('disabled', g.bill_list_selection.length == 0);
         },
@@ -647,8 +681,10 @@
     try {
         var template = 'bills_historical'; if (xul_param('current')) template = 'bills_current';
         JSAN.use('patron.util');
+        g.patron = patron.util.retrieve_fleshed_au_via_id(ses(),g.patron_id,null); 
         var params = { 
-            'patron' : patron.util.retrieve_au_via_id(ses(),g.patron_id), 
+            'patron' : g.patron,
+            'printer_context' : 'receipt',
             'template' : template
         };
         g.bill_list.print(params);
@@ -782,7 +818,7 @@
                 };
                 g.error.sdump('D_DEBUG',js2JSON(params));
                 if (! $('printer_prompt').hasAttribute('checked')) params.no_prompt = true;
-                JSAN.use('util.print'); var print = new util.print();
+                JSAN.use('util.print'); var print = new util.print('receipt');
                 print.tree_list( params ); 
             } catch(E) {
                 g.error.standard_unexpected_error_alert('bill receipt', E);
@@ -898,7 +934,7 @@
 
 function refresh_patron() {
     JSAN.use('patron.util'); JSAN.use('util.money');
-    patron.util.retrieve_au_via_id(ses(),g.patron_id, function(req) {
+    patron.util.retrieve_fleshed_au_via_id(ses(),g.patron_id,null,function(req) {
         var au_obj = req.getResultObject();
         if (typeof au_obj.ilsevent == 'undefined') {
             g.patron = au_obj;

Modified: branches/serials-integration/Open-ILS/xul/staff_client/server/patron/bill2.xul
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/server/patron/bill2.xul	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/xul/staff_client/server/patron/bill2.xul	2010-10-18 13:46:56 UTC (rev 18371)
@@ -96,7 +96,7 @@
                                         <menuitem id="payment_type_menuitem1" label="&staff.patron.bills_overlay.cash.label;" value="cash_payment"/>
                                         <menuitem id="payment_type_menuitem2" label="&staff.patron.bills_overlay.check.label;" value="check_payment"/>
                                         <menuitem id="payment_type_menuitem3" label="&staff.patron.bills_overlay.credit_card.label;" value="credit_card_payment"/>
-                                        <menuitem id="payment_type_menuitem4" label="&staff.patron.bills_overlay.patron_credit.label;" value="credit_payment" />
+                                        <menuitem id="payment_type_menuitem4" class="hide_patron_credit" label="&staff.patron.bills_overlay.patron_credit.label;" value="credit_payment" />
                                         <menuitem id="payment_type_menuitem5" label="&staff.patron.bills_overlay.word.label;" value="work_payment"/>
                                         <menuitem id="payment_type_menuitem6" label="&staff.patron.bills_overlay.forgive.label;" value="forgive_payment"/>
                                         <menuitem id="payment_type_menuitem7" label="&staff.patron.bills_overlay.goods.label;" value="goods_payment"/>
@@ -169,7 +169,7 @@
                         <label value='&staff.patron.bill_interface.voided_this_session.label;' class="emphasis1"/><label id="currently_voided" value="0.00"/>
                     </hbox>
                     <hbox><label value='&staff.patron.bill_interface.change_due_upon_payment.label;' class="big_emphasis1"/><label id="change_due" value="0.00" class="big_emphasis1"/></hbox>
-                    <checkbox id="convert_change_to_credit" label="&staff.patron.bills_overlay.convert_change_to_credit.label;" accesskey="&staff.patron.bills_overlay.convert_change_to_credit.accesskey;"/>
+                    <checkbox id="convert_change_to_credit" class="hide_patron_credit" label="&staff.patron.bills_overlay.convert_change_to_credit.label;" accesskey="&staff.patron.bills_overlay.convert_change_to_credit.accesskey;"/>
                 </vbox>
                 <spacer flex="1"/>
                 <grid>

Modified: branches/serials-integration/Open-ILS/xul/staff_client/server/patron/bill_details.js
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/server/patron/bill_details.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/xul/staff_client/server/patron/bill_details.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -5,7 +5,7 @@
 
     if (g.patron_id) {
         JSAN.use('patron.util'); 
-        g.au_obj = patron.util.retrieve_fleshed_au_via_id( ses(), g.patron_id );
+        g.au_obj = patron.util.retrieve_fleshed_au_via_id( ses(), g.patron_id, null );
         
         $('patron_name').setAttribute('value', 
             patron.util.format_name( g.au_obj ) + ' : ' + g.au_obj.card().barcode() 

Modified: branches/serials-integration/Open-ILS/xul/staff_client/server/patron/bill_history.js
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/server/patron/bill_history.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/xul/staff_client/server/patron/bill_history.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -376,7 +376,7 @@
         var template = 'bills_historical'; if (xul_param('current')) template = 'bills_current';
         JSAN.use('patron.util');
         var params = { 
-            'patron' : patron.util.retrieve_au_via_id(ses(),g.patron_id), 
+            'patron' : patron.util.retrieve_fleshed_au_via_id(ses(),g.patron_id,null), 
             'template' : template
         };
         g.bill_list.print(params);

Modified: branches/serials-integration/Open-ILS/xul/staff_client/server/patron/bills.js
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/server/patron/bills.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/xul/staff_client/server/patron/bills.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -516,7 +516,7 @@
                         var template = 'bill_payment';
                         JSAN.use('patron.util'); JSAN.use('util.functional');
                         var params = { 
-                            'patron' : patron.util.retrieve_fleshed_au_via_id(ses(),obj.patron_id), 
+                            'patron' : patron.util.retrieve_fleshed_au_via_id(ses(),obj.patron_id,null), 
                             'lib' : obj.data.hash.aou[ obj.data.list.au[0].ws_ou() ],
                             'staff' : obj.data.list.au[0],
                             'header' : obj.data.print_list_templates[template].header,
@@ -540,7 +540,7 @@
                         };
                         obj.error.sdump('D_DEBUG',js2JSON(params));
                         if (document.getElementById('auto_print').checked) params.no_prompt = true;
-                        JSAN.use('util.print'); var print = new util.print();
+                        JSAN.use('util.print'); var print = new util.print('receipt');
                         print.tree_list( params );
                     } catch(E) {
                         obj.error.standard_unexpected_error_alert('bill receipt', E);
@@ -684,7 +684,7 @@
             var columns = patron.util.mbts_columns({});
             var template = 'bills_main_view';
             var params = { 
-                'patron' : patron.util.retrieve_fleshed_au_via_id(ses(),obj.patron_id), 
+                'patron' : patron.util.retrieve_fleshed_au_via_id(ses(),obj.patron_id,null), 
                 'lib' : obj.data.hash.aou[ obj.data.list.au[0].ws_ou() ],
                 'staff' : obj.data.list.au[0],
                 'header' : obj.data.print_list_templates[template].header,
@@ -707,7 +707,7 @@
                     }
                 )
             };
-            JSAN.use('util.print'); var print = new util.print();
+            JSAN.use('util.print'); var print = new util.print('receipt');
             print.tree_list( params );
 
         } catch(E) {

Modified: branches/serials-integration/Open-ILS/xul/staff_client/server/patron/display.js
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/server/patron/display.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/xul/staff_client/server/patron/display.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -390,7 +390,7 @@
                             xulG.new_tab(
                                 "/eg/booking/reservation",
                                 {
-                                    "tab_name": offlineStrings.getString(
+                                    "tab_name": $("offlineStrings").getString(
                                         "menu.cmd_booking_reservation.tab"
                                     ),
                                     "browser": false
@@ -411,7 +411,7 @@
                             xulG.new_tab(
                                 "/eg/booking/pickup",
                                 {
-                                    "tab_name": offlineStrings.getString(
+                                    "tab_name": $("offlineStrings").getString(
                                         "menu.cmd_booking_reservation_pickup.tab"
                                     ),
                                     "browser": false
@@ -432,7 +432,7 @@
                             xulG.new_tab(
                                 "/eg/booking/return",
                                 {
-                                    "tab_name": offlineStrings.getString(
+                                    "tab_name": $("offlineStrings").getString(
                                         "menu.cmd_booking_reservation_return.tab"
                                     ),
                                     "browser": false
@@ -932,11 +932,17 @@
                     }
                 }
                 var penalties = obj.patron.standing_penalties();
+                if (penalties.length > 0) { msg += '<dl>'; }
                 for (var i = 0; i < penalties.length; i++) {
                     if (penalties[i].standing_penalty().block_list() || penalties[i].standing_penalty().id() == 20 /* ALERT_NOTE */) {
+                        msg += '<dt>';
                         msg += obj.OpenILS.data.hash.aou[ penalties[i].org_unit() ].shortname() + ' : ' + penalties[i].standing_penalty().label() + '<br/>';
+                        msg += '</dt><dd>';
+                        msg += penalties[i].note();
+                        msg += '</dd>';
                     }
                 }
+                if (penalties.length > 0) { msg += '</dl>'; }
                 var holds = params.holds_summary;
                 if (holds.ready && holds.ready > 0) {
                     msg += $("patronStrings").getFormattedString('staff.patron.display.init.holds_ready', [holds.ready]);

Modified: branches/serials-integration/Open-ILS/xul/staff_client/server/patron/display_horiz_overlay.xul
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/server/patron/display_horiz_overlay.xul	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/xul/staff_client/server/patron/display_horiz_overlay.xul	2010-10-18 13:46:56 UTC (rev 18371)
@@ -94,7 +94,7 @@
                                     <menuitem label="&staff.patron.info.stat_cats.label;" accesskey="&staff.patron.info.stat_cats.accesskey;" command="cmd_patron_info_stats"/>
                                     <menu id="PatronNavBar_other_booking" label="&staff.main.menu.booking.label;" accesskey="&staff.main.menu.booking.accesskey;">
                                         <menupopup id="PatronNavBar_other_booking_popup">
-                                            <menuitem label="&staff.main.menu.booking.reservation.label;" accesskey="&staff.main.menu.booking.reservation.accesskey;" command="cmd_patron_reservation" />
+                                            <menuitem label="&staff.main.menu.booking.reservation.label_alt;" accesskey="&staff.main.menu.booking.reservation.accesskey;" command="cmd_patron_reservation" />
                                             <menuitem label="&staff.main.menu.booking.reservation_pickup.label;" accesskey="&staff.main.menu.booking.reservation_pickup.accesskey;" command="cmd_patron_reservation_pickup" />
                                             <menuitem label="&staff.main.menu.booking.reservation_return.label;" accesskey="&staff.main.menu.booking.reservation_return.accesskey;" command="cmd_patron_reservation_return" />
                                         </menupopup>

Modified: branches/serials-integration/Open-ILS/xul/staff_client/server/patron/display_overlay.xul
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/server/patron/display_overlay.xul	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/xul/staff_client/server/patron/display_overlay.xul	2010-10-18 13:46:56 UTC (rev 18371)
@@ -94,7 +94,7 @@
                                     <menuitem label="&staff.patron.info.stat_cats.label;" accesskey="&staff.patron.info.stat_cats.accesskey;" command="cmd_patron_info_stats"/>
                                     <menu id="PatronNavBar_other_booking" label="&staff.main.menu.booking.label;" accesskey="&staff.main.menu.booking.accesskey;">
                                         <menupopup id="PatronNavBar_other_booking_popup">
-                                            <menuitem label="&staff.main.menu.booking.reservation.label;" accesskey="&staff.main.menu.booking.reservation.accesskey;" command="cmd_patron_reservation" />
+                                            <menuitem label="&staff.main.menu.booking.reservation.label_alt;" accesskey="&staff.main.menu.booking.reservation.accesskey;" command="cmd_patron_reservation" />
                                             <menuitem label="&staff.main.menu.booking.reservation_pickup.label;" accesskey="&staff.main.menu.booking.reservation_pickup.accesskey;" command="cmd_patron_reservation_pickup" />
                                             <menuitem label="&staff.main.menu.booking.reservation_return.label;" accesskey="&staff.main.menu.booking.reservation_return.accesskey;" command="cmd_patron_reservation_return" />
                                         </menupopup>

Modified: branches/serials-integration/Open-ILS/xul/staff_client/server/patron/hold_details.js
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/server/patron/hold_details.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/xul/staff_client/server/patron/hold_details.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -26,7 +26,7 @@
     }
 }
 
-function fetch_and_render_all() {
+function fetch_and_render_all(do_not_refresh_parent_interface) {
     try {
         if (!xulG.ahr_id) { alert('boo'); return; }
 
@@ -56,6 +56,12 @@
 
         retrieve_notifications(); render_notifications();
 
+        if (!do_not_refresh_parent_interface) {
+            if (typeof xulG.clear_and_retrieve == 'function') {
+                xulG.clear_and_retrieve();
+            }
+        }
+
     } catch(E) {
         alert('Error in hold_details.js, fetch_and_render_all(): ' + E);
     }
@@ -64,14 +70,15 @@
 function fetch_hold(id) {
     try {
         g.ahr_id = xulG.ahr_id;
-        g.blob = xulG.blob;
-        if (g.blob) {
-            g.ahr = xulG.blob.hold;
+        if (xulG.blob) {
+            g.blob = xulG.blob;
+            delete xulG.blob; // one-time deal for speed
         } else {
             g.blob = g.network.simple_request('FM_AHR_BLOB_RETRIEVE',[ ses(), g.ahr_id ]);
             if (typeof g.ahr.ilsevent != 'undefined') { throw(g.ahr); }
-            g.ahr = g.blob.hold;
         }
+        g.ahr = g.blob.hold;
+        g.ahr.status( g.blob.status );
     } catch(E) {
         alert('Error in hold_details.js, fetch_hold(): ' + E);
     }
@@ -123,9 +130,18 @@
             'row' : {
                 'my' : {
                     'ahr' : g.ahr,
+                    'status' : g.blob.status,
                     'acp' : g.blob.copy,
                     'acn' : g.blob.volume,
                     'mvr' : g.blob.mvr,
+                    'patron_family_name' : g.blob.patron_last,
+                    'patron_first_given_name' : g.blob.patron_first,
+                    'patron_barcode' : g.blob.patron_barcode,
+                    'total_holds' : g.blob.total_holds,
+                    'queue_position' : g.blob.queue_position,
+                    'potential_copies' : g.blob.potential_copies,
+                    'estimated_wait' : g.blob.estimated_wait,
+                    'ahrn_count' : g.blob.hold.notes().length,
                     'blob' : g.blob
                 }
             },

Modified: branches/serials-integration/Open-ILS/xul/staff_client/server/patron/holds.js
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/server/patron/holds.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/xul/staff_client/server/patron/holds.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -15,8 +15,8 @@
     'hold_interface_type' : null,
 
     'pull_from_shelf_interface' : {
-        '_default' : { 'limit' : 50, 'offset' : 0 },
-        'current' : { 'limit' : 50, 'offset' : 0 }
+        '_default' : { 'limit' : 100, 'offset' : 0 },
+        'current' : { 'limit' : 100, 'offset' : 0 }
     },
 
     'filter_lib' : null,
@@ -232,7 +232,8 @@
                                     xulG.patron_rendered_elsewhere = (obj.hold_interface_type == 'patron');
                                     xulG.bib_rendered_elsewhere = (obj.hold_interface_type == 'record');
                                     f.xulG = xulG;
-                                    f.fetch_and_render_all();
+                                    f.xulG.clear_and_retrieve = function() { obj.clear_and_retrieve(); };
+                                    f.fetch_and_render_all(true);
                                 }
                             } catch(E) {
                                 alert('Error in holds.js, cmd_alt_view handler: ' + E);
@@ -289,7 +290,39 @@
                             );
                         }
                     ],
-
+                    'cmd_holds_print_full' : [
+                        ['command'],
+                        function() {
+                            var x_print_full_pull_list = document.getElementById('print_full_btn');
+                            try {
+                                if (progressmeter) {
+                                    progressmeter.mode = 'undetermined';
+                                    progressmeter.hidden = false;
+                                    x_print_full_pull_list.disabled = true;
+                                }
+                                JSAN.use('util.print');
+                                var print = new util.print('default');
+                                var robj = fieldmapper.standardRequest(
+                                    [ api.HTML_HOLD_PULL_LIST.app, api.HTML_HOLD_PULL_LIST.method ],
+                                    {   async: false,
+                                        timeout: 180,
+                                        params: [ses()],
+                                    }
+                                );
+                                if (robj != null) {
+                                    if (typeof robj.ilsevent != 'undefined') { throw(robj); }
+                                    print.simple( robj.template_output().data() );
+                                }
+                            } catch(E) {
+                                obj.error.standard_unexpected_error_alert('cmd_holds_print_full',E);
+                            }
+                            if (progressmeter) {
+                                progressmeter.mode = 'determined';
+                                progressmeter.hidden = true;
+                                x_print_full_pull_list.disabled = false;
+                            }
+                        }
+                    ],
                     'cmd_holds_print' : [
                         ['command'],
                         function() {
@@ -1259,6 +1292,7 @@
         var x_show_cancelled_deck = document.getElementById('show_cancelled_deck');
         var x_clear_shelf_widgets = document.getElementById('clear_shelf_widgets');
         var x_expired_checkbox = document.getElementById('expired_checkbox');
+        var x_print_full_pull_list = document.getElementById('print_full_btn');
         switch(obj.hold_interface_type) {
             case 'shelf':
                 obj.render_lib_menus({'pickup_lib':true});
@@ -1269,6 +1303,7 @@
             break;
             case 'pull' :
                 if (x_fetch_more) x_fetch_more.hidden = false;
+                if (x_print_full_pull_list) x_print_full_pull_list.hidden = false;
                 if (x_lib_type_menu) x_lib_type_menu.hidden = true;
                 if (x_lib_menu_placeholder) x_lib_menu_placeholder.hidden = true;
             break;

Modified: branches/serials-integration/Open-ILS/xul/staff_client/server/patron/holds_overlay.xul
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/server/patron/holds_overlay.xul	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/xul/staff_client/server/patron/holds_overlay.xul	2010-10-18 13:46:56 UTC (rev 18371)
@@ -18,6 +18,7 @@
         <command id="cmd_csv_to_printer" />
         <command id="cmd_csv_to_file" />
         <command id="cmd_holds_print" />
+        <command id="cmd_holds_print_full" />
         <command id="cmd_show_catalog" />
         <command id="cmd_retrieve_patron" />
         <command id="cmd_holds_edit_desire_mint_condition" />
@@ -186,6 +187,7 @@
         </button>
 
         <button id="holds_print" label="&staff.patron.holds_overlay.print.label;" command="cmd_holds_print" accesskey="&staff.patron.holds_overlay.print.accesskey;" />
+        <button id="print_full_btn" hidden="true" label="&staff.patron.holds_overlay.print_full_pull_list.label;" command="cmd_holds_print_full" accesskey="&staff.patron.holds_overlay.print_full_pull_list.accesskey;" />
         <spacer flex="1"/>
     </hbox>
 

Modified: branches/serials-integration/Open-ILS/xul/staff_client/server/patron/info_group.js
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/server/patron/info_group.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/xul/staff_client/server/patron/info_group.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -116,7 +116,7 @@
                         return row;
                     }
 
-                    patron.util.retrieve_fleshed_au_via_id( ses(), id, function(req) {
+                    patron.util.retrieve_fleshed_au_via_id( ses(), id, null, function(req) {
                         row.my.au = req.getResultObject();
                         process_and_return();
                     });
@@ -428,7 +428,7 @@
         if (g.sel_list.length == 0) g.sel_list[0] = g.patron_id;
         for (var i = 0; i < g.sel_list.length; i++) {    
 
-            var patron_a = patron.util.retrieve_fleshed_au_via_id(ses(),g.sel_list[i]);
+            var patron_a = patron.util.retrieve_fleshed_au_via_id(ses(),g.sel_list[i],null);
             if (typeof patron_a.ilsevent != 'undefined') throw(patron_a);
             switch(direction) {
                 case true:

Modified: branches/serials-integration/Open-ILS/xul/staff_client/server/patron/items.js
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/server/patron/items.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/xul/staff_client/server/patron/items.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -132,7 +132,12 @@
                     'sel_copy_details2' : [ ['command'],
                         function() {
                             JSAN.use('circ.util');
-                            for (var i = 0; i < obj.retrieve_ids2.length; i++) { circ.util.show_copy_details( obj.retrieve_ids2[i].copy_id ); }
+                            circ.util.item_details_new(
+                                util.functional.map_list(
+                                    obj.retrieve_ids2,
+                                    function(o) { return o.barcode; }
+                                )
+                            );
                         }
                     ],
                     'cmd_items_print' : [ ['command'], function() { obj.items_print(1); } ],
@@ -251,6 +256,7 @@
             JSAN.use('patron.util');
             var params = { 
                 'patron' : patron.util.retrieve_fleshed_au_via_id(ses(),obj.patron_id), 
+                'printer_context' : 'receipt', 
                 'template' : 'items_out'
             };
             list.print( params );

Modified: branches/serials-integration/Open-ILS/xul/staff_client/server/patron/search_result.js
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/server/patron/search_result.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/xul/staff_client/server/patron/search_result.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -29,33 +29,57 @@
         JSAN.use('util.list'); obj.list = new util.list('patron_list');
 
         JSAN.use('patron.util');
-        var columns = patron.util.columns(
-            {
-                /* 'active' : { 'hidden' : 'false' }, */
-                'barred' : { 'hidden' : 'false' },
-                'family_name' : { 'hidden' : 'false' },
-                'first_given_name' : { 'hidden' : 'false' },
-                'second_given_name' : { 'hidden' : 'false' },
-                'dob' : { 'hidden' : obscure_dob }
-            },
-            {
-                'except_these' : [
-                    'au_barcode',
-                ]
-            }
+        var columns = obj.list.fm_columns('au',{
+            '*' : { 'remove_virtual' : true, 'expanded_label' : false, 'hidden' : true },
+            'au_barcode' : { 'hidden' : false },
+            'au_barred' : { 'hidden' : false },
+            'au_family_name' : { 'hidden' : false },
+            'au_first_given_name' : { 'hidden' : false },
+            'au_second_given_name' : { 'hidden' : false },
+            'au_dob' : { 'hidden' : false }
+        }).concat(
+            obj.list.fm_columns('ac',{
+                '*' : { 'remove_virtual' : true, 'expanded_label' : true, 'hidden' : true },
+                'ac_barcode' : { 'hidden' : false }
+            })
+        ).concat(
+            obj.list.fm_columns('aua',{
+                '*' : {
+                    'dataobj' : 'billing_aua',
+                    'remove_virtual' : true,
+                    'label_prefix' : $('patronStrings').getString('staff.patron.search_result.billing_address_column_label_prefix'),
+                    'hidden' : true
+                }
+            },'billing_')
+        ).concat(
+            obj.list.fm_columns('aua',{
+                '*' : {
+                    'dataobj' : 'mailing_aua',
+                    'remove_virtual' : true,
+                    'label_prefix' : $('patronStrings').getString('staff.patron.search_result.mailing_address_column_label_prefix'),
+                    'hidden' : true
+                }
+            },'mailing_')
         );
+
         obj.list.init(
             {
                 'columns' : columns,
                 'map_row_to_columns' : patron.util.std_map_row_to_columns(),
                 'retrieve_row' : function(params) {
                     var id = params.retrieve_id;
-                    var au_obj = patron.util.retrieve_au_via_id( ses(), id,
+                    var au_obj = patron.util.retrieve_fleshed_au_via_id(
+                        ses(),
+                        id,
+                        ["card","billing_address","mailing_address"],
                         function(req) {
                             try {
                                 var row = params.row;
                                 if (typeof row.my == 'undefined') row.my = {};
                                 row.my.au = req.getResultObject();
+                                row.my.ac = row.my.au.card();
+                                row.my.billing_aua = row.my.au.billing_address();
+                                row.my.mailing_aua = row.my.au.mailing_address();
                                 if (typeof params.on_retrieve == 'function') {
                                     params.on_retrieve(row);
                                 } else {

Modified: branches/serials-integration/Open-ILS/xul/staff_client/server/patron/standing_penalties.js
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/server/patron/standing_penalties.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/xul/staff_client/server/patron/standing_penalties.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -292,7 +292,7 @@
                     penalty.ischanged( 1 );
                     dojo.require('openils.PermaCrud');
                     var pcrud = new openils.PermaCrud( { authtoken :ses() });
-                    pcrud.apply( penalty, {
+                    pcrud.update( penalty, {
                         timeout : 10, // makes it synchronous
                         onerror : function(r) {
                             try {
@@ -303,19 +303,21 @@
                                 alert(E);
                             }
                         },
-                        oncomplete : function(r) {
-                            try {
-                                var res = openils.Util.readResponse(r,true);
-                                /* FIXME - test for success */
-                                var row_params = rows[ ids[i] ];
-                                row_params.row.my.ausp = penalty;
-                                row_params.row.my.csp = penalty.standing_penalty();
-                                list.refresh_row( row_params );
-                                document.getElementById('progress').hidden = true;
-                            } catch(E) {
-                                alert(E);
+                        oncomplete : function gen_func(p,row_id) {
+                            return function(r) {
+                                try {
+                                    var res = openils.Util.readResponse(r,true);
+                                    /* FIXME - test for success */
+                                    var row_params = rows[row_id];
+                                    row_params.row.my.ausp = p;
+                                    row_params.row.my.csp = p.standing_penalty();
+                                    list.refresh_row( row_params );
+                                    document.getElementById('progress').hidden = true;
+                                } catch(E) {
+                                    alert(E);
+                                }
                             }
-                        }
+                        }(penalty,ids[i])
                     });
                 }
             } 
@@ -346,7 +348,7 @@
                 penalty.stop_date( util.date.formatted_date(new Date(),'%F') );
                 dojo.require('openils.PermaCrud');
                 var pcrud = new openils.PermaCrud( { authtoken :ses() });
-                pcrud.apply( penalty, {
+                pcrud.update( penalty, {
                     onerror : function(r) {
                         try {
                             var res = openils.Util.readResponse(r,true);
@@ -358,21 +360,23 @@
                             document.getElementById('progress').hidden = true;
                         }
                     },
-                    oncomplete : function(r) {
-                        try {
-                            var res = openils.Util.readResponse(r,true);
-                            /* FIXME - test for success */
-                            var node = rows[ ids[i] ].my_node;
-                            var parentNode = node.parentNode;
-                            parentNode.removeChild( node );
-                            delete(rows[ ids[i] ]);
-                        } catch(E) {
-                            alert(E);
+                    oncomplete : function gen_func(row_id) {
+                        return function(r) {
+                            try {
+                                var res = openils.Util.readResponse(r,true);
+                                /* FIXME - test for success */
+                                var node = rows[row_id].my_node;
+                                var parentNode = node.parentNode;
+                                parentNode.removeChild( node );
+                                delete(rows[row_id]);
+                            } catch(E) {
+                                alert(E);
+                            }
+                            if (--outstanding_requests==0) {
+                                document.getElementById('progress').hidden = true;
+                            }
                         }
-                        if (--outstanding_requests==0) {
-                            document.getElementById('progress').hidden = true;
-                        }
-                    }
+                    }(ids[i])
                 });
             } 
             /*

Modified: branches/serials-integration/Open-ILS/xul/staff_client/server/patron/summary.js
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/server/patron/summary.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/xul/staff_client/server/patron/summary.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -2,6 +2,7 @@
 
 function $(id) { return document.getElementById(id); }
 var patronStrings = $('patronStrings');
+var offlineStrings = $('offlineStrings');
 
 if (typeof patron == 'undefined') patron = {};
 patron.summary = function (params) {
@@ -125,31 +126,44 @@
                         ['command'],
                         function() {
                             try {
+                                var rows = $('patron_info_rows');
                                 obj.stat_cat_list.clear();
                                 var entries = obj.patron.stat_cat_entries();
                                 for (var i = 0; i < entries.length; i++) {
                                     var stat_cat = obj.OpenILS.data.hash.my_actsc[ entries[i].stat_cat() ];
                                     if (!stat_cat) {
-                                        stat_cat = obj.OpenILS.data.hash.actsc[ entries[i].stat_cat() ];
+                                        stat_cat = obj.OpenILS.data.lookup('actsc',entries[i].stat_cat());
                                     }
-                                    if (!stat_cat) {
-                                        var robj = obj.network.simple_request('FM_ACTSC_RETRIEVE_VIA_PCRUD',[ ses(), { 'id' : { '=' : entries[i].stat_cat() } }]);
-                                        if (typeof robj == 'object' && typeof robj.ilsevent != 'undefined') {
-                                            obj.OpenILS.data.hash.actsc[ entries[i].stat_cat() ] = robj;
-                                            obj.OpenILS.data.stash( 'hash' );
-                                            stat_cat = robj;
-                                        }
-                                    }
                                     if (!stat_cat) { continue; }
-                                    if (get_bool( stat_cat.usr_summary() )) {
-                                        obj.stat_cat_list.append( {
-                                            'row' : {
-                                                'my' : {
-                                                    'actsc' : stat_cat,
-                                                    'actscecm' : entries[i],
-                                                }
+                                    // Every stat cat gets rendered in the Stat Cats tab
+                                    obj.stat_cat_list.append( {
+                                        'row' : {
+                                            'my' : {
+                                                'actsc' : stat_cat,
+                                                'actscecm' : entries[i],
                                             }
-                                        } );
+                                        }
+                                    } );
+                                    // But only a proud few share the Patron Info pane
+                                    if (rows && get_bool( stat_cat.usr_summary() )) {
+                                        var row_id = 'stat_cat_id_' + stat_cat.id();
+                                        var row; var label1; var label2;
+                                        if ($(row_id)) {
+                                            row = $(row_id);
+                                            label1 = row.firstChild;
+                                            label2 = row.lastChild;
+                                        } else {
+                                            row = document.createElement('row');
+                                            row.setAttribute('id',row_id);
+                                            label1 = document.createElement('label');
+                                            label2 = document.createElement('label');
+                                            row.appendChild(label1);
+                                            row.appendChild(label2);
+                                            rows.appendChild(row);
+                                        }
+                                        label1.setAttribute('value',stat_cat.name());
+                                        label1.setAttribute('tooltiptext','stat cat id ' + stat_cat.id());
+                                        label2.setAttribute('value',entries[i].stat_cat_entry());
                                     }
                                 }
                             } catch(E) {
@@ -368,13 +382,24 @@
                                     function(req) {
                                         try {
                                             var robj = req.getResultObject();
-                                            util.widgets.set_text(e, robj.out + robj.overdue + robj.claims_returned + robj.long_overdue );
+                                            var do_not_tally_claims_returned = String( obj.OpenILS.data.hash.aous['circ.do_not_tally_claims_returned'] ) == 'true';
+                                            util.widgets.set_text(e,
+                                                robj.out
+                                                + robj.overdue
+                                                + (do_not_tally_claims_returned ? 0 : robj.claims_returned)
+                                                + robj.long_overdue
+                                            );
                                             if (e2) util.widgets.set_text(e2, robj.overdue    );
                                             if (e3) util.widgets.set_text(e3, robj.claims_returned    );
                                             if (e4) util.widgets.set_text(e4, robj.long_overdue    );
                                             if (e5) util.widgets.set_text(e5, robj.lost    );
                                             if (under_btn) util.widgets.set_text(under_btn, 
-                                                String( robj.out + robj.overdue + robj.claims_returned + robj.long_overdue) 
+                                                String(
+                                                    robj.out
+                                                    + robj.overdue
+                                                    + (do_not_tally_claims_returned ? 0 : robj.claims_returned)
+                                                    + robj.long_overdue
+                                                ) 
                                                 /* + ( robj.overdue > 0 ? '*' : '' ) */
                                             );
                                         } catch(E) {
@@ -671,10 +696,14 @@
                         ['render'],
                         function(e) {
                             return function() { 
-                                util.widgets.set_text(e,
-                                    obj.patron.mailing_address().street1()
-                                );
-                                if (!get_bool(obj.patron.mailing_address().valid())){e.setAttribute('style','color: red');}
+                                if (obj.patron.mailing_address()) {
+                                    util.widgets.set_text(e,
+                                        obj.patron.mailing_address().street1()
+                                    );
+                                    if (!get_bool(obj.patron.mailing_address().valid())){e.setAttribute('style','color: red');}
+                                } else {
+                                    util.widgets.set_text(e,'');
+                                }
                             };
                         }
                     ],
@@ -682,10 +711,14 @@
                         ['render'],
                         function(e) {
                             return function() { 
-                                util.widgets.set_text(e,
-                                    obj.patron.mailing_address().street2()
-                                );
-                                if (!get_bool(obj.patron.mailing_address().valid())){e.setAttribute('style','color: red');}
+                                if (obj.patron.mailing_address()) {
+                                    util.widgets.set_text(e,
+                                        obj.patron.mailing_address().street2()
+                                    );
+                                    if (!get_bool(obj.patron.mailing_address().valid())){e.setAttribute('style','color: red');}
+                                } else {
+                                    util.widgets.set_text(e,'');
+                                }
                             };
                         }
                     ],
@@ -693,10 +726,14 @@
                         ['render'],
                         function(e) {
                             return function() { 
-                                util.widgets.set_text(e,
-                                    obj.patron.mailing_address().city()
-                                );
-                                if (!get_bool(obj.patron.mailing_address().valid())){e.setAttribute('style','color: red');}
+                                if (obj.patron.mailing_address()) {
+                                    util.widgets.set_text(e,
+                                        obj.patron.mailing_address().city()
+                                    );
+                                    if (!get_bool(obj.patron.mailing_address().valid())){e.setAttribute('style','color: red');}
+                                } else {
+                                    util.widgets.set_text(e,'');
+                                }
                             };
                         }
                     ],
@@ -704,10 +741,14 @@
                         ['render'],
                         function(e) {
                             return function() { 
-                                util.widgets.set_text(e,
-                                    obj.patron.mailing_address().state()
-                                );
-                                if (!get_bool(obj.patron.mailing_address().valid())){e.setAttribute('style','color: red');}
+                                if (obj.patron.mailing_address()) {
+                                    util.widgets.set_text(e,
+                                        obj.patron.mailing_address().state()
+                                    );
+                                    if (!get_bool(obj.patron.mailing_address().valid())){e.setAttribute('style','color: red');}
+                                } else {
+                                    util.widgets.set_text(e,'');
+                                }
                             };
                         }
                     ],
@@ -715,10 +756,14 @@
                         ['render'],
                         function(e) {
                             return function() { 
-                                util.widgets.set_text(e,
-                                    obj.patron.mailing_address().post_code()
-                                );
-                                if (!get_bool(obj.patron.mailing_address().valid())){e.setAttribute('style','color: red');}
+                                if (obj.patron.mailing_address()) {
+                                    util.widgets.set_text(e,
+                                        obj.patron.mailing_address().post_code()
+                                    );
+                                    if (!get_bool(obj.patron.mailing_address().valid())){e.setAttribute('style','color: red');}
+                                } else {
+                                    util.widgets.set_text(e,'');
+                                }
                             };
                         }
                     ],
@@ -726,54 +771,74 @@
                         ['render'],
                         function(e) {
                             return function() { 
-                                util.widgets.set_text(e,
-                                    obj.patron.billing_address().street1()
-                                );
-                                if (!get_bool(obj.patron.billing_address().valid())){e.setAttribute('style','color: red');}
+                                if (obj.patron.billing_address()) {
+                                    util.widgets.set_text(e,
+                                        obj.patron.billing_address().street1()
+                                    );
+                                    if (!get_bool(obj.patron.billing_address().valid())){e.setAttribute('style','color: red');}
+                                } else {
+                                    util.widgets.set_text(e,'');
+                                }
                             };
                         }
                     ],
                     'patron_physical_address_street2' : [
                         ['render'],
                         function(e) {
-                            return function() { 
-                                util.widgets.set_text(e,
-                                    obj.patron.billing_address().street2()
-                                );
-                                if (!get_bool(obj.patron.billing_address().valid())){e.setAttribute('style','color: red');}
+                            return function() {
+                                if (obj.patron.billing_address()) { 
+                                    util.widgets.set_text(e,
+                                        obj.patron.billing_address().street2()
+                                    );
+                                    if (!get_bool(obj.patron.billing_address().valid())){e.setAttribute('style','color: red');}
+                                } else {
+                                    util.widgets.set_text(e,'');
+                                }
                             };
                         }
                     ],
                     'patron_physical_address_city' : [
                         ['render'],
                         function(e) {
-                            return function() { 
-                                util.widgets.set_text(e,
-                                    obj.patron.billing_address().city()
-                                );
-                                if (!get_bool(obj.patron.billing_address().valid())){e.setAttribute('style','color: red');}
+                            return function() {
+                                if (obj.patron.billing_address()) { 
+                                    util.widgets.set_text(e,
+                                        obj.patron.billing_address().city()
+                                    );
+                                    if (!get_bool(obj.patron.billing_address().valid())){e.setAttribute('style','color: red');}
+                                } else {
+                                    util.widgets.set_text(e,'');
+                                }
                             };
                         }
                     ],
                     'patron_physical_address_state' : [
                         ['render'],
                         function(e) {
-                            return function() { 
-                                util.widgets.set_text(e,
-                                    obj.patron.billing_address().state()
-                                );
-                                if (!get_bool(obj.patron.billing_address().valid())){e.setAttribute('style','color: red');}
+                            return function() {
+                                if (obj.patron.billing_address()) { 
+                                    util.widgets.set_text(e,
+                                        obj.patron.billing_address().state()
+                                    );
+                                    if (!get_bool(obj.patron.billing_address().valid())){e.setAttribute('style','color: red');}
+                                } else {
+                                    util.widgets.set_text(e,'');
+                                }
                             };
                         }
                     ],
                     'patron_physical_address_post_code' : [
                         ['render'],
                         function(e) {
-                            return function() { 
-                                util.widgets.set_text(e,
-                                    obj.patron.billing_address().post_code()
-                                );
-                                if (!get_bool(obj.patron.billing_address().valid())){e.setAttribute('style','color: red');}
+                            return function() {
+                                if (obj.patron.billing_address()) { 
+                                    util.widgets.set_text(e,
+                                        obj.patron.billing_address().post_code()
+                                    );
+                                    if (!get_bool(obj.patron.billing_address().valid())){e.setAttribute('style','color: red');}
+                                } else {
+                                    util.widgets.set_text(e,'');
+                                }
                             };
                         }
                     ]
@@ -899,7 +964,12 @@
             */
 
             // Update the screen
-            chain.push( function() { obj.controller.render(); } );
+            chain.push( function() {
+                obj.controller.render();
+                if ($('stat_cat_tab')) {
+                    util.widgets.dispatch('command','stat_cat_tab'); 
+                }
+            } );
 
             // On Complete
 

Modified: branches/serials-integration/Open-ILS/xul/staff_client/server/patron/summary.xul
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/server/patron/summary.xul	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/xul/staff_client/server/patron/summary.xul	2010-10-18 13:46:56 UTC (rev 18371)
@@ -110,7 +110,7 @@
                 case 'addr_export_print':
                     // Replace literal instances of '\n' and excessive whitespace.
                     s = s.replace(/(\\n)+/g, "<br/>").replace(/ {2,}/g, " ");
-                    JSAN.use('util.print'); var print = new util.print(); print.simple(s);
+                    JSAN.use('util.print'); var print = new util.print('mail'); print.simple(s);
                 break;
             };
         }
@@ -141,6 +141,7 @@
     </script>
     
     <messagecatalog id="patronStrings" src="/xul/server/locale/<!--#echo var='locale'-->/patron.properties"/>
+    <messagecatalog id="offlineStrings" src="/xul/server/locale/<!--#echo var='locale'-->/offline.properties"/>
 
     <commandset id="patron_summary_cmds" />
     <popupset id="patron_summary_popups" />

Modified: branches/serials-integration/Open-ILS/xul/staff_client/server/patron/summary_overlay_horiz.xul
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/server/patron/summary_overlay_horiz.xul	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/xul/staff_client/server/patron/summary_overlay_horiz.xul	2010-10-18 13:46:56 UTC (rev 18371)
@@ -100,7 +100,7 @@
                 <column/>
                 <column/>
             </columns>
-            <rows>
+            <rows id="patron_info_rows">
                 <row>
                     <label id="PatronSummaryContact_date_of_birth_label" click_to_hide_dob="true" class="copyable text_left dob label click_link" value="&staff.patron_display.date_of_birth.label;"/>
                     <description id="patron_date_of_birth" class="copyable dob value" hide_value="true" oils_persist="hide_value"/>

Modified: branches/serials-integration/Open-ILS/xul/staff_client/server/patron/ue.js
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/server/patron/ue.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/xul/staff_client/server/patron/ue.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -638,7 +638,7 @@
             var href = location.href;
             href = href.replace(/\&?usr=\d+/, '');
             href = href.replace(/\&?clone=\d+/, '');
-            href += '&clone=' + cloneme;
+            href += (href.match(/\?/) ? "&" : "?") + 'clone=' + cloneme;
             location.href = href;
         }
 

Modified: branches/serials-integration/Open-ILS/xul/staff_client/server/patron/util.js
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/server/patron/util.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/xul/staff_client/server/patron/util.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -227,7 +227,7 @@
         },
         {
             'persist' : 'hidden width ordinal', 'id' : 'mp_staff', 'label' : commonStrings.getString('staff.mp_accepting_usr_label'), 'flex' : 1,
-            'primary' : false, 'hidden' : false, 'editable' : false, 'render' : function(my) { var s = my.mp.accepting_usr(); if (s && typeof s != "object") s = patron.util.retrieve_fleshed_au_via_id(ses(),s); return s.family_name() + " (" + s.card().barcode() + ") @ " + data.hash.aou[ s.home_ou() ].shortname(); }
+            'primary' : false, 'hidden' : false, 'editable' : false, 'render' : function(my) { var s = my.mp.accepting_usr(); if (s && typeof s != "object") s = patron.util.retrieve_fleshed_au_via_id(ses(),s,["card"]); return s.family_name() + " (" + s.card().barcode() + ") @ " + data.hash.aou[ s.home_ou() ].shortname(); }
         },
         {
             'persist' : 'hidden width ordinal', 'id' : 'mp_xact', 'label' : commonStrings.getString('staff.mp_xact_label'), 'flex' : 1,
@@ -590,16 +590,16 @@
     return parts;
 }
 
-patron.util.retrieve_fleshed_au_via_id = function(session, id, f) {
+patron.util.retrieve_fleshed_au_via_id = function(session, id, fields, func) {
     JSAN.use('util.network');
     var network = new util.network();
     var patron_obj = network.simple_request(
         'FM_AU_FLESHED_RETRIEVE_VIA_ID.authoritative',
-        [ session, id ],
-        typeof f == 'function' ? f : null
+        [ session, id, fields ],
+        typeof func == 'function' ? func : null
     );
-    if (typeof f != 'function') {
-        patron.util.set_penalty_css(patron_obj);
+    if (typeof func != 'function') {
+        if (!fields) { patron.util.set_penalty_css(patron_obj); }
         return patron_obj;
     }
 }
@@ -619,38 +619,39 @@
 
 patron.util.set_penalty_css = function(patron) {
     try {
-                            removeCSSClass(document.documentElement,'PATRON_HAS_BILLS');
-                            removeCSSClass(document.documentElement,'PATRON_HAS_OVERDUES');
-                            removeCSSClass(document.documentElement,'PATRON_HAS_NOTES');
-                            removeCSSClass(document.documentElement,'PATRON_EXCEEDS_CHECKOUT_COUNT');
-                            removeCSSClass(document.documentElement,'PATRON_EXCEEDS_OVERDUE_COUNT');
-                            removeCSSClass(document.documentElement,'PATRON_EXCEEDS_FINES');
-                            removeCSSClass(document.documentElement,'NO_PENALTIES');
-                            removeCSSClass(document.documentElement,'ONE_PENALTY');
-                            removeCSSClass(document.documentElement,'MULTIPLE_PENALTIES');
-                            removeCSSClass(document.documentElement,'PATRON_HAS_ALERT');
-                            removeCSSClass(document.documentElement,'PATRON_BARRED');
-                            removeCSSClass(document.documentElement,'PATRON_INACTIVE');
-                            removeCSSClass(document.documentElement,'PATRON_EXPIRED');
-                            removeCSSClass(document.documentElement,'PATRON_HAS_INVALID_DOB');
-                            removeCSSClass(document.documentElement,'PATRON_HAS_INVALID_ADDRESS');
-                            removeCSSClass(document.documentElement,'PATRON_AGE_GE_65');
-                            removeCSSClass(document.documentElement,'PATRON_AGE_LT_65');
-                            removeCSSClass(document.documentElement,'PATRON_AGE_GE_24');
-                            removeCSSClass(document.documentElement,'PATRON_AGE_LT_24');
-                            removeCSSClass(document.documentElement,'PATRON_AGE_GE_21');
-                            removeCSSClass(document.documentElement,'PATRON_AGE_LT_21');
-                            removeCSSClass(document.documentElement,'PATRON_AGE_GE_18');
-                            removeCSSClass(document.documentElement,'PATRON_AGE_LT_18');
-                            removeCSSClass(document.documentElement,'PATRON_AGE_GE_13');
-                            removeCSSClass(document.documentElement,'PATRON_AGE_LT_13');
-                            removeCSSClass(document.documentElement,'PATRON_NET_ACCESS_1');
-                            removeCSSClass(document.documentElement,'PATRON_NET_ACCESS_2');
-                            removeCSSClass(document.documentElement,'PATRON_NET_ACCESS_3');
+        removeCSSClass(document.documentElement,'PATRON_HAS_BILLS');
+        removeCSSClass(document.documentElement,'PATRON_HAS_OVERDUES');
+        removeCSSClass(document.documentElement,'PATRON_HAS_NOTES');
+        removeCSSClass(document.documentElement,'PATRON_EXCEEDS_CHECKOUT_COUNT');
+        removeCSSClass(document.documentElement,'PATRON_EXCEEDS_OVERDUE_COUNT');
+        removeCSSClass(document.documentElement,'PATRON_EXCEEDS_FINES');
+        removeCSSClass(document.documentElement,'NO_PENALTIES');
+        removeCSSClass(document.documentElement,'ONE_PENALTY');
+        removeCSSClass(document.documentElement,'MULTIPLE_PENALTIES');
+        removeCSSClass(document.documentElement,'PATRON_HAS_ALERT');
+        removeCSSClass(document.documentElement,'PATRON_BARRED');
+        removeCSSClass(document.documentElement,'PATRON_INACTIVE');
+        removeCSSClass(document.documentElement,'PATRON_EXPIRED');
+        removeCSSClass(document.documentElement,'PATRON_HAS_INVALID_DOB');
+        removeCSSClass(document.documentElement,'PATRON_HAS_INVALID_ADDRESS');
+        removeCSSClass(document.documentElement,'PATRON_AGE_GE_65');
+        removeCSSClass(document.documentElement,'PATRON_AGE_LT_65');
+        removeCSSClass(document.documentElement,'PATRON_AGE_GE_24');
+        removeCSSClass(document.documentElement,'PATRON_AGE_LT_24');
+        removeCSSClass(document.documentElement,'PATRON_AGE_GE_21');
+        removeCSSClass(document.documentElement,'PATRON_AGE_LT_21');
+        removeCSSClass(document.documentElement,'PATRON_AGE_GE_18');
+        removeCSSClass(document.documentElement,'PATRON_AGE_LT_18');
+        removeCSSClass(document.documentElement,'PATRON_AGE_GE_13');
+        removeCSSClass(document.documentElement,'PATRON_AGE_LT_13');
+        removeCSSClass(document.documentElement,'PATRON_NET_ACCESS_1');
+        removeCSSClass(document.documentElement,'PATRON_NET_ACCESS_2');
+        removeCSSClass(document.documentElement,'PATRON_NET_ACCESS_3');
 
         JSAN.use('util.network'); var net = new util.network();
         net.simple_request('FM_MOUS_RETRIEVE.authoritative',[ ses(), patron.id() ], function(req) {
-            if (req.getResultObject().balance_owed() > 0) addCSSClass(document.documentElement,'PATRON_HAS_BILLS');
+            var summary = req.getResultObject();
+            if (summary && summary.balance_owed() > 0) addCSSClass(document.documentElement,'PATRON_HAS_BILLS');
         });
         net.simple_request('FM_CIRC_COUNT_RETRIEVE_VIA_USER.authoritative',[ ses(), patron.id() ], function(req) {
             try {
@@ -671,6 +672,7 @@
         */
 
         var penalties = patron.standing_penalties();
+        if (!penalties) { penalties = []; }
         for (var i = 0; i < penalties.length; i++) {
             /* this comes from /opac/common/js/utils.js */
             addCSSClass(document.documentElement,penalties[i].standing_penalty().name());
@@ -742,12 +744,12 @@
         if ( get_bool( patron.juvenile() ) ) addCSSClass(document.documentElement,'PATRON_JUVENILE');
         else removeCSSClass(document.documentElement,'PATRON_JUVENILE');
 
-        if (patron.mailing_address()) {
+        if (patron.mailing_address() && typeof patron.mailing_address() == 'object') {
             if (!get_bool(patron.mailing_address().valid())) {
                 addCSSClass(document.documentElement,'PATRON_HAS_INVALID_ADDRESS');
             }
         }
-        if (patron.billing_address()) {
+        if (patron.billing_address() && typeof patron.billing_address() == 'object') {
             if (!get_bool(patron.billing_address().valid())) {
                 addCSSClass(document.documentElement,'PATRON_HAS_INVALID_ADDRESS');
             }

Copied: branches/serials-integration/Open-ILS/xul/staff_client/server/serial/batch_receive.js (from rev 17886, trunk/Open-ILS/xul/staff_client/server/serial/batch_receive.js)
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/server/serial/batch_receive.js	                        (rev 0)
+++ branches/serials-integration/Open-ILS/xul/staff_client/server/serial/batch_receive.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -0,0 +1,974 @@
+/* The code in this file relies on common.js */
+
+dojo.require("dojo.cookie");
+dojo.require("openils.Util");
+dojo.require("openils.User");
+dojo.require("openils.CGI");
+dojo.require("openils.PermaCrud");
+
+var batch_receiver;
+
+function S(k) {
+    return dojo.byId("serialStrings").getString("batch_receive." + k).
+        replace("\\n", "\n");
+}
+
+function F(k, args) {
+    return dojo.byId("serialStrings").
+        getFormattedString("batch_receive." + k, args).replace("\\n", "\n");
+}
+
+function BatchReceiver() {
+    var self = this;
+
+    this.init = function(authtoken, bib_id, sub_id) {
+        if (authtoken) {
+            this.user = new openils.User({"authtoken": authtoken});
+            this.pcrud = new openils.PermaCrud({"authtoken": authtoken});
+            this.authtoken = authtoken;
+        }
+
+        hide("batch_receive_sub");
+        hide("batch_receive_entry");
+        hide("batch_receive_bibdata_bits");
+        hide("batch_receive_sub_bits");
+        hide("batch_receive_issuance_bits");
+        hide("batch_receive_issuance");
+
+        dojo.byId("bib_lookup_submit").disabled = false;
+        dojo.byId("bib_search_term").value = "";
+
+        if (!bib_id) {
+            show("batch_receive_bib");
+            dojo.byId("bib_search_term").focus();
+        }
+
+        if (!this.entry_tbody) {
+            this.entry_tbody = dojo.byId("entry_tbody");
+            this.template = this.entry_tbody.removeChild(
+                dojo.byId("entry_template")
+            );
+        }
+
+        this._clear_entry_batch_row();
+
+        this._call_number_cache = null;
+        this._prepared_call_number_controls = {};
+        this._location_by_lib = {};
+
+        /* empty the entry receiving table if we're starting over */
+        if (this.item_cache) {
+            for (var id in this.item_cache) {
+                this.finish_receipt(this.item_cache[id]);
+                hard_empty(this.entry_tbody);
+            }
+            /* XXX incredibly, running hard_empty() more than once seems to be
+             * good and necessary.  There's a bug under the covers somewhere,
+             * but this keeps it out of sight for the moment. */
+             hard_empty(this.entry_tbody);
+        }
+        hard_empty(this.entry_tbody);
+
+        this.rows = {};
+        this.item_cache = {};
+
+        if (bib_id)
+            this.bib_lookup(bib_id, null, true, sub_id);
+
+        busy(false);
+    };
+
+    this._clear_entry_batch_row = function() {
+        dojo.forEach(
+            dojo.byId("entry_batch_row").childNodes,
+            function(node) {
+                if (node.nodeType == 1 &&
+                    node.getAttribute("name") != "barcode")
+                    hard_empty(node);
+            }
+        );
+    };
+
+    this._show_bibdata_bits = function() {
+        hard_empty("title_here");
+        dojo.byId("title_here").appendChild(T(this.bibdata.mvr.title()));
+        hard_empty("author_here");
+
+        if (this.bibdata.mvr.author()) {
+            dojo.byId("author_here").appendChild(T(this.bibdata.mvr.author()));
+            show("author_here_holder");
+        } else {
+            hide("author_here_holder");
+        }
+
+        show("batch_receive_bibdata_bits");
+    };
+
+    this._sub_label = function(sub) {
+        /* XXX use a formatting string from serial.properties */
+        return sub.id() + ": (" + sub.owning_lib().shortname() + ") " +
+            D(sub.start_date()) + " - " + D(sub.end_date());
+    };
+
+    this._show_sub_bits = function() {
+        hard_empty("sublabel_here");
+        dojo.place(
+            T(this._sub_label(this.sub)),
+            "sublabel_here",
+            "only"
+        );
+        hide("batch_receive_sub");
+        show("batch_receive_sub_bits");
+    };
+
+    this._show_issuance_bits = function() {
+        hide("batch_receive_issuance");
+        hard_empty("issuance_label_here");
+        dojo.place(
+            T(this.issuance.label()),
+            "issuance_label_here",
+            "only"
+        );
+        show("batch_receive_issuance_bits");
+    }
+
+    this._get_receivable_issuances = function() {
+        var issuances = [];
+
+        busy(true);
+        try {
+            fieldmapper.standardRequest(
+                ["open-ils.serial", "open-ils.serial.issuances.receivable"], {
+                    "params": [this.authtoken, this.sub.id()],
+                    "async": false,
+                    "onresponse": function(r) {
+                        if (r = openils.Util.readResponse(r))
+                            issuances.push(r);
+                    }
+                }
+            );
+        } catch (E) {
+            alert(E);
+        }
+        busy(false);
+
+        return issuances;
+    };
+
+    this._build_circ_modifier_dropdown = function() {
+        if (!this._built_circ_modifier_dropdown) {
+            var menulist = dojo.create("menulist");
+            var menupopup = dojo.create("menupopup", null, menulist, "only");
+            dojo.create(
+                "menuitem", {"value": 0, "label": S("none")},
+                menupopup, "first"
+            );
+
+            var mods = [];
+            fieldmapper.standardRequest(
+                ["open-ils.circ", "open-ils.circ.circ_modifier.retrieve.all"],{
+                    "params": [{"full": true}],
+                    "async": false,
+                    "onresponse": function(r) {
+                        if (mods = openils.Util.readResponse(r)) {
+                            mods.sort(
+                                function(a,b) {
+                                    return a.code() > b.code() ? 1 :
+                                        b.code() > a.code() ? -1 :
+                                        0;
+                                }
+                            ).forEach(
+                                function(mod) {
+                                    dojo.create(
+                                        "menuitem", {
+                                            "value": mod.code(),
+                                            "label": document.getElementById('commonStrings').getFormattedString('staff.circ_modifier.display',[mod.code(),mod.name(),mod.description()]) 
+                                        }, menupopup, "last"
+                                    );
+                                }
+                            );
+                        }
+                    }
+                }
+            );
+            if (!mods.length) {
+                /* in this case, discard menulist and menupopup */
+                this._built_circ_modifier_dropdown =
+                    dojo.create("description", {"value": "-"});
+            } else {
+                this._built_circ_modifier_dropdown = menulist;
+            }
+        }
+
+        return dojo.clone(this._built_circ_modifier_dropdown);
+    };
+
+    this._extend_circ_modifier_for_batch = function(control) {
+        dojo.create(
+            "menuitem", {"value": -1, "label": "---"},
+            dojo.query("menupopup", control)[0],
+            "first"
+        );
+        return control;
+    };
+
+    this._build_location_dropdown = function(locs, add_unset_value) {
+        var menulist = dojo.create("menulist");
+        var menupopup = dojo.create("menupopup", null, menulist, "only");
+
+        if (add_unset_value) {
+            dojo.create(
+                "menuitem", {"value": -1, "label": "---"}, menupopup, "first"
+            );
+        }
+
+        locs.forEach(
+            function(loc) {
+                dojo.create(
+                    "menuitem", {
+                        "value": loc.id(), "label": loc.name()
+                    }, menupopup, "last"
+                );
+            }
+        );
+
+        return menulist;
+    };
+
+    this._get_locations_for_lib = function(lib) {
+        if (!this._location_by_lib[lib]) {
+            fieldmapper.standardRequest(
+                ["open-ils.circ", "open-ils.circ.copy_location.retrieve.all"],{
+                    "params": [lib, false, true],
+                    "async": false,
+                    "onresponse": function(r) {
+                        if (locs = openils.Util.readResponse(r))
+                            self._location_by_lib[lib] = locs;
+                    }
+                }
+            );
+        }
+
+        return this._location_by_lib[lib];
+    };
+
+    this._build_call_number_control = function(item) {
+        /* In any case, give a dropdown of call numbers related to the
+         * same bre as the subscription relates to. */
+        if (!this._call_number_cache) {
+            this._call_number_cache = this.pcrud.search(
+                "acn", {
+                    "record": this.sub.record_entry()
+                }, {
+                    "order_by": {"acn": "label"},   /* XXX wrong sorting? */
+                }
+            );
+        }
+
+        if (typeof item == "undefined") {
+            /* In this case, no further limiting of call numbers for now,
+             * although ideally it might be nice to limit to call numbers
+             * with owning_lib matching the holding_lib of the distribs
+             * that ultimately relate to the items. */
+
+            var menulist = dojo.create("menulist", {
+                "editable": "true", "className": "cn"
+            });
+            var menupopup = dojo.create("menupopup", null, menulist, "only");
+
+            openils.Util.uniqueObjects(this._call_number_cache, "label").
+                forEach(
+                    function(cn) {
+                        dojo.create(
+                            "menuitem", {
+                                "value": cn.label(), "label": cn.label()
+                            }, menupopup, "last"
+                        );
+                    }
+                );
+
+            return menulist;
+        } else {
+            /* In this case, limit call numbers by owning_lib matching
+             * distributions's holding_lib. */
+
+            var lib = item.stream().distribution().holding_lib().id();
+            if (!this._prepared_call_number_controls[lib]) {
+                var menulist = dojo.create("menulist", {
+                    "editable": "true", "className": "cn"
+                });
+                var menupopup = dojo.create("menupopup", null, menulist,"only");
+                this._call_number_cache.filter(
+                    function(cn) { return cn.owning_lib() == lib; }
+                ).forEach(
+                    function(cn) {
+                        dojo.create(
+                            "menuitem", {
+                                "value": cn.label(), "label": cn.label()
+                            }, menupopup, "last"
+                        );
+                    }
+                );
+                this._prepared_call_number_controls[lib] = menulist;
+            }
+            return dojo.clone(this._prepared_call_number_controls[lib]);
+        }
+    };
+
+    this._build_batch_location_dropdown = function() {
+        var menulist = dojo.create("menulist");
+        var menupopup = dojo.create("menupopup",null,menulist);
+        dojo.create("menuitem", {"value": -1, "label": "---"}, menupopup);
+
+        fieldmapper.standardRequest(
+            ["open-ils.circ",
+                "open-ils.circ.copy_location.retrieve.distinct.atomic"],{
+                "params": [],
+                "async": false,
+                "onresponse": function(r) {
+                    if (list = openils.Util.readResponse(r)) {
+                        list.forEach(
+                            function(locname) {
+                                dojo.create(
+                                    "menuitem", {
+                                        "value": locname, "label": locname
+                                    }, menupopup
+                                );
+                            }
+                        );
+                    }
+                }
+            }
+        );
+
+        return menulist;
+    };
+
+    this._build_receive_toggle = function(item) {
+        return dojo.create(
+            "checkbox", {
+                "oncommand": function(ev) {
+	                self._disable_row(item.id(), !ev.target.checked);
+                },
+                "checked": "true"
+            }
+        );
+    }
+
+    this._disable_row = function(item_id, disabled) {
+        var row = this.rows[item_id];
+        dojo.query("textbox,menulist", row).forEach(
+            function(element) { element.disabled = disabled; }
+        );
+        this._row_disabled(row, disabled);
+    };
+
+    this._row_disabled = function(row, disabled) {
+        if (typeof(row) == "string") row = this.rows[row];
+
+        var checkbox = dojo.query("checkbox", row)[0];
+
+        if (typeof(disabled) != "undefined")
+            checkbox.checked = !disabled;
+
+        return !checkbox.checked;
+    };
+
+    this._row_field_value = function(row, field, value) {
+        if (typeof(row) == "string") row = this.rows[row];
+
+        var node = dojo.query("*", node_by_name(field, row))[0];
+
+        if (typeof(value) == "undefined")
+            return node.value;
+        else
+            node.value = value;
+    }
+
+	this._user_wants_autogen = function() {
+        return dojo.byId("autogen_barcodes").checked;
+    };
+
+    this._get_autogen_potentials = function(item_id) {
+        var hit_a_wall = false;
+
+        return [openils.Util.objectProperties(this.rows).sort(num_sort).filter(
+            function(id) {
+                if (hit_a_wall) {
+                    return false;
+                } else if (id <= item_id || self._row_disabled(id)) {
+                    return false;
+                } else if (self._row_field_value(id, "barcode")) {
+                    hit_a_wall = true;
+                    return false;
+                } else {
+                    return true;
+                }
+            }
+        ), hit_a_wall];
+    };
+
+    this._prepare_autogen_control = function() {
+        dojo.attr("autogen_barcodes",
+            "command", function(ev) {
+                if (!ev.target.checked) {
+                    var list = self._have_autogen_barcodes();
+                    if (list.length && confirm(S("autogen_barcodes.remove"))) {
+                        list.forEach(
+                            function(id) {
+                                self._row_field_value(id, "barcode", "");
+                                self.rows[id]._has_autogen_barcode = false;
+                            }
+                        );
+                    }
+                }
+            }
+        );
+    };
+
+    this._have_autogen_barcodes = function() {
+        var list = [];
+        for (var id in this.rows)
+            if (this.rows[id]._has_autogen_barcode) list.push(id);
+        return list;
+    };
+
+    this._cn_exists_but_not_for_lib = function(lib, value) {
+        var exists = this._call_number_cache.filter(
+            function(cn) { return cn.label() == value }
+        );
+        var for_lib = exists.filter(
+            function(cn) { return cn.owning_lib() == lib; }
+        );
+        return (exists.length && !for_lib.length);
+    };
+
+    this._call_number_confirm_for_lib = function(lib, value) {
+        if (!this._has_confirmed_cn_for)
+            this._has_confirmed_cn_for = {};
+
+        if (typeof(this._has_confirmed_cn_for[lib.id()]) == "undefined") {
+            if (this._cn_exists_but_not_for_lib(lib.id(), value)) {
+                this._has_confirmed_cn_for[lib.id()] = confirm(
+                    F("cn_for_lib", [lib.shortname()])
+                );
+            } else {
+                this._has_confirmed_cn_for[lib.id()] = true;
+            }
+        }
+
+        return this._has_confirmed_cn_for[lib.id()];
+    }
+
+    this._confirm_row_field_application = function(id, key, value) {
+        if (key == "call_number") { /* XXX make a dispatch table so we can do
+                                       this for other fields too */
+            return this._call_number_confirm_for_lib(
+                this.item_cache[id].stream().distribution().holding_lib(),
+                value
+            );
+        } else {
+            return true;
+        }
+    };
+
+    this._location_by_name = function(id, value) {
+        var lib = this.item_cache[id].stream().distribution().
+            holding_lib().id();
+        var winners = this._location_by_lib[lib].filter(
+            function(loc) { return loc.name() == value; }
+        );
+        if (winners.length) {
+            return winners[0].id();
+        } else {
+            return null;
+        }
+    };
+
+    this._set_all_enabled_rows = function(key, value) {
+        /* do NOT do trimming here, set whitespace as is. */
+        for (var id in this.rows) {
+            if (!this._row_disabled(id)) {
+                if (this._confirm_row_field_application(id, key, value)) {
+                    if (key == "location") /* kludge for this field */ {
+                        if (actual = this._location_by_name(id, value))
+                            this._row_field_value(id, key, actual);
+                    } else {
+                        this._row_field_value(id, key, value);
+                    }
+                }
+            }
+        }
+    };
+
+    this.bib_lookup = function(bib_search_term, evt, is_actual_id, sub_id) {
+        if (evt && evt.keyCode != 13) return;
+
+        if (!bib_search_term) {
+            var bib_search_term = dojo.byId("bib_search_term").value.trim();
+            if (!bib_search_term.length) {
+                alert(S("bib_lookup.empty"));
+                return;
+            }
+        }
+
+        hide("batch_receive_sub");
+        hide("batch_receive_entry");
+
+        busy(true);
+        dojo.byId("bib_lookup_submit").disabled = true;
+        fieldmapper.standardRequest(
+            ["open-ils.serial",
+                "open-ils.serial.biblio.record_entry.by_identifier.atomic"], {
+                "params": [
+                    bib_search_term, {
+                        "require_subscriptions": true,
+                        "add_mvr": true,
+                        "is_actual_id": is_actual_id
+                    }
+                ],
+                "async": false,
+                "oncomplete": function(r) {
+                    /* These two things better come before readResponse(),
+                     * which can throw exceptions. */
+                    busy(false);
+                    dojo.byId("bib_lookup_submit").disabled = false;
+
+                    var list = openils.Util.readResponse(r, false, true);
+                    if (list && list.length) {
+                        if (list.length > 1) {
+                            /* XXX TODO just let the user pick one from a list,
+                             * although this circumstance seems really
+                             * unlikely.  It just can't happen for TCN, and
+                             * wouldn't be likely for ISxN or UPC... ? */
+                            alert(S("bib_lookup.multiple"));
+                        } else {
+                            self.bibdata = list[0];
+                            self._show_bibdata_bits();
+                            self.choose_subscription(sub_id);
+                        }
+                    } else {
+                        alert(S("bib_lookup.not_found"));
+                        if (is_actual_id) {
+                            self.init();
+                        } else {
+                            dojo.byId("bib_search_term").reset();
+                            dojo.byId("bib_search_term").focus();
+                        }
+                    }
+                }
+            }
+        );
+    };
+
+    this.choose_subscription = function(sub_id) {
+        hide("batch_receive_bib");
+        hide("batch_receive_entry");
+        hide("batch_receive_sub_bits");
+        hide("batch_receive_issuance");
+
+        var subs = this.bibdata.bre.subscriptions();
+
+        if (sub_id) {
+            this.choose_issuance(
+                subs.filter(function(o) { return o.id() == sub_id; })[0]
+            );
+        } else if (subs.length > 1) {
+            var menulist = dojo.create("menulist", {"id": "sub_chooser"});
+            var menupopup = dojo.create("menupopup", {}, menulist, "only");
+
+            this.bibdata.bre.subscriptions().forEach(
+                function(sub) {
+                    dojo.create(
+                        "menuitem", {
+                            "label": self._sub_label(sub),
+                            "value": sub.id()
+                        }, menupopup, "last"
+                    );
+                }
+            );
+
+            hard_empty(dojo.byId("sub_chooser_here"));
+
+            dojo.place(menulist, dojo.byId("sub_chooser_here"), "only");
+            show("batch_receive_sub");
+        } else {
+            this.choose_issuance(subs[0]);
+        }
+    };
+
+    this.choose_issuance = function(sub) {
+        hide("batch_receive_bib");
+        hide("batch_receive_entry");
+        hide("batch_receive_sub");
+
+        if (typeof(sub) == "undefined") {   /* sub chosen from menu */
+            var sub_id = dojo.byId("sub_chooser").value;
+            this.sub = this.bibdata.bre.subscriptions().filter(
+                function(o) { return o.id() == sub_id; }
+            )[0];
+        } else {    /* only one sub possible, passed in directly */
+            this.sub = sub;
+        }
+
+        this._show_sub_bits();
+
+        this.issuances = this._get_receivable_issuances();   /* sync */
+
+        if (this.issuances.length > 1) {
+            var menulist = dojo.create("menulist", {"id": "issuance_chooser"});
+            var menupopup = dojo.create("menupopup", {}, menulist, "only");
+
+            this.issuances.sort(
+                function(a, b) {
+                    if (a.date_published()>b.date_published()) return 1;
+                    else if (b.date_published()>a.date_published()) return -1;
+                    else return 0;
+                }
+            ).forEach(
+                function(issuance) {
+                    dojo.create(
+                        "menuitem", {
+                            "label": issuance.label(),
+                            "value": issuance.id()
+                        }, menupopup, "last"
+                    );
+                }
+            );
+
+            hard_empty("issuance_chooser_here");
+            dojo.place(menulist, dojo.byId("issuance_chooser_here"), "only");
+
+            show("batch_receive_issuance");
+        } else if (this.issuances.length) {
+            this.load_entry_form(this.issuances[0]);
+        } else {
+            alert(S("issuance_lookup.none"));
+            this.init();
+        }
+
+    };
+
+    this.load_entry_form = function(issuance) {
+        if (typeof(issuance) == "undefined") {
+            var issuance_id = dojo.byId("issuance_chooser").value;
+            this.issuance = this.issuances.filter(
+                function(o) { return o.id() == issuance_id; }
+            )[0];
+        } else {
+            this.issuance = issuance;
+        }
+
+        this._show_issuance_bits();
+        this._prepare_autogen_control();
+
+        busy(true);
+
+        fieldmapper.standardRequest(
+            ["open-ils.serial",
+                "open-ils.serial.items.receivable.by_issuance.atomic"], {
+                "params": [this.authtoken, this.issuance.id()],
+                "async": true,
+                "onresponse": function(r) {
+                    busy(false);
+
+                    if (list = openils.Util.readResponse(r, false, true)) {
+
+                        if (list.length) {
+                            busy(true);
+                            show("form_holder");
+
+                            list.forEach(function(o) {self.add_entry_row(o);});
+
+                            self.build_batch_entry_row();
+                            dojo.byId("batch_receive_with_units").doCommand();
+
+                            show("batch_receive_entry");
+                            busy(false);
+                        } else {
+                            alert(S("item_lookup.none"));
+                            if (self.issuances.length) self.choose_issuance();
+                            else self.init();
+                        }
+                    }
+                }
+            }
+        );
+    };
+
+    this.toggle_receive_with_units = function(ev) {
+        var head_row = dojo.byId("batch_receive_entry_thead");
+        var batch_row = dojo.byId("entry_batch_row");
+
+        var fields = [
+            "barcode", "call_number", "price", "location", "circ_modifier"
+        ];
+
+        var table_cell_func = ev.target.checked ?
+            show_table_cell : hide_table_cell;
+        fields.forEach(
+            function(key) {
+                if (batch_row) table_cell_func(node_by_name(key, batch_row));
+                if (head_row) table_cell_func(node_by_name(key, head_row));
+
+                for (var id in self.rows) {
+                    table_cell_func(node_by_name(key, self.rows[id]));
+                }
+            }
+        );
+
+        if (!ev.target.checked) {
+            /* XXX As of the time of this writing, a blank barcode field will
+             * avoid unit creation */
+            this._set_all_enabled_rows("barcode", "");
+        }
+    };
+
+    this.toggle_all_receive = function(checked) {
+        for (var id in this.rows) {
+            this._disable_row(id, !checked);
+        }
+    };
+
+    this.build_batch_entry_row = function() {
+        var row = dojo.byId("entry_batch_row");
+
+        this.batch_controls = {};
+
+        node_by_name("note", row).appendChild(
+            this.batch_controls.note = dojo.create("textbox", {"size": 20})
+        );
+
+        node_by_name("location", row).appendChild(
+            this.batch_controls.location =
+                this._build_batch_location_dropdown()
+        );
+
+        node_by_name("circ_modifier", row).appendChild(
+            this.batch_controls.circ_modifier =
+                this._extend_circ_modifier_for_batch(
+                    this._build_circ_modifier_dropdown() /* for all OUs */
+                )
+        );
+
+        node_by_name("call_number", row).appendChild(
+            this.batch_controls.call_number = this._build_call_number_control()
+        );
+
+        node_by_name("price", row).appendChild(
+            this.batch_controls.price = dojo.create("textbox", {"size": 9})
+        );
+
+        node_by_name("receive", row).appendChild(
+            dojo.create(
+                "checkbox", {
+                    "oncommand": function(ev) {
+                        self.toggle_all_receive(ev.target.checked);
+                    },
+                    "checked": "true"
+                }
+            )
+        );
+
+        node_by_name("apply", row).appendChild(
+            dojo.create("button", {
+                "label": S("apply"),
+                "oncommand": function() { self.apply_batch_values(); }
+            })
+        );
+    };
+
+    this.apply_batch_values = function() {
+        var row = dojo.byId("entry_batch_row");
+
+        for (var key in this.batch_controls) {
+            var value = this.batch_controls[key].value;
+            if (value != "" && value != -1)
+                this._set_all_enabled_rows(key, value);
+        }
+
+        /* XXX genericize for all fields? */
+        delete this._has_confirmed_cn_for;
+    };
+
+    this.add_entry_row = function(item) {
+        this.item_cache[item.id()] = item;
+        var row = this.rows[item.id()] = dojo.clone(this.template);
+
+        function n(s) { return node_by_name(s, row); }    /* typing saver */
+
+        var stream_dist_label = item.stream().distribution().label();
+        if (item.stream().routing_label())
+            stream_dist_label += " / " + item.stream().routing_label();
+
+        n("holding_lib").appendChild(
+            dojo.create(
+                "description", {
+                    "value": item.stream().distribution().
+                        holding_lib().shortname(),
+                    "tooltiptext": stream_dist_label
+                }
+            )
+        );
+
+        n("barcode").appendChild(
+            dojo.create(
+                "textbox", {
+                    "size": 15,
+                    "tabindex": 10000 + Number(item.id()), /* is this right? */
+                    "onchange": function() {
+                        self.autogen_if_appropriate(this, item.id());
+                    }
+                }
+            )
+        );
+
+        n("location").appendChild(
+            this._build_location_dropdown(
+                this._get_locations_for_lib(
+                    item.stream().distribution().holding_lib().id()
+                )
+            )
+        );
+
+        n("note").appendChild(dojo.create("textbox", {"size": 20}));
+        n("circ_modifier").appendChild(this._build_circ_modifier_dropdown());
+        n("call_number").appendChild(this._build_call_number_control(item));
+        n("price").appendChild(dojo.create("textbox", {"size": 9}));
+        n("receive").appendChild(this._build_receive_toggle(item));
+
+        this.entry_tbody.appendChild(row);
+    };
+
+    this.receive = function() {
+        var items = [];
+        var confirmed_missing_units = false;
+
+        for (var id in this.rows) {
+            if (this._row_disabled(id))
+                continue;
+
+            var item = this.item_cache[id];
+
+            /* Don't trim() call_number field, as existing call numbers
+             * are yielded by their label field, not by id, and if
+             * they start or end in spaces, we'll unintentionally create
+             * a new, different CN if we trim that */
+            var cn_string = this._row_field_value(id, "call_number");
+            var barcode = this._row_field_value(id, "barcode").trim();
+
+            if (barcode && cn_string.length) {
+                var unit = new sunit();
+                unit.barcode(barcode);
+
+                ["price", "location", "circ_modifier"].forEach(
+                    function(field) {
+                        var value = self._row_field_value(id, field).trim();
+                        if (value) unit[field](value);
+                    }
+                );
+
+                unit.call_number(cn_string);
+                item.unit(unit);
+            } else if (barcode && !cn_string.length) {
+                alert(S("missing_cn"));
+                return;
+            } else if (!confirmed_missing_units) {
+                if (
+                    (!dojo.byId("batch_receive_with_units").checked) ||
+                    confirm(S("missing_units"))
+                ) {
+                    confirmed_missing_units = true;
+                } else {
+                    return;
+                }
+            }
+
+            var note_value = this._row_field_value(id, "note").trim();
+            if (note_value) {
+                var note = new sin();
+                note.item(id);
+                note.pub(false);
+                note.title(S("receive_time_note"));
+                note.value(note_value);
+
+                item.notes([note]);
+            }
+
+            items.push(item);
+        }
+
+        busy(true);
+        fieldmapper.standardRequest(
+            ["open-ils.serial", "open-ils.serial.receive_items.one_unit_per"],{
+                "params": [this.authtoken, items, this.sub.record_entry()],
+                "async": true,
+                "oncomplete": function(r) {
+                    try {
+                        while (item_id = openils.Util.readResponse(r))
+                            self.finish_receipt(item_id);
+                    } catch (E) {
+                        alert(E);
+                    }
+                    busy(false);
+                }
+            }
+        );
+    };
+
+    this.finish_receipt = function(item_id) {
+        hard_empty(this.rows[item_id]);
+        dojo.destroy(this.rows[item_id]);
+        delete this.rows[item_id];
+        delete this.item_cache[item_id];
+    };
+
+    this.autogen_if_appropriate = function(textbox, item_id) {
+        if (this._user_wants_autogen() && textbox.value) {
+            var [list, question] = this._get_autogen_potentials(item_id);
+            if (list.length) {
+                if (question && !confirm(S("autogen_barcodes.questionable")))
+                    return;
+
+                busy(true);
+                try {
+                    fieldmapper.standardRequest(
+                        ["open-ils.cat", "open-ils.cat.item.barcode.autogen"], {
+                            "params": [
+                                this.authtoken, textbox.value, list.length
+                            ],
+                            "async": false,
+                            "onresponse": function(r) {
+                                r = openils.Util.readResponse(r, false, true);
+                                if (r) {
+                                    for (var i = 0; i < r.length; i++) {
+                                        var row = self.rows[list[i]];
+                                        self._row_field_value(
+                                            row, "barcode", r[i]
+                                        );
+                                        row._has_autogen_barcode = true;
+                                    }
+                                }
+                            }
+                        }
+                    );
+                } catch (E) {
+                    alert(E);
+                }
+                busy(false);
+            } /* do nothing for empty list */
+        }
+    };
+
+    this.init.apply(this, arguments);
+}
+
+function my_init() {
+    var cgi = new openils.CGI();
+
+    batch_receiver = new BatchReceiver(
+        (typeof ses == "function" ? ses() : 0) ||
+            cgi.param("ses") || dojo.cookie("ses"),
+        cgi.param("docid") || null, cgi.param("subid") || null
+    );
+}

Copied: branches/serials-integration/Open-ILS/xul/staff_client/server/serial/batch_receive.xul (from rev 17886, trunk/Open-ILS/xul/staff_client/server/serial/batch_receive.xul)
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/server/serial/batch_receive.xul	                        (rev 0)
+++ branches/serials-integration/Open-ILS/xul/staff_client/server/serial/batch_receive.xul	2010-10-18 13:46:56 UTC (rev 18371)
@@ -0,0 +1,32 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
+<?xml-stylesheet href="/xul/server/skin/global.css" type="text/css"?>
+<?xml-stylesheet href="/xul/server/skin/serial.css" type="text/css"?>
+<!DOCTYPE window PUBLIC "" ""[
+    <!--#include virtual="/opac/locale/${locale}/lang.dtd"-->
+]>
+<?xul-overlay href="/xul/server/OpenILS/util_overlay.xul"?>
+<?xul-overlay href="/xul/server/serial/batch_receive_overlay.xul"?>
+
+<window id="batch_receive_win"
+    onload="try{my_init();font_helper();persist_helper();}catch(E){alert(E);}"
+    xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+    <script type="text/javascript">
+        var myPackageDir = "open_ils_staff_client";
+        var IAMXUL = true;
+        var g = {};
+    </script>
+
+    <scripts id="openils_util_scripts" />
+
+    <!-- JSAN is still needed for font_helper stuff, but I'm going to try
+        not to use it otherwise.  -->
+    <script type="text/javascript" src="/xul/server/main/JSAN.js" />
+
+    <messagecatalog id="serialStrings"
+        src="/xul/server/locale/<!--#echo var='locale'-->/serial.properties" />
+
+    <commandset />
+    <box id="batch_receive_main" />
+</window>

Copied: branches/serials-integration/Open-ILS/xul/staff_client/server/serial/batch_receive_overlay.xul (from rev 17886, trunk/Open-ILS/xul/staff_client/server/serial/batch_receive_overlay.xul)
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/server/serial/batch_receive_overlay.xul	                        (rev 0)
+++ branches/serials-integration/Open-ILS/xul/staff_client/server/serial/batch_receive_overlay.xul	2010-10-18 13:46:56 UTC (rev 18371)
@@ -0,0 +1,172 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE overlay PUBLIC "" ""[
+    <!--#include virtual="/opac/locale/${locale}/lang.dtd"-->
+]>
+<overlay id="batch_receive_overlay"
+    xmlns:h="http://www.w3.org/1999/xhtml"
+    xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+    <script type="text/javascript" src="/xul/server/serial/common.js" />
+    <script type="text/javascript" src="/xul/server/serial/batch_receive.js" />
+
+    <box id="batch_receive_main" flex="1" orient="vertical" class="my_overflow">
+        <caption class="top" label="&staff.serial.batch_receive;" />
+
+        <vbox flex="1" id="batch_receve_main_action">
+            <vbox id="batch_receive_bib" class="hideme">
+                <hbox align="center" flex="0">
+                    <label
+                        control="bib_search_term"
+                        accesskey="&staff.serial.batch_receive.bib_search_term.accesskey;"
+                        value="&staff.serial.batch_receive.bib_search_term;" />
+                    <textbox id="bib_search_term"
+                        onkeypress="batch_receiver.bib_lookup(null, event);" />
+                    <button id="bib_lookup_submit"
+                        oncommand="batch_receiver.bib_lookup();"
+                        label="&staff.serial.batch_receive.find_record;"
+                        accesskey="&staff.serial.batch_receive.find_record.accesskey;" />
+                </hbox>
+            </vbox>
+
+            <vbox id="batch_receive_bibdata_bits" class="hideme">
+                <hbox>
+                    <label value="&staff.serial.batch_receive.title;" />
+                    <description id="title_here" />
+                </hbox>
+                <hbox id="author_here_holder" class="hideme">
+                    <label value="&staff.serial.batch_receive.author;" />
+                    <description id="author_here" />
+                </hbox>
+            </vbox>
+
+            <box id="batch_receive_sub_bits" class="hideme">
+                <label value="&staff.serial.batch_receive.fulfilling_sub;" />
+                <description id="sublabel_here" />
+            </box>
+
+            <vbox id="batch_receive_sub" class="hideme">
+                <hbox align="center">
+                    <label
+                        control="sub_chooser"
+                        value="&staff.serial.batch_receive.choose_sub;"
+                        accesskey="&staff.serial.batch_receive.choose_sub.accesskey;" />
+                    <box id="sub_chooser_here"></box>
+                    <button
+                        oncommand="batch_receiver.choose_issuance();"
+                        label="&staff.serial.batch_receive.next;"
+                        accesskey="&staff.serial.batch_receive.next.accesskey;" />
+                </hbox>
+            </vbox>
+
+            <box id="batch_receive_issuance_bits" class="hideme">
+                <label value="&staff.serial.batch_receive.issuance;" />
+                <description id="issuance_label_here" />
+            </box>
+
+            <vbox id="batch_receive_issuance" class="hideme">
+                <hbox align="center">
+                    <label
+                        control="issuance_chooser"
+                        value="&staff.serial.batch_receive.choose_issuance;"
+                        accesskey="&staff.serial.batch_receive.choose_issuance.accesskey;" />
+                    <box id="issuance_chooser_here"></box>
+                    <button
+                        oncommand="batch_receiver.load_entry_form();"
+                        label="&staff.serial.batch_receive.next;"
+                        accesskey="&staff.serial.batch_receive.next.accesskey;" />
+                </hbox>
+            </vbox>
+
+            <vbox id="batch_receive_no_entry" class="hideme">
+                <description value="&staff.serial.batch_receive.no_items;" />
+            </vbox>
+
+            <vbox id="batch_receive_entry" class="hideme">
+                <box class="hideme" id="form_holder">
+                    <!-- XXX should be a XUL grid instead of an HTML table -->
+                    <h:table id="batch_receive_entry_thead">
+                        <h:thead>
+                            <h:tr>
+                                <h:th>
+                                    &staff.serial.batch_receive.org_unit;
+                                </h:th>
+                                <h:th name="barcode">
+                                    &staff.serial.batch_receive.barcode;
+                                </h:th>
+                                <h:th name="circ_modifier">
+                                    &staff.serial.batch_receive.circ_modifier;
+                                </h:th>
+                                <h:th name="call_number">
+                                    &staff.serial.batch_receive.call_number;
+                                </h:th>
+                                <h:th>
+                                    &staff.serial.batch_receive.note;
+                                </h:th>
+                                <h:th name="location">
+                                    &staff.serial.batch_receive.location;
+                                </h:th>
+                                <h:th name="price">
+                                    &staff.serial.batch_receive.price;
+                                </h:th>
+                                <h:th>
+                                    &staff.serial.batch_receive.receive;
+                                </h:th>
+                            </h:tr>
+                        </h:thead>
+                        <h:tbody id="entry_batch_tbody">
+                            <h:tr id="entry_batch_row">
+                                <h:td name="holding_lib"><!-- empty --></h:td>
+                                <h:td name="barcode" align="center">
+                                    <checkbox
+                                        id="autogen_barcodes"
+                                        label="&staff.serial.batch_receive.auto_generate;" />
+                                </h:td>
+                                <h:td name="circ_modifier" align="center"></h:td>
+                                <h:td name="call_number" align="center"></h:td>
+                                <h:td name="note"></h:td>
+                                <h:td name="location" align="center"></h:td>
+                                <h:td name="price"></h:td>
+                                <h:td name="receive" align="center"></h:td>
+                                <h:td name="apply"></h:td>
+                            </h:tr>
+                            <h:tr>
+                                <h:td colspan="8">
+                                    <h:hr size="4" />
+                                </h:td>
+                            </h:tr>
+                        </h:tbody>
+                        <h:tbody id="entry_tbody">
+                            <h:tr id="entry_template">
+                                <h:td name="holding_lib" align="center"></h:td>
+                                <h:td name="barcode"></h:td>
+                                <h:td name="circ_modifier" align="center"></h:td>
+                                <h:td name="call_number" align="center"></h:td>
+                                <h:td name="note"></h:td>
+                                <h:td name="location" align="center"></h:td>
+                                <h:td name="price"></h:td>
+                                <h:td name="receive" align="center"></h:td>
+                            </h:tr>
+                        </h:tbody>
+                    </h:table>
+                </box>
+                <hbox id="entry_submitter" flex="1">
+                    <button oncommand="batch_receiver.receive();"
+                        label="&staff.serial.batch_receive.recieve_selected;" />
+                </hbox>
+            </vbox>
+        </vbox>
+
+        <hbox align="center">
+            <button oncommand="batch_receiver.init();"
+                label="&staff.serial.batch_receive.start_over;"
+                accesskey="&staff.serial.batch_receive.start_over.accesskey;" />
+            <spacer flex="1" />
+            <checkbox
+                id="batch_receive_with_units"
+                oils_persist="checked"
+                oncommand="batch_receiver.toggle_receive_with_units(event);"
+                label="&staff.serial.batch_receive.with_units;"
+                accesskey="&staff.serial.batch_receive.with_units.accesskey;" />
+        </hbox>
+    </box>
+</overlay>

Copied: branches/serials-integration/Open-ILS/xul/staff_client/server/serial/common.js (from rev 17886, trunk/Open-ILS/xul/staff_client/server/serial/common.js)
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/server/serial/common.js	                        (rev 0)
+++ branches/serials-integration/Open-ILS/xul/staff_client/server/serial/common.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -0,0 +1,62 @@
+String.prototype.trim = function() {return this.replace(/^\s*(.+)\s*$/,"$1");}
+
+/**
+ * hard_empty() is needed because dojo.empty() doesn't seem to work on
+ * XUL nodes. This also means that dojo.place() with a position argument of
+ * "only" doesn't do what it should, but calling hard_empty() on the refnode
+ * first will do the trick.
+ */
+function hard_empty(node) {
+    if (typeof(node) == "string")
+        node = dojo.byId(node);
+    if (node)
+        dojo.forEach(node.childNodes, dojo.destroy);
+}
+
+function hide(e) {
+    if (typeof(e) == "string") e = dojo.byId(e);
+    openils.Util.addCSSClass(e, "hideme");
+}
+
+function show(e) {
+    if (typeof(e) == "string") e = dojo.byId(e);
+    openils.Util.removeCSSClass(e, "hideme");
+}
+
+function hide_table_cell(e) {
+    if (typeof(e) == "string") e = dojo.byId(e);
+
+    e.style.display = "none";
+    e.style.visibility = "hidden";
+}
+
+function show_table_cell(e) {
+    if (typeof(e) == "string") e = dojo.byId(e);
+    e.style.display = "table-cell";
+    e.style.visibility = "visible";
+}
+
+function soft_hide(e) { /* doesn't disrupt XUL grid alignment */
+    if (typeof(e) == "string") e = dojo.byId(e);
+    e.style.visibility = "hidden";
+}
+
+function soft_show(e) {
+    if (typeof(e) == "string") e = dojo.byId(e);
+    e.style.visibility = "visible";
+}
+
+function busy(on) {
+    if (typeof(busy._window) == "undefined")
+        busy._window = dojo.query("window")[0];
+    busy._window.style.cursor = on ? "wait" : "auto";
+}
+
+function T(s) { return document.createTextNode(s); }
+function D(s) {return s ? openils.Util.timeStamp(s, {"selector":"date"}) : "";}
+function node_by_name(s, ctx) {return dojo.query("[name='" + s + "']", ctx)[0];}
+
+function num_sort(a, b) {
+    [a, b] = [Number(a), Number(b)];
+    return a > b ? 1 : (a < b ? -1 : 0);
+}

Copied: branches/serials-integration/Open-ILS/xul/staff_client/server/serial/pattern_wizard.js (from rev 17886, trunk/Open-ILS/xul/staff_client/server/serial/pattern_wizard.js)
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/server/serial/pattern_wizard.js	                        (rev 0)
+++ branches/serials-integration/Open-ILS/xul/staff_client/server/serial/pattern_wizard.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -0,0 +1,619 @@
+/* The code in this file relies on common.js */
+
+dojo.require("openils.Util");
+
+var wizard;
+
+function S(k) {
+    return dojo.byId("serialStrings").getString("pattern_wizard." + k).
+        replace("\\n", "\n");
+}
+
+function _month_menuitems() {
+    /* XXX i18n, and also this is just pathetic in general, but a datepicker
+     * seemed wrong since we don't want a year. */
+    return [
+        ["01", "January"],
+        ["02", "February"],
+        ["03", "March"],
+        ["04", "April"],
+        ["05", "May"],
+        ["06", "June"],
+        ["07", "July"],
+        ["08", "August"],
+        ["09", "September"],
+        ["10", "October"],
+        ["11", "November"],
+        ["12", "December"]
+    ].map(
+        function(t) {
+            return dojo.create("menuitem", {"value": t[0], "label": t[1]});
+        }
+    );
+}
+
+function _date_validate(date_val, month_val) {
+    /* general purpose date validation irrespective of year */
+    date_val = date_val.trim();
+
+    if (!date_val.match(/^[0123]?\d$/))
+        return false;
+
+    date_val = Number(date_val); /* do NOT use parseInt */
+    month_val = Number(month_val);
+
+    if (date_val < 1) {
+        return false;
+    } else if (month_val == 2) {
+        return date_val <= 29;
+    } else if ([1,3,5,7,8,10,12].indexOf(month_val) != -1) {
+        return date_val <= 31;
+    } else {
+        return date_val <= 30;
+    }
+}
+
+function CalendarChangeRow() {
+    var self = this;
+
+    this._init = function(template, id, manager) {
+        this.element = dojo.clone(template);
+
+        this.point_widgets = ["month", "season", "date"].map(
+            function(type) { return node_by_name(type, self.element); }
+        );
+
+        dojo.attr(
+            node_by_name("type", this.element), "oncommand", function(ev) {
+                self.point_widgets.forEach(
+                    function(w) {
+                        var active = (dojo.attr(w, "name") == ev.target.value);
+                        (active ? show : hide)(w);
+                    }
+                );
+            }
+        );
+
+        var date_month_selector = node_by_name("date_month", this.element);
+
+        dojo.attr(
+            node_by_name("date_day", this.element), "onchange", function(ev) {
+                if (_date_validate(ev.target.value,date_month_selector.value)){
+                    return true;
+                } else {
+                    alert(S("bad_date_value"));
+                    ev.target.focus();
+                    return false;
+                }
+            }
+        );
+
+        this.remover = node_by_name("remover", this.element);
+        dojo.attr(
+            this.remover, "onclick", function() { manager.remove_row(id); }
+        );
+    };
+
+    this._compile_month = function() {
+        return node_by_name("month", this.element).value;
+    };
+
+    this._compile_season = function() {
+        return node_by_name("season", this.element).value;
+    };
+
+    this._compile_date = function() {
+        var n = Number(node_by_name("date_day", this.element).value);
+        if (n < 10)
+            n = "0" + String(n);
+        else
+            n = String(n);
+
+        return node_by_name("date_month", this.element).value + n;
+    };
+
+    this.compile = function() {
+        var type = node_by_name("type", this.element).value;
+
+        return type ? this["_compile_" + type]() : [];
+    };
+
+    this._init.apply(this, arguments);
+};
+
+function CalendarChangeEditor() {
+    var self = this;
+
+    this._init = function() {
+        this.rows = {};
+        this.row_count = 0;
+
+        this._get_template();
+        this.add_row();
+    };
+
+    this._get_template = function() {
+        var temp_template = dojo.byId("calendar_row_template");
+        this.grid = temp_template.parentNode;
+        this.template = this.grid.removeChild(temp_template);
+        this.template.removeAttribute("id");
+
+        [
+            dojo.query("[name='month'] menupopup", this.template)[0],
+            dojo.query("[name='date_month'] menupopup", this.template)[0]
+        ].forEach(
+            function(menupopup) {
+                _month_menuitems().forEach(
+                    function(menuitem) {
+                        dojo.place(menuitem, menupopup, "last");
+                    }
+                );
+            }
+        );
+    };
+
+    this.remove_row = function(id) {
+        hard_empty(this.rows[id].element);
+        dojo.destroy(this.rows[id].element);
+        delete this.rows[id];
+
+        dojo.byId("calendar_change_add_row").disabled = false;
+    };
+
+    this.add_row = function() {
+        var id = this.row_count++;
+
+        this.rows[id] =
+            new CalendarChangeRow(dojo.clone(this.template), id, this);
+        dojo.place(this.rows[id].element, this.grid, "last");
+    };
+
+    this.toggle = function(ev) {
+        this.active = ev.target.checked;
+        (this.active ? show : hide)("calendar_change_editor_here");
+    };
+
+    this.compile = function() {
+        if (!this.active) return [];
+
+        return [
+            "x",
+            openils.Util.objectProperties(this.rows).sort(num_sort).map(
+                function(key) { return self.rows[key].compile(); }
+            ).join(",")
+        ];
+    };
+
+    this._init.apply(this, arguments);
+}
+
+function ChronRow() {
+    var self = this;
+
+    this._init = function(template, subfield, manager) {
+        this.subfield = subfield;
+        this.element = dojo.clone(template);
+
+        dojo.attr(
+            node_by_name("caption_label", this.element),
+            "value", S("chronology." + subfield) + ":"
+        );
+
+        this.fields = {};
+        ["caption", "display_in_holding"].forEach(
+            function(o) { self.fields[o] = node_by_name(o, self.element); }
+        );
+
+        this.remover = node_by_name("remover", this.element);
+        dojo.attr(
+            this.remover, "onclick", function(){ manager.remove_row(subfield); }
+        );
+    };
+
+    this._init.apply(this, arguments);
+};
+
+function ChronEditor() {
+    /* TODO make this enforce unique caption values for each row? */
+    var self = this;
+
+    this._init = function() {
+        this.rows = {};
+
+        this.subfields = ["i", "j", "k", "l", "m"];
+
+        this._get_template();
+        this.add_row();
+    };
+
+    this._get_template = function() {
+        var temp_template = dojo.byId("chron_row_template");
+        this.grid = temp_template.parentNode;
+        this.template = this.grid.removeChild(temp_template);
+        this.template.removeAttribute("id");
+    };
+
+    this._test_removability = function(subfield) {
+        var start = this.subfields.indexOf(subfield);
+
+        if (start < 0) {
+            /* no such field, not OK to remove */
+            return false;
+        } else if (!this.subfields[start]) {
+            /* field row not present, not OK to remove */
+            return false;
+        }
+
+        var next = this.subfields[start + 1];
+        if (typeof(next) == "undefined") { /* last in set, ok to remove */
+            return true;
+        } else {
+            if (this.rows[next]) { /* NOT last in set, not ok to remove */
+                return false;
+            } else { /* last in set actually present, ok to remove */
+                return true;
+            }
+        }
+    };
+
+    this.remove_row = function(subfield) {
+        if (this._test_removability(subfield)) {
+            hard_empty(this.rows[subfield].element);
+            dojo.destroy(this.rows[subfield].element);
+            delete this.rows[subfield];
+
+            dojo.byId("chron_add_row").disabled = false;
+        } else {
+            alert(S("not_removable_row"));
+        }
+    };
+
+    this.add_row = function() {
+        var available = this.subfields.filter(
+            function(subfield) { return !Boolean(self.rows[subfield]); }
+        );
+
+        if (available.length) {
+            var subfield = available.shift();
+            if (!available.length)
+                dojo.byId("chron_add_row").disabled = true;
+        } else {
+            /* We shouldn't really be able to get here. */
+            return;
+        }
+
+        this.rows[subfield] =
+            new ChronRow(dojo.clone(this.template), subfield, this);
+
+        dojo.place(this.rows[subfield].element, this.grid, "last");
+    };
+
+    this.toggle = function(ev) {
+        this.active = ev.target.checked;
+        (this.active ? show : hide)("chron_editor_here");
+    };
+
+    this.compile = function() {
+        if (!this.active) return [];
+
+        return this.subfields.filter(
+            function(subfield) { return Boolean(self.rows[subfield]); }
+        ).reduce(
+            function(result, subfield) {
+                var caption = self.rows[subfield].fields.caption.value;
+                if (!self.rows[subfield].fields.display_in_holding.checked)
+                    caption = "(" + caption + ")";
+                return result.concat([subfield, caption]);
+            }, []
+        );
+    };
+
+    this._init.apply(this, arguments);
+}
+
+function EnumRow() {
+    var self = this;
+
+    this._init = function(template, subfield, manager) {
+        this.subfield = subfield;
+        this.element = dojo.clone(template);
+
+        this.fields = {};
+        ["caption","units_per","units_per_number","continuity","remover"].
+            forEach(
+                function(o) { self.fields[o] = node_by_name(o, self.element); }
+            );
+
+        if (subfield == "a" || subfield == "g") {
+            ["units_per", "continuity"].forEach(
+                function(o) { soft_hide(node_by_name(o, self.element)); }
+            );
+        }
+
+        var caption_id = "enum_caption_" + subfield;
+        var caption_label = node_by_name("caption_label", this.element);
+        dojo.attr(this.fields.caption, "id", caption_id);
+        dojo.attr(caption_label, "control", caption_id);
+        dojo.attr(caption_label, "value", S("enumeration." + subfield) + ":");
+
+        this.remover = this.fields.remover;
+        dojo.attr(
+            this.remover, "onclick", function(){manager.remove_row(subfield);}
+        );
+    };
+
+    this._init.apply(this, arguments);
+};
+
+function EnumEditor() {
+    var self = this;
+
+    this._init = function() {
+        this.normal_rows = {};
+        this.alt_rows = {};
+
+        this.normal_subfields = ["a","b","c","d","e","f"];
+        this.alt_subfields = ["g","h"];
+
+        this._get_template();
+        this.add_normal_row();
+    };
+
+    this._get_template = function() {
+        var temp_template = dojo.byId("enum_row_template");
+        this.grid = temp_template.parentNode;
+        this.template = this.grid.removeChild(temp_template);
+        this.template.removeAttribute("id");
+    };
+
+    this.remove_row = function(subfield) {
+        if (this._test_removability(subfield)) {
+            var add_button = "enum_add_normal_row";
+            var set = this.normal_rows;
+            if (!set[subfield]) {
+                set = this.alt_rows;
+                add_button = "enum_add_alt_row";
+            }
+
+            hard_empty(set[subfield].element);
+            dojo.destroy(set[subfield].element);
+            delete set[subfield];
+            dojo.byId(add_button).disabled = false;
+        } else {
+            alert(S("not_removable_row"));
+        }
+    };
+
+    this._test_removability = function(id) {
+        var set = this.normal_subfields;
+        var rows = this.normal_rows;
+        var start = set.indexOf(id);
+
+        if (start == -1) {
+            set = this.alt_subfields;
+            rows = this.alt_rows;
+            start = set.indexOf(id);
+        }
+
+        if (start < 0) {
+            /* no such field, not OK to remove */
+            return false;
+        } else if (!set[start]) {
+            /* field row not present, not OK to remove */
+            return false;
+        }
+
+        var next = set[start + 1];
+        if (typeof(next) == "undefined") { /* last in set, ok to remove */
+            return true;
+        } else {
+            if (rows[next]) { /* NOT last in set, not ok to remove */
+                return false;
+            } else { /* last in set actually present, ok to remove */
+                return true;
+            }
+        }
+    };
+
+    this.add_normal_row = function() {
+        var available = this.normal_subfields.filter(
+            function(subfield) { return !Boolean(self.normal_rows[subfield]); }
+        );
+        if (available.length) {
+            var subfield = available.shift();
+            if (!available.length) {
+                /* If that was the last available normal row, disable the
+                 * add rows button. */
+                dojo.byId("enum_add_normal_row").disabled = true;
+            }
+        } else {
+            /* We shouldn't really be able to get here. */
+            return;
+        }
+
+        this.normal_rows[subfield] =
+            new EnumRow(dojo.clone(this.template), subfield, this);
+
+        dojo.place(this.normal_rows[subfield].element, this.grid, "last");
+    };
+
+    this.add_alt_row = function() {
+        var available = this.alt_subfields.filter(
+            function(subfield) { return !Boolean(self.alt_rows[subfield]); }
+        );
+        if (available.length) {
+            var subfield = available.shift();
+            if (!available.length) {
+                /* If that was the last available normal row, disable the
+                 * add rows button. */
+                dojo.byId("enum_add_alt_row").disabled = true;
+            }
+        } else {
+            /* We shouldn't really be able to get here. */
+            return;
+        }
+
+        this.alt_rows[subfield] =
+            new EnumRow(dojo.clone(this.template), subfield, this);
+
+        dojo.place(this.alt_rows[subfield].element, this.grid, "last");
+    };
+
+    this.toggle = function(ev) {
+        var func;
+        var use_calendar_change = dojo.byId("use_calendar_change");
+
+        this.active = ev.target.checked;
+
+        if (this.active) {
+            func = show;
+            use_calendar_change.disabled = false;
+        } else {
+            use_calendar_change.checked = false;
+            use_calendar_change.doCommand();
+            use_calendar_change.disabled = true;
+            func = hide;
+        }
+
+        func("enum_editor_here");
+    };
+
+    this.compile = function() {
+        if (!this.active) return [];
+
+        var rows = dojo.mixin({}, this.normal_rows, this.alt_rows);
+        var subfields = [].concat(this.normal_subfields, this.alt_subfields);
+
+        return subfields.filter(
+            function(subfield) { return Boolean(rows[subfield]); }
+        ).reduce(
+            function(result, subfield) {
+                var fields = rows[subfield].fields;
+                var pairs = [subfield, fields.caption.value];
+
+                if (subfield != "a" && subfield != "g") {
+                    if (fields.units_per.value == "number") {
+                        if (fields.units_per_number.value) {
+                            pairs = pairs.concat([
+                                "u", fields.units_per_number.value,
+                                "v", fields.continuity.value
+                            ]);
+                        }
+                    } else {
+                        pairs = pairs.concat([
+                            "u", fields.units_per.value,
+                            "v", fields.continuity.value
+                        ]);
+                    }
+                }
+
+                return result.concat(pairs);
+            }, []
+        );
+    };
+
+    this._init.apply(this, arguments);
+}
+
+function Wizard() {
+    var self = this;
+
+    var _step_prefix = "wizard_step_";
+    var _step_regex = new RegExp("^" + _step_prefix + "(.+)$");
+
+    this._init = function(onsubmit) {
+        this._onsubmit = onsubmit;
+
+        this.load();
+        this.reset();
+    };
+
+    this.load = function() {
+        /* The Wizard object will handle simpler parts of the wizard (those
+         * parts with more-or-less static controls) itself, and will
+         * instantiate more specific objects to deal with more dynamic
+         * super-widgets (like the enum and chron editors).
+         */
+        this.steps = dojo.query("[id^='" + _step_prefix + "']").map(
+            function(o) {
+                return dojo.attr(o, "id").match(_step_regex)[1];
+            }
+        );
+
+        this.enum_editor = new EnumEditor();
+        this.chron_editor = new ChronEditor();
+        this.calendar_change_editor = new CalendarChangeEditor();
+
+        this.field_w = dojo.byId("hard_w");
+    };
+
+    this.reset = function() {
+        this.step = 0;
+        this.show_only_step(this.steps[0]);
+        this.step_bounds_check();
+    };
+
+    this.show_step = function(step) { show(_step_prefix + step); }
+    this.hide_step = function(step) { hide(_step_prefix + step); }
+
+    this.step_bounds_check = function() {
+        dojo.byId("wizard_previous_step").disabled = this.step < 1;
+        dojo.byId("wizard_next_step").disabled =
+            this.step >= this.steps.length -1;
+    };
+
+    this.show_only_step = function(to_keep) {
+        this.steps.forEach(
+            function(step) { if (step != to_keep) self.hide_step(step); }
+        );
+        this.show_step(to_keep);
+    };
+
+    this.previous_step = function() {
+        this.show_only_step(this.steps[--(this.step)]);
+        this.step_bounds_check();
+    };
+
+    /* Figure out the what step we're in, and proceed to the next */
+    this.next_step = function() {
+        this.show_only_step(this.steps[++(this.step)]);
+        this.step_bounds_check();
+    };
+
+    this.frequency_type_toggle = function(which) {
+        var other = which == "soft_w" ? "hard_w" : "soft_w";
+
+        dojo.byId(other).disabled = true;
+        dojo.byId(which).disabled = false;
+        dojo.byId(which).focus();
+
+        this.field_w = dojo.byId(which);
+    };
+
+    this.compile = function() {
+        var code = [
+            dojo.byId("ind1").value, dojo.byId("ind2").value,
+            "8", "1" /* TODO find out how to best deal with $8 */
+        ];
+
+        code = code.concat(this.enum_editor.compile());
+        code = code.concat(this.chron_editor.compile());
+
+        code = code.concat("w", this.field_w.value);
+
+        code = code.concat(this.calendar_change_editor.compile());
+
+        return code;
+    };
+
+    this.submit = function() {
+        this._onsubmit(js2JSON(this.compile()));
+        window.close();
+    };
+
+    this._init.apply(this, arguments);
+}
+
+function my_init() {
+    wizard = new Wizard(window.arguments[0]);
+}

Copied: branches/serials-integration/Open-ILS/xul/staff_client/server/serial/pattern_wizard.xul (from rev 17886, trunk/Open-ILS/xul/staff_client/server/serial/pattern_wizard.xul)
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/server/serial/pattern_wizard.xul	                        (rev 0)
+++ branches/serials-integration/Open-ILS/xul/staff_client/server/serial/pattern_wizard.xul	2010-10-18 13:46:56 UTC (rev 18371)
@@ -0,0 +1,32 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
+<?xml-stylesheet href="/xul/server/skin/global.css" type="text/css"?>
+<?xml-stylesheet href="/xul/server/skin/serial.css" type="text/css"?>
+<!DOCTYPE window PUBLIC "" ""[
+    <!--#include virtual="/opac/locale/${locale}/lang.dtd"-->
+]>
+<?xul-overlay href="/xul/server/OpenILS/util_overlay.xul"?>
+<?xul-overlay href="/xul/server/serial/pattern_wizard_overlay.xul"?>
+
+<window id="pattern_wizard_win"
+    onload="try{my_init();font_helper();persist_helper();}catch(E){alert(E);}"
+    xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+    <script type="text/javascript">
+        var myPackageDir = "open_ils_staff_client";
+        var IAMXUL = true;
+        var g = {};
+    </script>
+
+    <scripts id="openils_util_scripts" />
+
+    <!-- JSAN is still needed for font_helper stuff, but I'm going to try
+        not to use it otherwise.  -->
+    <script type="text/javascript" src="/xul/server/main/JSAN.js" />
+
+    <messagecatalog id="serialStrings"
+        src="/xul/server/locale/<!--#echo var='locale'-->/serial.properties" />
+
+    <commandset />
+    <box id="pattern_wizard_main" />
+</window>

Copied: branches/serials-integration/Open-ILS/xul/staff_client/server/serial/pattern_wizard_overlay.xul (from rev 17886, trunk/Open-ILS/xul/staff_client/server/serial/pattern_wizard_overlay.xul)
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/server/serial/pattern_wizard_overlay.xul	                        (rev 0)
+++ branches/serials-integration/Open-ILS/xul/staff_client/server/serial/pattern_wizard_overlay.xul	2010-10-18 13:46:56 UTC (rev 18371)
@@ -0,0 +1,289 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE overlay PUBLIC "" ""[
+    <!--#include virtual="/opac/locale/${locale}/lang.dtd"-->
+]>
+<overlay id="pattern_wizard_overlay"
+    xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+    <script type="text/javascript" src="/xul/server/serial/common.js" />
+    <script type="text/javascript" src="/xul/server/serial/pattern_wizard.js" />
+
+    <box orient="vertical" id="pattern_wizard_main" flex="1">
+        <caption class="top" label="Pattern Code Wizard" />
+        <vbox flex="1">
+            <hbox align="center" class="padded_bottom">
+                <button id="wizard_previous_step" disabled="true"
+                    icon="go-back" label="Previous"
+                    oncommand="wizard.previous_step();" />
+                <spacer flex="1" />
+                <button id="wizard_next_step" disabled="true"
+                    icon="go-forward" label="Next"
+                    oncommand="wizard.next_step();" />
+            </hbox>
+            <vbox id="wizard_step_captions" class="hideme">
+                <checkbox id="use_enum"
+                    oncommand="wizard.enum_editor.toggle(event);"
+                    label="Use enumerations?" />
+                <vbox id="enum_editor_here" class="hideme">
+                    <description class="step">
+                        "v." and "no." are common first and second level
+                        enumeration captions.
+                    </description>
+                    <grid flex="1">
+                        <columns>
+                            <column />
+                            <column />
+                            <column />
+                            <column />
+                        </columns>
+                        <rows>
+                            <row id="enum_row_headings">
+                                <label value="Enumeration Caption" />
+                                <label value="Units Per Higher Level" />
+                                <label value="Numbering Continuity" />
+                                <label />
+                            </row>
+                            <row id="enum_row_template" align="top">
+                                <vbox>
+                                    <label name="caption_label" />
+                                    <hbox>
+                                        <spacer flex="1" />
+                                        <textbox size="6" name="caption" />
+                                    </hbox>
+                                </vbox>
+                                <radiogroup name="units_per">
+                                    <hbox align="center">
+                                        <radio label="Number" value="number" />
+                                        <textbox name="units_per_number"
+                                            size="6" />
+                                    </hbox>
+                                    <radio label="Varies" value="var" />
+                                    <radio label="Undetermined" value="und" />
+                                </radiogroup>
+                                <menulist name="continuity">
+                                    <menupopup>
+                                        <menuitem value="c" label="Increments continuously" />
+                                        <menuitem value="r" label="Restarts at unit completion" />
+                                    </menupopup>
+                                </menulist>
+                                <button icon="remove" name="remover" label="Remove" />
+                            </row>
+                        </rows>
+                    </grid>
+                    <hbox>
+                        <spacer flex="1" />
+                        <button id="enum_add_normal_row"
+                            icon="add"
+                            label="Add Enumeration" accesskey="E"
+                            oncommand="wizard.enum_editor.add_normal_row();"
+                            />
+                        <spacer flex="1" />
+                        <button id="enum_add_alt_row"
+                            icon="add"
+                            label="Add Alternate Enumeration" accesskey="A"
+                            oncommand="wizard.enum_editor.add_alt_row();"
+                            />
+                        <spacer flex="1" />
+                    </hbox>
+                </vbox>
+            </vbox>
+            <vbox id="wizard_step_calendar_change" class="hideme">
+                <checkbox id="use_calendar_change"
+                    disabled="true"
+                    oncommand="wizard.calendar_change_editor.toggle(event);"
+                    label="Use calendar changes?" />
+                <vbox id="calendar_change_editor_here" class="hideme">
+                    <description class="step">
+                        Identify any points during the year at which the
+                        highest level enumeration caption changes.
+                    </description>
+                    <grid>
+                        <columns>
+                            <column />
+                            <column flex="1" />
+                            <column />
+                        </columns>
+                        <rows>
+                            <row id="calendar_change_row_headings">
+                                <label value="Type" />
+                                <label value="Point" />
+                                <label />
+                            </row>
+                            <row id="calendar_row_template">
+                                <menulist name="type">
+                                    <menupopup>
+                                        <menuitem value="month" label="At start of a month" />
+                                        <menuitem value="season" label="At start of a season" />
+                                        <menuitem value="date" label="On a date" />
+                                    </menupopup>
+                                </menulist>
+                                <hbox align="center">
+                                    <menulist name="month">
+                                        <menupopup>
+                                        </menupopup>
+                                    </menulist>
+                                    <menulist name="season" class="hideme">
+                                        <menupopup>
+                                            <menuitem value="21" label="Spring" />
+                                            <menuitem value="22" label="Summer" />
+                                            <menuitem value="23" label="Autumn" />
+                                            <menuitem value="24" label="Winter" />
+                                        </menupopup>
+                                    </menulist>
+                                    <hbox name="date" class="hideme">
+                                        <menulist name="date_month">
+                                            <menupopup>
+                                            </menupopup>
+                                        </menulist>
+                                        <textbox name="date_day" size="3" />
+                                    </hbox>
+                                </hbox>
+                                <button icon="remove" name="remover" label="Remove" />
+                            </row>
+                        </rows>
+                    </grid>
+                    <hbox pack="center">
+                        <button
+                            id="calendar_change_add_row"
+                            label="Add Calendar Change"
+                            accesskey="C"
+                            oncommand="wizard.calendar_change_editor.add_row();" />
+                    </hbox>
+                </vbox>
+            </vbox>
+            <vbox id="wizard_step_chronology" class="hideme">
+                <checkbox id="use_chron"
+                    oncommand="wizard.chron_editor.toggle(event);"
+                    label="Use chronology captions?" />
+                <vbox id="chron_editor_here" class="hideme">
+                    <description class="step">
+                        Each caption must be a smaller unit of
+                        time than the preceding caption.<!-- XXX TODO enforce -->
+                    </description>
+                    <grid>
+                        <columns>
+                            <column />
+                            <column />
+                            <column flex="1" />
+                            <column />
+                        </columns>
+                        <rows>
+                            <row id="chron_row_headings">
+                                <label />
+                                <label value="Caption" />
+                                <label value="Display in holding field?" />
+                                <label />
+                            </row>
+                            <row id="chron_row_template">
+                                <label name="caption_label" />
+                                <menulist name="caption">
+                                    <menupopup>
+                                        <menuitem label="Year" value="year" />
+                                        <menuitem label="Season" value="season" />
+                                        <menuitem label="Month" value="month" />
+                                        <menuitem label="Week" value="week" />
+                                        <menuitem label="Day" value="day" />
+                                        <menuitem label="Hour" value="hour" />
+                                    </menupopup>
+                                </menulist>
+                                <checkbox name="display_in_holding" />
+                                <button icon="remove" name="remover" label="Remove" />
+                            </row>
+                        </rows>
+                    </grid>
+                    <hbox pack="center">
+                        <button
+                            id="chron_add_row"
+                            label="Add Chronology Caption"
+                            accesskey="C"
+                            oncommand="wizard.chron_editor.add_row();" />
+                    </hbox>
+                </vbox>
+            </vbox>
+            <vbox id="wizard_step_basics" class="hideme">
+                <grid class="padded_bottom">
+                    <columns>
+                        <column />
+                        <column />
+                    </columns>
+                    <rows><!-- TODO hide these inputs if we're doing an 855 -->
+                        <row align="center">
+                            <label align="right" value="Compressibility and Expandability:" />
+                            <menulist id="ind1">
+                                <menupopup>
+                                    <menuitem value="0" label="Cannot compress or expand" />
+                                    <menuitem value="1" label="Can compress but not expand" />
+                                    <menuitem value="2" label="Can compress or expand" />
+                                    <menuitem value="3" label="Unknown" />
+                                </menupopup>
+                            </menulist>
+                        </row>
+                        <row align="center">
+                            <label align="right" value="Caption Evaluation:" />
+                            <menulist id="ind2">
+                                <menupopup>
+                                    <menuitem value="0" label="Captions verified; all levels present" />
+                                    <menuitem value="1" label="Captions verified; all levels may not be present" />
+                                    <menuitem value="2" label="Captions unverified; all levels present" />
+                                    <menuitem value="3" label="Captions unverified; all levels may not be present" />
+                                </menupopup>
+                            </menulist>
+                        </row>
+                    </rows>
+                </grid>
+                <radiogroup
+                    oncommand="wizard.frequency_type_toggle(this.value);">
+                    <grid>
+                        <columns><column /><column /></columns>
+                        <rows>
+                            <row>
+                                <radio
+                                    label="Select frequency:"
+                                    accesskey="F" selected="true"
+                                    value="hard_w" />
+                                <menulist id="hard_w">
+                                    <menupopup>
+                                        <menuitem label="Annual" value="a" />
+                                        <menuitem label="Bimonthly" value="b" />
+                                        <menuitem label="Semiweekly" value="c" />
+                                        <menuitem label="Daily" value="d" />
+                                        <menuitem label="Biweekly" value="e" />
+                                        <menuitem label="Semiannual" value="f" />
+                                        <menuitem label="Biennial" value="g" />
+                                        <menuitem label="Triennial" value="h" />
+                                        <menuitem label="Three times a week" value="i" />
+                                        <menuitem label="Three times a month" value="j" />
+                                        <menuitem label="Continuously updated" value="k" />
+                                        <menuitem label="Monthly" value="m" />
+                                        <menuitem label="Quarterly" value="q" />
+                                        <menuitem label="Semimonthly" value="s" />
+                                        <menuitem label="Three times a year" value="t" />
+                                        <menuitem label="Weekly" value="w" />
+                                        <menuitem label="Completely irregular" value="x" />
+                                    </menupopup>
+                                </menulist>
+                            </row>
+                            <row>
+                                <radio
+                                    label="Use number of issues per year:"
+                                    value="soft_w"
+                                    selected="false" accesskey="I" />
+                                <textbox id="soft_w" disabled="true" />
+                            </row>
+                        </rows>
+                    </grid>
+                </radiogroup>
+            </vbox>
+            <vbox id="wizard_step_submit" class="hideme">
+                <description class="step">
+                    Are you ready to create a pattern code from your
+                    selections in this wizard?
+                </description>
+                <hbox pack="center">
+                    <button oncommand="wizard.submit();" icon="accept"
+                        accesskey="P" label="Create Pattern Code" />
+                </hbox>
+            </vbox>
+        </vbox>
+    </box>
+</overlay>

Modified: branches/serials-integration/Open-ILS/xul/staff_client/server/serial/scap_editor.js
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/server/serial/scap_editor.js	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/xul/staff_client/server/serial/scap_editor.js	2010-10-18 13:46:56 UTC (rev 18371)
@@ -2,6 +2,7 @@
 // vim:noet:sw=4:ts=4:
 
 JSAN.use('serial.editor_base');
+var pattern_code_key = 'Pattern Code (temporary)';
 
 if (typeof serial == 'undefined') serial = {};
 serial.scap_editor = function (params) {
@@ -98,7 +99,7 @@
                 }
             ],
             [
-                'Pattern Code (temporary)',
+                pattern_code_key,
                 { 
                     render: 'fm.pattern_code() == null ? "" : fm.pattern_code();',
                     input: 'c = function(v){ obj.apply("pattern_code",v); if (typeof post_c == "function") post_c(v); }; x = document.createElement("textbox"); x.setAttribute("value",obj.editor_values.pattern_code); x.addEventListener("apply",function(f){ return function(ev) { f(ev.target.value); } }(c), false);',
@@ -132,6 +133,24 @@
         obj.editor_base_save('open-ils.serial.caption_and_pattern.batch.update');
     },
 
+    /* Pattern/caption wizard */
+    "pattern_wizard": function() {
+        var obj = this;
+
+        var onsubmit = function(value) {
+            obj.apply("pattern_code", value);
+            obj.summarize(obj.scaps);
+            obj.render();
+        };
+        netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+        window.openDialog(
+            xulG.url_prefix("/xul/server/serial/pattern_wizard.xul"),
+            "pattern_wizard",
+            "scrollbars=yes", /* XXX FIXME: scrollbars aren't working. what to do? */
+            onsubmit
+        );
+    },
+
     /******************************************************************************************************/
     'save_attributes' : serial.editor_base.editor_base_save_attributes
 };

Modified: branches/serials-integration/Open-ILS/xul/staff_client/server/serial/scap_editor.xul
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/server/serial/scap_editor.xul	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/xul/staff_client/server/serial/scap_editor.xul	2010-10-18 13:46:56 UTC (rev 18371)
@@ -22,6 +22,7 @@
 
 		<hbox id="scap_editor_nav">
 			<spacer flex="1"/>
+			<button id="scap_pattern_wizard" label="&staff.serial.scap_editor.pattern_wizard;" accesskey="&staff.serial.scap_editor.pattern_wizard.accesskey;" oncommand="g.manage_subs.scap_editor.pattern_wizard();" />
 			<button id="scap_save" label="&staff.serial.scap_editor.modify;" hidden="true" accesskey="&staff.serial.scap_editor.modify.accesskey;" oncommand="g.manage_subs.scap_editor.save()" />
 			<!--<button id="cancel" label="&staff.cat.copy_editor.cancel.label;" accesskey="&staff.cat.copy_editor.cancel.accesskey;" oncommand="window.close();"/>-->
 		</hbox>

Modified: branches/serials-integration/Open-ILS/xul/staff_client/server/skin/cat.css
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/server/skin/cat.css	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/xul/staff_client/server/skin/cat.css	2010-10-18 13:46:56 UTC (rev 18371)
@@ -3,7 +3,7 @@
 @namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"); 
 @namespace html url("http://www.w3.org/TR/REC-html40"); 
 
-.has_copies { color: black; background-color: lightgreen; font-weight: bold; }
+.has_copies { border-left: solid thick green; font-weight: bold; }
 
 .copy_editor_field_changed { background: lightgreen; }
 .copy_editor_field_required { border: solid thin red; }

Modified: branches/serials-integration/Open-ILS/xul/staff_client/server/skin/global.css
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/server/skin/global.css	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/Open-ILS/xul/staff_client/server/skin/global.css	2010-10-18 13:46:56 UTC (rev 18371)
@@ -7,6 +7,8 @@
 messagecatalog { -moz-binding: url('/xul/server/main/bindings.xml#messagecatalog'); }
 .shrinkable_groupbox { font-weight: bold; -moz-binding: url('/xul/server/main/bindings.xml#caption'); }
 
+window:not([active="true"]) menubar > menu { color: menutext !important }
+
 treechildren::-moz-tree-checkbox(checked) {
     /* css for checked cells */
     list-style-image: url("chrome://global/skin/checkbox/cbox-check.gif");
@@ -100,6 +102,7 @@
 
 .header { font-weight: bold; }
 .header1 { font-weight: bold; font-size: large; }
+.emphasis { font-weight: bold; }
 
 .tan { background-color: #D2B48C; }
 .sandy_brown { background-color: #F4A460; }

Copied: branches/serials-integration/Open-ILS/xul/staff_client/server/skin/serial.css (from rev 17886, trunk/Open-ILS/xul/staff_client/server/skin/serial.css)
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/server/skin/serial.css	                        (rev 0)
+++ branches/serials-integration/Open-ILS/xul/staff_client/server/skin/serial.css	2010-10-18 13:46:56 UTC (rev 18371)
@@ -0,0 +1,22 @@
+ at namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
+caption.top {
+    background-color: #00246b;
+    color: #ff6308;
+    font-size: 200%;
+    text-align: center;
+}
+label.receiving { width: 20em; text-align: right; }
+.hideme { display: none; }
+#batch_receive_entry { padding-top: 10px; }
+#entry_submitter { padding: 20px 0; }
+menulist.cn { width: 12em; }
+button[icon="remove"] { min-width: 2.5em; }
+#enum_row_headings label { font-weight: bold; }
+#chron_row_headings label { font-weight: bold; }
+#calendar_change_row_headings label { font-weight: bold; }
+description.step { font-style: italic; font-size: 110%; }
+checkbox:focus:not([label]) .checkbox-label-box {
+    -moz-appearance: none;
+    border: none;
+}
+.padded_bottom { padding-bottom: 10px; }

Copied: branches/serials-integration/Open-ILS/xul/staff_client/update.rdf (from rev 17886, trunk/Open-ILS/xul/staff_client/update.rdf)
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/update.rdf	                        (rev 0)
+++ branches/serials-integration/Open-ILS/xul/staff_client/update.rdf	2010-10-18 13:46:56 UTC (rev 18371)
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<RDF:RDF xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+         xmlns:em="http://www.mozilla.org/2004/em-rdf#">
+
+  <RDF:Description about="urn:mozilla:extension:staff-client at open-ils.org">
+    <em:updates>
+      <RDF:Seq>
+        <RDF:li>
+          <RDF:Description>
+            <em:version>1.6</em:version>
+            <em:targetApplication>
+              <RDF:Description>
+                <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
+                <em:minVersion>3.5</em:minVersion>
+                <em:maxVersion>3.6.*</em:maxVersion>
+                <em:updateLink>https://::HOSTNAME::/updates/extension.xpi</em:updateLink>
+                <em:updateInfoURL>http://::HOSTNAME::/updates/updatedetails.html</em:updateInfoURL>
+                <em:updateHash></em:updateHash>
+              </RDF:Description>
+            </em:targetApplication>
+          </RDF:Description>
+        </RDF:li>
+      </RDF:Seq>
+    </em:updates>
+  </RDF:Description>
+</RDF:RDF>

Copied: branches/serials-integration/Open-ILS/xul/staff_client/windowssetup.nsi (from rev 17886, trunk/Open-ILS/xul/staff_client/windowssetup.nsi)
===================================================================
--- branches/serials-integration/Open-ILS/xul/staff_client/windowssetup.nsi	                        (rev 0)
+++ branches/serials-integration/Open-ILS/xul/staff_client/windowssetup.nsi	2010-10-18 13:46:56 UTC (rev 18371)
@@ -0,0 +1,212 @@
+; Script generated by the HM NIS Edit Script Wizard.
+
+; HM NIS Edit Wizard helper defines
+!define PRODUCT_NAME "Evergreen Staff Client Trunk"
+; Old versions of makensis don't like this, moved to Makefile
+;!define /file PRODUCT_VERSION "client/VERSION"
+!define PRODUCT_PUBLISHER "Evergreen Community"
+!define PRODUCT_WEB_SITE "http://evergreen-ils.org/"
+!define PRODUCT_DIR_REGKEY "Software\Microsoft\Windows\CurrentVersion\App Paths\evergreen.exe"
+!define PRODUCT_UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}"
+!define PRODUCT_UNINST_ROOT_KEY "HKLM"
+!define PRODUCT_STARTMENU_REGVAL "NSIS:StartMenuDir"
+
+; MUI 1.67 compatible ------
+!include "MUI.nsh"
+
+; File Functions
+!include "FileFunc.nsh"
+
+; MUI Settings
+!define MUI_ABORTWARNING
+!define MUI_ICON "${NSISDIR}\Contrib\Graphics\Icons\modern-install.ico"
+!define MUI_UNICON "${NSISDIR}\Contrib\Graphics\Icons\modern-uninstall.ico"
+
+; Language Selection Dialog Settings
+!define MUI_LANGDLL_REGISTRY_ROOT "${PRODUCT_UNINST_ROOT_KEY}"
+!define MUI_LANGDLL_REGISTRY_KEY "${PRODUCT_UNINST_KEY}"
+!define MUI_LANGDLL_REGISTRY_VALUENAME "NSIS:Language"
+
+; Welcome page
+!insertmacro MUI_PAGE_WELCOME
+; License page
+!insertmacro MUI_PAGE_LICENSE "..\..\..\LICENSE.txt"
+; Components page
+!ifdef AUTOUPDATE | DEVELOPER
+!insertmacro MUI_PAGE_COMPONENTS
+!endif
+; Directory page
+!insertmacro MUI_PAGE_DIRECTORY
+; Start menu page
+var ICONS_GROUP
+!define MUI_STARTMENUPAGE_NODISABLE
+!define MUI_STARTMENUPAGE_DEFAULTFOLDER "Evergreen Staff Client Trunk"
+!define MUI_STARTMENUPAGE_REGISTRY_ROOT "${PRODUCT_UNINST_ROOT_KEY}"
+!define MUI_STARTMENUPAGE_REGISTRY_KEY "${PRODUCT_UNINST_KEY}"
+!define MUI_STARTMENUPAGE_REGISTRY_VALUENAME "${PRODUCT_STARTMENU_REGVAL}"
+!insertmacro MUI_PAGE_STARTMENU Application $ICONS_GROUP
+; Instfiles page
+!insertmacro MUI_PAGE_INSTFILES
+; Finish page
+!define MUI_FINISHPAGE_RUN "$INSTDIR\evergreen.exe"
+!insertmacro MUI_PAGE_FINISH
+
+; Uninstaller pages
+!insertmacro MUI_UNPAGE_INSTFILES
+
+; Language files
+!insertmacro MUI_LANGUAGE "Czech"
+!insertmacro MUI_LANGUAGE "English"
+!insertmacro MUI_LANGUAGE "French"
+
+; MUI end ------
+
+Name "${PRODUCT_NAME} ${PRODUCT_VERSION}"
+OutFile "evergreen_staff_client_setup.exe"
+InstallDir "$PROGRAMFILES\Evergreen Staff Client Trunk"
+InstallDirRegKey HKLM "${PRODUCT_DIR_REGKEY}" ""
+ShowInstDetails show
+ShowUnInstDetails show
+RequestExecutionLevel admin
+
+Section "Staff Client" SECMAIN
+  SetOutPath "$INSTDIR"
+  File /r /x "autoupdate.js" /x "autochannel.js" /x "developers.js" "client\*"
+
+; Shortcuts
+  !insertmacro MUI_STARTMENU_WRITE_BEGIN Application
+  CreateDirectory "$SMPROGRAMS\$ICONS_GROUP"
+  !ifdef WICON
+  CreateShortCut "$SMPROGRAMS\$ICONS_GROUP\Evergreen Staff Client.lnk" "$INSTDIR\evergreen.exe" "" "$INSTDIR\evergreen.ico"
+  !ifdef PROFILES
+  CreateShortCut "$SMPROGRAMS\$ICONS_GROUP\Evergreen Staff Client Profile Manager.lnk" "$INSTRDIR\evergreen.exe -profilemanager" "" "$INSTDIR\evergreen.ico"
+  !endif
+  !else
+  CreateShortCut "$SMPROGRAMS\$ICONS_GROUP\Evergreen Staff Client.lnk" "$INSTDIR\evergreen.exe"
+  !ifdef PROFILES
+  CreateShortCut "$SMPROGRAMS\$ICONS_GROUP\Evergreen Staff Client Profile Manager.lnk" "$INSTRDIR\evergreen.exe -profilemanager"
+  !endif
+  !endif
+  CreateShortCut "$DESKTOP\Evergreen Staff Client Trunk.lnk" "$INSTDIR\evergreen.exe"
+  !insertmacro MUI_STARTMENU_WRITE_END
+SectionEnd
+
+!ifdef AUTOUPDATE
+Section /o "Automatic Update" SECAUTO
+  SetOutPath "$INSTDIR\defaults\preferences"
+  File "client\defaults\preferences\autoupdate.js"
+  File "client\defaults\preferences\autochannel.js"
+  SetOutPath "$INSTDIR"
+SectionEnd
+!endif
+
+!ifdef DEVELOPER
+Section /o "Developer Options" SECDEV
+  SetOutPath "$INSTDIR\defaults\preferences"
+  File "client\defaults\preferences\developers.js"
+  SetOutPath "$INSTDIR"
+SectionEnd
+!endif
+
+
+Function .onInit
+  !insertmacro MUI_LANGDLL_DISPLAY
+  SectionSetFlags ${SECMAIN} 17
+  ; This is mainly for silent installs
+  !ifdef AUTOUPDATE | DEVELOPER
+    Var /GLOBAL CMD_ARGS
+    StrCpy $CMD_ARGS ""
+    ${GetParameters} $CMD_ARGS
+    !ifdef AUTOUPDATE
+      !ifdef AUTOUPDATE_NODEFAULT
+        ${GetOptions} $CMD_ARGS "/autoupdate" $0
+        IfErrors +2 0
+      !else
+        ${GetOptions} $CMD_ARGS "/noautoupdate" $0
+        IfErrors 0 +2
+      !endif
+      SectionSetFlags ${SECAUTO} 1
+    !endif
+    !ifdef DEVELOPER
+      ${GetOptions} $CMD_ARGS "/developer" $0
+      IfErrors +2 0
+      SectionSetFlags ${SECDEV} 1
+    !endif
+  !endif
+FunctionEnd
+
+Section -AdditionalIcons
+  !insertmacro MUI_STARTMENU_WRITE_BEGIN Application
+  WriteIniStr "$INSTDIR\${PRODUCT_NAME}.url" "InternetShortcut" "URL" "${PRODUCT_WEB_SITE}"
+  CreateShortCut "$SMPROGRAMS\$ICONS_GROUP\Website.lnk" "$INSTDIR\${PRODUCT_NAME}.url"
+  CreateShortCut "$SMPROGRAMS\$ICONS_GROUP\Uninstall.lnk" "$INSTDIR\uninst.exe"
+  !insertmacro MUI_STARTMENU_WRITE_END
+SectionEnd
+
+Section -Post
+  WriteUninstaller "$INSTDIR\uninst.exe"
+  WriteRegStr HKLM "${PRODUCT_DIR_REGKEY}" "" "$INSTDIR\evergreen.exe"
+  WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayName" "$(^Name)"
+  WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "UninstallString" "$INSTDIR\uninst.exe"
+  WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayIcon" "$INSTDIR\evergreen.exe"
+  WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayVersion" "${PRODUCT_VERSION}"
+  WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "URLInfoAbout" "${PRODUCT_WEB_SITE}"
+  WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "Publisher" "${PRODUCT_PUBLISHER}"
+SectionEnd
+
+; Section descriptions
+!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN
+  !insertmacro MUI_DESCRIPTION_TEXT ${SECMAIN} "The Evergreen Staff Client with XULRunner, Required"
+  !ifdef AUTOUPDATE
+  !insertmacro MUI_DESCRIPTION_TEXT ${SECAUTO} "Automatic Update Functionality"
+  !endif
+  !ifdef DEVELOPER
+  !insertmacro MUI_DESCRIPTION_TEXT ${SECDEV}  "Developer Options"
+  !endif
+!insertmacro MUI_FUNCTION_DESCRIPTION_END
+
+
+Function un.onUninstSuccess
+  HideWindow
+  MessageBox MB_ICONINFORMATION|MB_OK "$(^Name) was successfully removed from your computer."
+FunctionEnd
+
+Function un.onInit
+!insertmacro MUI_UNGETLANGUAGE
+  MessageBox MB_ICONQUESTION|MB_YESNO|MB_DEFBUTTON2 "Are you sure you want to completely remove $(^Name) and all of its components?" IDYES +2
+  Abort
+FunctionEnd
+
+Section Uninstall
+  !insertmacro MUI_STARTMENU_GETFOLDER "Application" $ICONS_GROUP
+  Delete "$INSTDIR\${PRODUCT_NAME}.url"
+  Delete "$INSTDIR\uninst.exe"
+  Delete "$INSTDIR\evergreen.exe"
+  Delete "$INSTDIR\application.ini"
+  Delete "$INSTDIR\BUILD_ID"
+  Delete "$INSTDIR\STAMP_ID"
+  Delete "$INSTDIR\VERSION"
+  Delete "$INSTDIR\install.rdf"
+  Delete "$INSTDIR\active-update.xml"
+  Delete "$INSTDIR\chrome.manifest"
+  Delete "$INSTDIR\updates.xml"
+  Delete "$INSTDIR\log.txt"
+
+  Delete "$SMPROGRAMS\$ICONS_GROUP\Uninstall.lnk"
+  Delete "$SMPROGRAMS\$ICONS_GROUP\Website.lnk"
+  Delete "$DESKTOP\Evergreen Staff Client Trunk.lnk"
+  Delete "$SMPROGRAMS\$ICONS_GROUP\Evergreen Staff Client.lnk"
+
+  RMDir "$SMPROGRAMS\$ICONS_GROUP"
+  RMDir /r "$INSTDIR\updates"
+  RMDir /r "$INSTDIR\xulrunner"
+  RMDir /r "$INSTDIR\extensions"
+  RMDir /r "$INSTDIR\chrome"
+  RMDir /r "$INSTDIR\components"
+  RMDir /r "$INSTDIR\defaults"
+  RMDir "$INSTDIR"
+
+  DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}"
+  DeleteRegKey HKLM "${PRODUCT_DIR_REGKEY}"
+  SetAutoClose true
+SectionEnd

Modified: branches/serials-integration/README
===================================================================
--- branches/serials-integration/README	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/README	2010-10-18 13:46:56 UTC (rev 18371)
@@ -43,11 +43,11 @@
 Once you have configured and compiled Evergreen, issue the following
 command as the root user to install Evergreen:
 
-make STAFF_CLIENT_BUILD_ID=rel_trunk install
+make STAFF_CLIENT_STAMP_ID=rel_trunk install
 
 This will install Evergreen, including example configuration files in
 /openils/conf/ that you can use as templates for your own configuration files.
-The STAFF_CLIENT_BUILD_ID variable stamps the server-side and client-side files
+The STAFF_CLIENT_STAMP_ID variable stamps the server-side and client-side files
 for the staff client to ensure that they match.
 
 Install Dojo Toolkit:
@@ -125,7 +125,7 @@
 commands, we assume that you are working with PostgreSQL 8.4 on a Debian-based
 system:
 
-createdb -E UNICODE evergreen
+createdb --template template0 --encoding UNICODE evergreen
 createlang plperl evergreen
 createlang plperlu evergreen
 createlang plpgsql evergreen
@@ -147,7 +147,7 @@
 with the appropriate values for your PostgreSQL database:
 
 perl Open-ILS/src/support-scripts/eg_db_config.pl --update-config \
-       --service all --create-schema --create-bootstrap --create-offline \
+       --service all --create-schema --create-offline \
        --user <user> --password <password> --hostname <hostname> --port <port> \
        --database <dbname>
 

Copied: branches/serials-integration/build/i18n/po/opac.js/opac.js.pot (from rev 17886, trunk/build/i18n/po/opac.js/opac.js.pot)
===================================================================
--- branches/serials-integration/build/i18n/po/opac.js/opac.js.pot	                        (rev 0)
+++ branches/serials-integration/build/i18n/po/opac.js/opac.js.pot	2010-10-18 13:46:56 UTC (rev 18371)
@@ -0,0 +1,148 @@
+# 
+msgid ""
+msgstr ""
+"Project-Id-Version: Evergreen 1.4\n"
+"Report-Msgid-Bugs-To: open-ils-dev at list.georgialibraries.org\n"
+"POT-Creation-Date: 2010-09-01 22:23:40-0400\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL at ADDRESS>\n"
+"Language-Team: LANGUAGE <LL at li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8-bit\n"
+
+#: opac.js:PWD_RESET_SUBMIT_PROMPT
+msgid "To begin the password reset process, enter either your barcode or user name in the form below and click 'Submit'"
+msgstr ""
+
+#: opac.js:PWD_RESET_FORM_TITLE
+msgid "Request password reset"
+msgstr ""
+
+#: opac.js:PWD_RESET_RESPONSE_TITLE
+msgid "Password reset response"
+msgstr ""
+
+#: opac.js:SUBMIT_BUTTON_LABEL
+msgid "Submit"
+msgstr ""
+
+#: opac.js:CREATED_MFHD_RECORD
+msgid "Created MFHD record for ${0}"
+msgstr ""
+
+#: opac.js:BARCODE_PROMPT
+msgid "Barcode: "
+msgstr ""
+
+#: opac.js:SUPPLEMENT_HOLDINGS_ADD
+msgid "Additional Supplement Information"
+msgstr ""
+
+#: opac.js:DELETED_MFHD_RECORD
+msgid "Deleted MFHD record ${0}"
+msgstr ""
+
+#: opac.js:SAVE_MFHD_LABEL
+msgid "Save MFHD"
+msgstr ""
+
+#: opac.js:EDIT_PROPERTIES
+msgid "Edit Propeties"
+msgstr ""
+
+#: opac.js:PWD_RESET_SUBMIT_ERROR
+msgid "The system could not process your request for a password reset. Please try again, or contact circulation staff for assistance."
+msgstr ""
+
+#: opac.js:EDIT_MFHD_RECORD
+msgid "Edit Record"
+msgstr ""
+
+#: opac.js:PWD_RESET_FORGOT_PROMPT
+msgid "Forgot your password?"
+msgstr ""
+
+#: opac.js:INDEX_HOLDINGS_ADD
+msgid "Additional Index Information"
+msgstr ""
+
+#: opac.js:INCOMPLETE_VOLUMES
+msgid "Incomplete volumes"
+msgstr ""
+
+#: opac.js:CURRENT_HOLDINGS
+msgid "Current volume"
+msgstr ""
+
+#: opac.js:MISSING_VOLUMES
+msgid "Missing volumes"
+msgstr ""
+
+#: opac.js:BASIC_HOLDINGS_ADD
+msgid "Additional Volume Information"
+msgstr ""
+
+#: opac.js:EDIT_MFHD_MENU
+msgid "Edit Holdings"
+msgstr ""
+
+#: opac.js:SUPPLEMENT_HOLDINGS
+msgid "Supplements"
+msgstr ""
+
+#: opac.js:BASIC_HOLDINGS
+msgid "Volumes"
+msgstr ""
+
+#: opac.js:HOLDINGS_TABLE_CAPTION
+msgid "Holdings summary (${0})"
+msgstr ""
+
+#: opac.js:OK
+msgid "OK"
+msgstr ""
+
+#: opac.js:INDEX_HOLDINGS
+msgid "Indexes"
+msgstr ""
+
+#: opac.js:CURRENT_SUPPLEMENTS
+msgid "Current supplements"
+msgstr ""
+
+#: opac.js:CURRENT_INDEXES
+msgid "Current indexes"
+msgstr ""
+
+#: opac.js:DELETE_MFHD
+msgid "Delete Record"
+msgstr ""
+
+#: opac.js:CREATE_MFHD
+msgid "Add MFHD Record"
+msgstr ""
+
+#: opac.js:USERNAME_PROMPT
+msgid "User name: "
+msgstr ""
+
+#: opac.js:DELETE_MFHD_CONFIRM
+msgid "Are you sure you want to delete this serial record?"
+msgstr ""
+
+#: opac.js:PWD_RESET_SUBMIT_SUCCESS
+msgid "Your request to begin the password reset process has been processed. If your account has a valid email address, you should soon receive an email containing further instructions for resetting your password."
+msgstr ""
+
+#: opac.js:CANCEL_BUTTON_LABEL
+msgid "Cancel"
+msgstr ""
+
+#: opac.js:PWD_RESET_SUBMIT_STATUS
+msgid "Sending request..."
+msgstr ""
+
+#: opac.js:ONLINE_VOLUMES
+msgid "Online volumes"
+msgstr ""

Modified: branches/serials-integration/build/tools/update.sh
===================================================================
--- branches/serials-integration/build/tools/update.sh	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/build/tools/update.sh	2010-10-18 13:46:56 UTC (rev 18371)
@@ -153,11 +153,14 @@
 fi
 sudo chown -R opensrf:opensrf $INSTALL
 
-BID=$(date +"%Y-%m-%dT%H:%M:%S");   # or "current"
-cd $ILS && sudo make install STAFF_CLIENT_BUILD_ID=$BID;
+BIDDATE=$(date +"%Y-%m-%dT%H:%M:%S");
+BID=${STAFF_CLIENT_BUILD_ID:-$BIDDATE};   # or "current"
+
+rm -f "$XUL/current" || rm -rf "$XUL/current";      # removing the old link/build
+cd $ILS && sudo make install STAFF_CLIENT_STAMP_ID=$BID STAFF_CLIENT_BUILD_ID=$BID;
 sudo chown -R opensrf:opensrf $INSTALL
 
-[ -d "$XUL/$BID" ] || die_msg "New build directory $XUL/$BID was not created.  sudo make install failed?"
+[ -d "$XUL/$BID" ] || die_msg "New build directory $XUL/$BID was not created.  sudo make install failed?";
 
 if [ -z "$OPT_VERBOSE" ] ; then
     exec 1>&3   # Restore STDOUT
@@ -168,12 +171,25 @@
 rm -f $XUL/current-client-build.zip;
 cp -r "$ILS/Open-ILS/xul/staff_client/build" ./
 zip -rq current-client-build.zip build;
-cat ./build/BUILD_ID
+echo -n "BUILD_ID: ";
+cat ./build/BUILD_ID;
+echo -n "STAMP_ID: ";
+cat ./build/STAMP_ID;
+echo -n " VERSION: ";
+cat ./build/VERSION;
 rm -rf ./build;
 
+echo "build ID is '$BID'";
 
+if [ "$BID" != "$BIDDDATE" ] ; then
+    mv $BID $BIDDATE;    # Move the non-timestamp directory to timestamp-based spot
+    ln -s $BIDDATE $BID; # link back to it
+fi
+
 rm -f current;      # removing the link to the old build
-ln -s $BID current; # linking "current" to the new build
+ln -s $BIDDATE current; # linking "current" to the new build
+
+rm -f server;
 ln -s current/server server;
     
 

Modified: branches/serials-integration/configure.ac
===================================================================
--- branches/serials-integration/configure.ac	2010-10-16 15:51:19 UTC (rev 18370)
+++ branches/serials-integration/configure.ac	2010-10-18 13:46:56 UTC (rev 18371)
@@ -52,6 +52,7 @@
 #    yes) openils_all=true;
 #	 openils_core=true;
 #	 openils_web=true;
+#	 openils_updates=true;
 #	 openils_reporter=true;
 #	 openils_client_xul=true;
 #	 openils_server_xul=true ;;
@@ -85,6 +86,26 @@
 
 AM_CONDITIONAL([BUILDILSWEB], [test x$openils_web = xtrue])
 
+# install evergreen-updates?
+
+AC_ARG_ENABLE([updates],
+[  --disable-updates    disables installation of the Evergreen updates folder ],
+[case "${enableval}" in
+    yes) openils_updates=true ;;
+    no)  openils_updates=false ;;
+  *) AC_MSG_ERROR([please choose another value for --disable-updates (supported values are yes or no])
+esac],
+[openils_updates=true])
+
+AM_CONDITIONAL([BUILDILSUPDATES], [test x$openils_updates = xtrue])
+
+# Default updates host?
+AC_ARG_WITH([updateshost],
+[  --with-updateshost=hostname    default hostname for automatic updates (default is blank)],
+[AUTOUPDATE_HOST=${withval}],
+[AUTOUPDATE_HOST=])
+AC_SUBST([AUTOUPDATE_HOST])
+
 # install Evergreen Apache modules?
 AC_ARG_ENABLE([apache-modules],
 [  --disable-apache-modules    disables installation of the Evergreen Apache modules ],
@@ -350,6 +371,7 @@
 AC_CONFIG_FILES([Makefile
 		 Open-ILS/src/Makefile
 		 Open-ILS/web/Makefile
+		 Open-ILS/updates/Makefile
 		 Open-ILS/xul/staff_client/Makefile
 		 Open-ILS/src/extras/eg_config
 		 Open-ILS/src/extras/fast-extract],
@@ -383,6 +405,11 @@
 else
         AC_MSG_RESULT([Evergreen Web:			no])
 fi
+if test "$openils_updates" = "true" ; then
+        AC_MSG_RESULT([Evergreen Updates:		yes])
+else
+        AC_MSG_RESULT([Evergreen Updates:		no])
+fi
 if test "$openils_reporter" = "true" ; then
         AC_MSG_RESULT([Evergreen Reporter:		yes])
 else



More information about the open-ils-commits mailing list