Merge branch 'master' of git+ssh://yeti.esilibrary.com/home/evergreen/evergreen-equin...
authorberick <berick@esilibrary.com>
Fri, 18 Feb 2011 14:38:53 +0000 (09:38 -0500)
committerberick <berick@esilibrary.com>
Fri, 18 Feb 2011 14:38:53 +0000 (09:38 -0500)
25 files changed:
Open-ILS/examples/fm_IDL.xml
Open-ILS/src/extras/Makefile.install
Open-ILS/src/perlmods/lib/OpenILS/Application/Actor.pm
Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/Circulate.pm
Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/Money.pm
Open-ILS/src/perlmods/lib/OpenILS/Application/Storage/Publisher/action.pm
Open-ILS/src/perlmods/lib/OpenILS/Application/Trigger/Reactor/SendEmail.pm
Open-ILS/src/sql/Pg/002.functions.config.sql
Open-ILS/src/sql/Pg/002.schema.config.sql
Open-ILS/src/sql/Pg/100.circ_matrix.sql
Open-ILS/src/sql/Pg/110.hold_matrix.sql
Open-ILS/src/sql/Pg/950.data.seed-values.sql
Open-ILS/src/sql/Pg/upgrade/0487.circ_matrix_fallthrough.sql [new file with mode: 0644]
Open-ILS/src/sql/Pg/upgrade/0488.function.maintain_901_tcn.sql [new file with mode: 0644]
Open-ILS/web/js/dojo/openils/BibTemplate.js
Open-ILS/web/js/dojo/openils/widget/AutoFieldWidget.js
Open-ILS/web/js/dojo/openils/widget/AutoGrid.js
Open-ILS/web/js/dojo/openils/widget/EditPane.js
Open-ILS/web/js/dojo/openils/widget/nls/AutoFieldWidget.js
Open-ILS/web/js/ui/default/circ/selfcheck/selfcheck.js
Open-ILS/web/js/ui/default/conify/global/config/circ_matrix_matchpoint.js
Open-ILS/web/opac/common/js/opac_utils.js
Open-ILS/web/opac/skin/default/xml/body.xml
Open-ILS/web/opac/skin/default/xml/home/index_body.xml
Open-ILS/web/templates/default/conify/global/config/circ_matrix_matchpoint.tt2

index 0f13006..60e38b8 100644 (file)
@@ -1146,13 +1146,15 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
                        <field reporter:label="MARC Form" name="marc_form" oils_persist:primitive="string" reporter:datatype="link"/>
                        <field reporter:label="Videorecording Format" name="marc_vr_format" oils_persist:primitive="string" reporter:datatype="link"/>
                        <field reporter:label="Reference?" name="ref_flag" reporter:datatype="bool"/>
+            <field reporter:label="Juvenile?" name="juvenile_flag" reporter:datatype="bool"/>
                        <field reporter:label="User Age: Lower Bound" name="usr_age_lower_bound" reporter:datatype="text"/>
                        <field reporter:label="User Age: Upper Bound" name="usr_age_upper_bound" reporter:datatype="text"/>
                        <field reporter:label="Circulate?" name="circulate" reporter:datatype="bool"/>
-                       <field reporter:label="Duration Rule" name="duration_rule" reporter:datatype="link" oils_obj:required="true"/>
-                       <field reporter:label="Recurring Fine Rule" name="recurring_fine_rule" reporter:datatype="link" oils_obj:required="true"/>
-                       <field reporter:label="Max Fine Rule" name="max_fine_rule" reporter:datatype="link" oils_obj:required="true"/>
+                       <field reporter:label="Duration Rule" name="duration_rule" reporter:datatype="link"/>
+                       <field reporter:label="Recurring Fine Rule" name="recurring_fine_rule" reporter:datatype="link"/>
+                       <field reporter:label="Max Fine Rule" name="max_fine_rule" reporter:datatype="link"/>
             <field reporter:label="Hard Due Date" name="hard_due_date" reporter:datatype="link"/>
+            <field reporter:label="Renewals Override" name="renewals" reporter:datatype="int"/>
                        <field reporter:label="Script Test" name="script_test" reporter:datatype="text"/>
                        <field name="total_copy_hold_ratio" reporter:datatype="float" reporter:label="Minimum Total Copy/Hold Ratio"/>
                        <field name="available_copy_hold_ratio" reporter:datatype="float" reporter:label="Minimum Available Copy/Hold Ratio"/>
index 1be7dc5..80c47b2 100644 (file)
@@ -87,6 +87,7 @@ DEBS =  \
        libdatetime-set-perl\
        libdbd-pg-perl\
        libemail-send-perl\
+       libemail-simple-perl\
        libgd-graph3d-perl\
        liblog-log4perl-perl\
        libmarc-record-perl\
@@ -172,6 +173,7 @@ FEDORA_13_RPMS = \
        perl-Business-ISBN-Data \
        perl-DBD-Pg \
        perl-Email-Send \
+       perl-Email-Simple \
        perl-GDGraph3d \
        perl-Net-SSH2 \
        perl-OLE-Storage_Lite \
index 3a7efd0..d8dfb71 100644 (file)
@@ -1641,7 +1641,7 @@ foreach (keys %methods) {
             }
         }
     );
-    /\.have_balance/ and $args{authoritative} = 1;     # FIXME: I don't know why have_charge isn't authoritative
+    $args{authoritative} = 1;
     __PACKAGE__->register_method(%args);
 }
 
@@ -1682,12 +1682,17 @@ __PACKAGE__->register_method(
 
 
 sub user_transactions {
-       my( $self, $client, $login_session, $user_id, $type, $options ) = @_;
+       my( $self, $client, $auth, $user_id, $type, $options ) = @_;
     $options ||= {};
 
-       my( $user_obj, $target, $evt ) = $apputils->checkses_requestor(
-               $login_session, $user_id, 'VIEW_USER_TRANSACTIONS' );
-       return $evt if $evt;
+    my $e = new_editor(authtoken => $auth);
+    return $e->event unless $e->checkauth;
+
+    my $user = $e->retrieve_actor_user($user_id) or return $e->event;
+
+    return $e->event unless 
+        $e->requestor->id == $user_id or
+        $e->allowed('VIEW_USER_TRANSACTIONS', $user->home_ou);
 
     my $api = $self->api_name();
 
@@ -1695,17 +1700,13 @@ sub user_transactions {
         { 'balance_owed' => { '<>' => 0 } }:
         { 'total_owed' => { '>' => 0 } };
 
-    my ($trans) = $self->method_lookup(
-        'open-ils.actor.user.transactions.history.still_open')
-      ->run( $login_session, $user_id, $type, $filter, $options );
+    my $method = 'open-ils.actor.user.transactions.history.still_open';
+    $method = "$method.authoritative" if $api => /authoritative/;
+    my ($trans) = $self->method_lookup($method)->run($auth, $user_id, $type, $filter, $options);
 
        if($api =~ /total/o) { 
                my $total = 0.0;
-               for my $t (@$trans) {
-                       $total += $t->balance_owed;
-               }
-
-               $logger->debug("Total balance owed by user $user_id: $total");
+        $total += $_->balance_owed for @$trans;
                return $total;
        }
 
@@ -1720,27 +1721,8 @@ sub user_transactions {
                        next;
                }
 
-               my $circ = $apputils->simple_scalar_request(
-                               "open-ils.cstore",
-                               "open-ils.cstore.direct.action.circulation.retrieve",
-                               $t->id );
-
-               next unless $circ;
-
-               my $title = $apputils->simple_scalar_request(
-                       "open-ils.storage", 
-                       "open-ils.storage.fleshed.biblio.record_entry.retrieve_by_copy",
-                       $circ->target_copy );
-
-               next unless $title;
-
-               my $u = OpenILS::Utils::ModsParser->new();
-               $u->start_mods_batch($title->marc());
-               my $mods = $u->finish_mods_batch();
-               $mods->doc_id($title->id) if $mods;
-
-               push @resp, {transaction => $t, circ => $circ, record => $mods };
-
+        my $circ_data = flesh_circ($e, $t->id);
+               push @resp, {transaction => $t, %$circ_data};
        }
 
        return \@resp; 
@@ -1779,8 +1761,18 @@ sub user_transaction_retrieve {
     return $trans unless $self->api_name =~ /flesh/;
     return {transaction => $trans} if $trans->xact_type ne 'circulation';
 
+    my $circ_data = flesh_circ($e, $trans->id, 1);
+
+       return {transaction => $trans, %$circ_data};
+}
+
+sub flesh_circ {
+    my $e = shift;
+    my $circ_id = shift;
+    my $flesh_copy = shift;
+
     my $circ = $e->retrieve_action_circulation([
-        $trans->id, {
+        $circ_id, {
             flesh => 3,
             flesh_fields => {
                 circ => ['target_copy'],
@@ -1809,7 +1801,7 @@ sub user_transaction_retrieve {
     $circ->target_copy($circ->target_copy->id);
     $copy->call_number($copy->call_number->id);
 
-       return {transaction => $trans, circ => $circ, record => $mods, copy => $copy };
+       return {circ => $circ, record => $mods, copy => ($flesh_copy) ? $copy : undef };
 }
 
 
@@ -2021,23 +2013,20 @@ sub _sigmaker {
     return @sig;
 }
 
-my %hist_methods = (
+my %auth_hist_methods = (
     'history'             => '',
     'history.have_charge' => 'that have an initial charge',
     'history.still_open'  => 'that are not finished',
-);
-my %auth_hist_methods = (
     'history.have_balance'         => 'that have a balance',
     'history.have_bill'            => 'that have billings',
     'history.have_bill_or_payment' => 'that have non-zero-sum billings or at least 1 payment',
+    'history.have_payment' => 'that have at least 1 payment',
 );
-foreach (keys %hist_methods) {
-    __PACKAGE__->register_method(_sigmaker($_,       $hist_methods{$_}));
-    __PACKAGE__->register_method(_sigmaker("$_.ids", $hist_methods{$_}));
-}
+
 foreach (keys %auth_hist_methods) {
     __PACKAGE__->register_method(_sigmaker($_,       $auth_hist_methods{$_}, 1));
     __PACKAGE__->register_method(_sigmaker("$_.ids", $auth_hist_methods{$_}, 1));
+    __PACKAGE__->register_method(_sigmaker("$_.fleshed", $auth_hist_methods{$_}, 1));
 }
 
 sub user_transaction_history {
@@ -2067,6 +2056,10 @@ sub user_transaction_history {
             'last_payment_ts' => { '<>' => undef }
         };
 
+    } elsif($api =~ /have_payment/) {
+
+        $filter->{last_payment_ts} ||= {'<>' => undef};
+
     } elsif( $api =~ /have_balance/o) {
 
         # transactions that have a non-zero overall balance
@@ -2089,17 +2082,27 @@ sub user_transaction_history {
     $options_clause->{'offset'} = $options->{'offset'} if $options->{'offset'}; 
 
     my $mbts = $e->search_money_billable_transaction_summary(
-        [ 
-            { usr => $userid, @xact_finish, %$filter },
+        [   { usr => $userid, @xact_finish, %$filter },
             $options_clause
         ]
     );
 
-    if ($api =~ /\.ids/) {
-       return [map {$_->id} @$mbts];
-    } else {
-        return $mbts;
-    }
+    return [map {$_->id} @$mbts] if $api =~ /\.ids/;
+    return $mbts unless $api =~ /fleshed/;
+
+       my @resp;
+       for my $t (@$mbts) {
+                       
+               if( $t->xact_type ne 'circulation' ) {
+                       push @resp, {transaction => $t};
+                       next;
+               }
+
+        my $circ_data = flesh_circ($e, $t->id);
+               push @resp, {transaction => $t, %$circ_data};
+       }
+
+       return \@resp; 
 }
 
 
@@ -3517,7 +3520,9 @@ sub user_payments {
     return $e->die_event unless $e->checkauth;
 
     my $user = $e->retrieve_actor_user($user_id) or return $e->event;
-    return $e->event unless $e->allowed('VIEW_USER_TRANSACTIONS', $user->home_ou);
+    return $e->event unless 
+        $e->requestor->id == $user_id or
+        $e->allowed('VIEW_USER_TRANSACTIONS', $user->home_ou);
 
     # Find all payments for all transactions for user $user_id
     my $query = {
index cc30638..97e4771 100644 (file)
@@ -1151,16 +1151,15 @@ sub run_indb_circ_test {
     $self->circ_test_success($U->is_true($results->[0]->{success}));
 
     if(my $mp = $results->[0]->{matchpoint}) {
-        $logger->info("circulator: circ policy test found matchpoint $mp");
-        $self->circ_matrix_matchpoint(
-            $self->editor->retrieve_config_circ_matrix_matchpoint([
-                $mp,
-                {   flesh => 1,
-                    flesh_fields => {ccmm => 
-                        ['duration_rule', 'recurring_fine_rule', 'max_fine_rule', 'hard_due_date']}
-                }
-            ])
-        );
+        $logger->info("circulator: circ policy test found matchpoint built via rows " . $results->[0]->{buildrows});
+        $self->circ_matrix_matchpoint($self->editor->retrieve_config_circ_matrix_matchpoint($mp));
+        $self->circ_matrix_matchpoint->duration_rule($self->editor->retrieve_config_rules_circ_duration($results->[0]->{duration_rule}));
+        if($results->[0]->{renewals}) {
+            $self->circ_matrix_matchpoint->duration_rule->max_renewals($results->[0]->{renewals});
+        }
+        $self->circ_matrix_matchpoint->recurring_fine_rule($self->editor->retrieve_config_rules_recurring_fine($results->[0]->{recurring_fine_rule}));
+        $self->circ_matrix_matchpoint->max_fine_rule($self->editor->retrieve_config_rules_max_fine($results->[0]->{max_fine_rule}));
+        $self->circ_matrix_matchpoint->hard_due_date($self->editor->retrieve_config_hard_due_date($results->[0]->{hard_due_date}));
     }
 
     return $self->matrix_test_result($results);
index d472820..dcf19cc 100644 (file)
@@ -139,7 +139,7 @@ sub make_payments {
     my $cc_args = $payments->{cc_args};
     my $check_number = $payments->{check_number};
     my $total_paid = 0;
-    my $this_ou = $e->requestor->ws_ou;
+    my $this_ou = $e->requestor->ws_ou || $e->requestor->home_ou;
     my %orgs;
 
     # unless/until determined by payment processor API
@@ -534,9 +534,11 @@ sub format_payment_receipt {
                     mbt => ['usr']
                 }
             }
-        ]) or return OpenILS::Event->new('MP_NOT_FOUND');
+        ]) or return $e->event;
 
-        return $e->event unless $e->allowed('VIEW_TRANSACTION', $payment->xact->usr->home_ou); 
+        return $e->event unless 
+            $e->requestor->id == $payment->xact->usr->id or
+            $e->allowed('VIEW_TRANSACTION', $payment->xact->usr->home_ou); 
 
         push @$payments, $payment;
     }
index 6b96ffa..6295a62 100644 (file)
@@ -1689,6 +1689,14 @@ sub reservation_targeter {
                     next;
                 }
 
+                # At this point, if we're just targeting one specific
+                # resource, just succeed. We don't care about its present
+                # copy status.
+                if ($bresv->target_resource) {
+                    push @good_resources, $res;
+                    next;
+                }
+
                 if ($copy->status->id == 0 || $copy->status->id == 7) {
                     push @good_resources, $res;
                     next;
index 64826fd..5cf08c3 100644 (file)
@@ -3,10 +3,11 @@ use strict; use warnings;
 use Error qw/:try/;
 use Data::Dumper;
 use Email::Send;
+use Email::Simple;
 use OpenSRF::Utils::SettingsClient;
 use OpenILS::Application::Trigger::Reactor;
 use OpenSRF::Utils::Logger qw/:logger/;
-use utf8;
+use Encode;
 $Data::Dumper::Indent = 0;
 
 use base 'OpenILS::Application::Trigger::Reactor';
@@ -24,6 +25,10 @@ setting is used to send the email, and the value at
 /opensrf/default/email_notify/sender_address is passed into the template as
 the 'default_sender' variable.
 
+Email is encoded in UTF-8 and the corresponding MIME-Version, Content-Type,
+and Content-Transfer-Encoding headers are set to help mail user agents
+decode the content.
+
 No default template is assumed, and all information other than the
 default_sender that the system provides is expected to be gathered by the
 Event Definition through either Environment or Parameter definitions.
@@ -39,7 +44,7 @@ sub handler {
     my $smtp = $conf->config_value('email_notify', 'smtp_server');
     $$env{default_sender} = $conf->config_value('email_notify', 'sender_address');
 
-    my $text = $self->run_TT($env);
+    my $text = encode_utf8($self->run_TT($env));
     return 0 if (!$text);
 
     my $sender = Email::Send->new({mailer => 'SMTP'});
@@ -48,10 +53,13 @@ sub handler {
     my $stat;
     my $err;
 
-    utf8::encode($text); # prevent "Wide character" errors in Email::Send
+    my $email = Email::Simple->new($text);
+    $email->header_set('MIME-Version' => '1.0');
+    $email->header_set('Content-Type' => "text/plain; charset=UTF-8");
+    $email->header_set('Content-Transfer-Encoding' => '8bit');
 
     try {
-        $stat = $sender->send($text);
+        $stat = $sender->send($email);
     } catch Error with {
         $err = $stat = shift;
         $logger->error("SendEmail Reactor: Email failed with error: $err");
index 1a967db..ec2dbf2 100644 (file)
@@ -420,10 +420,21 @@ CREATE OR REPLACE FUNCTION oils_json_to_text( TEXT ) RETURNS TEXT AS $f$
 $f$ LANGUAGE PLPERLU;
 
 CREATE OR REPLACE FUNCTION maintain_901 () RETURNS TRIGGER AS $func$
+DECLARE
+    use_id_for_tcn BOOLEAN;
 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
+        -- Set TCN value to record ID?
+        SELECT enabled FROM config.global_flag INTO use_id_for_tcn
+            WHERE name = 'cat.bib.use_id_for_tcn';
+
+        IF use_id_for_tcn = 't' THEN
+            NEW.tcn_value := NEW.id;
+        END IF;
+
         NEW.marc := REGEXP_REPLACE(
             NEW.marc,
             E'(</(?:[^:]*?:)?record>)',
index 857d1a1..6b0db4d 100644 (file)
@@ -70,7 +70,7 @@ CREATE TABLE config.upgrade_log (
     install_date    TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW()
 );
 
-INSERT INTO config.upgrade_log (version) VALUES ('0486'); -- berick
+INSERT INTO config.upgrade_log (version) VALUES ('0488'); -- dbs
 
 CREATE TABLE config.bib_source (
        id              SERIAL  PRIMARY KEY,
index 0ed8e67..e0f3b3d 100644 (file)
@@ -95,11 +95,12 @@ CREATE TABLE config.circ_matrix_matchpoint (
     usr_age_lower_bound  INTERVAL,
     usr_age_upper_bound  INTERVAL,
     -- "Result" Fields
-    circulate            BOOL    NOT NULL DEFAULT TRUE,    -- Hard "can't circ" flag requiring an override
-    duration_rule        INT     NOT NULL REFERENCES config.rule_circ_duration (id) DEFERRABLE INITIALLY DEFERRED,
-    recurring_fine_rule  INT     NOT NULL REFERENCES config.rule_recurring_fine (id) DEFERRABLE INITIALLY DEFERRED,
-    max_fine_rule        INT     NOT NULL REFERENCES config.rule_max_fine (id) DEFERRABLE INITIALLY DEFERRED,
+    circulate            BOOL,   -- Hard "can't circ" flag requiring an override
+    duration_rule        INT     REFERENCES config.rule_circ_duration (id) DEFERRABLE INITIALLY DEFERRED,
+    recurring_fine_rule  INT     REFERENCES config.rule_recurring_fine (id) DEFERRABLE INITIALLY DEFERRED,
+    max_fine_rule        INT     REFERENCES config.rule_max_fine (id) DEFERRABLE INITIALLY DEFERRED,
     hard_due_date        INT     REFERENCES config.hard_due_date (id) DEFERRABLE INITIALLY DEFERRED,
+    renewals             INT,    -- Renewal count override
     script_test          TEXT,                           -- javascript source 
     total_copy_hold_ratio     FLOAT,
     available_copy_hold_ratio FLOAT
@@ -122,19 +123,24 @@ CREATE TABLE config.circ_matrix_circ_mod_test_map (
     CONSTRAINT cm_once_per_test UNIQUE (circ_mod_test, circ_mod)
 );
 
-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$
+CREATE TYPE action.found_circ_matrix_matchpoint AS ( success BOOL, matchpoint config.circ_matrix_matchpoint, buildrows INT[] );
+
+CREATE OR REPLACE FUNCTION action.find_circ_matrix_matchpoint( context_ou INT, item_object asset.copy, user_object actor.usr, renewal BOOL ) RETURNS action.found_circ_matrix_matchpoint AS $func$
 DECLARE
-    user_object     actor.usr%ROWTYPE;
-    item_object     asset.copy%ROWTYPE;
     cn_object       asset.call_number%ROWTYPE;
     rec_descriptor  metabib.rec_descriptor%ROWTYPE;
+    cur_matchpoint  config.circ_matrix_matchpoint%ROWTYPE;
     matchpoint      config.circ_matrix_matchpoint%ROWTYPE;
     weights         config.circ_matrix_weights%ROWTYPE;
     user_age        INTERVAL;
     denominator     NUMERIC(6,2);
+    row_list        INT[];
+    result          action.found_circ_matrix_matchpoint;
 BEGIN
-    SELECT INTO user_object     * FROM actor.usr                WHERE id = match_user;
-    SELECT INTO item_object     * FROM asset.copy               WHERE id = match_item;
+    -- Assume failure
+    result.success = false;
+
+    -- Fetch useful data
     SELECT INTO cn_object       * FROM asset.call_number        WHERE id = item_object.call_number;
     SELECT INTO rec_descriptor  * FROM metabib.rec_descriptor   WHERE record = cn_object.record;
 
@@ -181,60 +187,126 @@ BEGIN
        )
     SELECT INTO denominator MAX(distance) + 1 FROM all_distance;
 
-    -- Select the winning matchpoint into the matchpoint variable for returning
-    SELECT INTO matchpoint m.*
-      FROM  config.circ_matrix_matchpoint m
-            /*LEFT*/ JOIN permission.grp_ancestors_distance( user_object.profile ) upgad ON m.grp = upgad.id
-            /*LEFT*/ JOIN actor.org_unit_ancestors_distance( context_ou ) ctoua ON m.org_unit = ctoua.id
-            LEFT JOIN actor.org_unit_ancestors_distance( cn_object.owning_lib ) cnoua ON m.copy_owning_lib = cnoua.id
-            LEFT JOIN actor.org_unit_ancestors_distance( item_object.circ_lib ) iooua ON m.copy_circ_lib = iooua.id
-            LEFT JOIN actor.org_unit_ancestors_distance( user_object.home_ou  ) uhoua ON m.user_home_ou = uhoua.id
-      WHERE m.active
-            -- Permission Groups
-         -- AND (m.grp                      IS NULL OR upgad.id IS NOT NULL) -- Optional Permission Group?
-            -- Org Units
-         -- AND (m.org_unit                 IS NULL OR ctoua.id IS NOT NULL) -- Optional Org Unit?
-            AND (m.copy_owning_lib          IS NULL OR cnoua.id IS NOT NULL)
-            AND (m.copy_circ_lib            IS NULL OR iooua.id IS NOT NULL)
-            AND (m.user_home_ou             IS NULL OR uhoua.id IS NOT NULL)
-            -- Circ Type
-            AND (m.is_renewal               IS NULL OR m.is_renewal = renewal)
-            -- Static User Checks
-            AND (m.juvenile_flag            IS NULL OR m.juvenile_flag = user_object.juvenile)
-            AND (m.usr_age_lower_bound      IS NULL OR (user_age IS NOT NULL AND m.usr_age_lower_bound < user_age))
-            AND (m.usr_age_upper_bound      IS NULL OR (user_age IS NOT NULL AND m.usr_age_upper_bound > user_age))
-            -- Static Item Checks
-            AND (m.circ_modifier            IS NULL OR m.circ_modifier = item_object.circ_modifier)
-            AND (m.marc_type                IS NULL OR m.marc_type = COALESCE(item_object.circ_as_type, rec_descriptor.item_type))
-            AND (m.marc_form                IS NULL OR m.marc_form = rec_descriptor.item_form)
-            AND (m.marc_vr_format           IS NULL OR m.marc_vr_format = rec_descriptor.vr_format)
-            AND (m.ref_flag                 IS NULL OR m.ref_flag = item_object.ref)
-      ORDER BY
-            -- Permission Groups
-            CASE WHEN upgad.distance        IS NOT NULL THEN 2^(2*weights.grp - (upgad.distance/denominator)) ELSE 0.0 END +
-            -- Org Units
-            CASE WHEN ctoua.distance        IS NOT NULL THEN 2^(2*weights.org_unit - (ctoua.distance/denominator)) ELSE 0.0 END +
-            CASE WHEN cnoua.distance        IS NOT NULL THEN 2^(2*weights.copy_owning_lib - (cnoua.distance/denominator)) ELSE 0.0 END +
-            CASE WHEN iooua.distance        IS NOT NULL THEN 2^(2*weights.copy_circ_lib - (iooua.distance/denominator)) ELSE 0.0 END +
-            CASE WHEN uhoua.distance        IS NOT NULL THEN 2^(2*weights.user_home_ou - (uhoua.distance/denominator)) ELSE 0.0 END +
-            -- Circ Type                    -- Note: 4^x is equiv to 2^(2*x)
-            CASE WHEN m.is_renewal          IS NOT NULL THEN 4^weights.is_renewal ELSE 0.0 END +
-            -- Static User Checks
-            CASE WHEN m.juvenile_flag       IS NOT NULL THEN 4^weights.juvenile_flag ELSE 0.0 END +
-            CASE WHEN m.usr_age_lower_bound IS NOT NULL THEN 4^weights.usr_age_lower_bound ELSE 0.0 END +
-            CASE WHEN m.usr_age_upper_bound IS NOT NULL THEN 4^weights.usr_age_upper_bound ELSE 0.0 END +
-            -- Static Item Checks
-            CASE WHEN m.circ_modifier       IS NOT NULL THEN 4^weights.circ_modifier ELSE 0.0 END +
-            CASE WHEN m.marc_type           IS NOT NULL THEN 4^weights.marc_type ELSE 0.0 END +
-            CASE WHEN m.marc_form           IS NOT NULL THEN 4^weights.marc_form ELSE 0.0 END +
-            CASE WHEN m.marc_vr_format      IS NOT NULL THEN 4^weights.marc_vr_format ELSE 0.0 END +
-            CASE WHEN m.ref_flag            IS NOT NULL THEN 4^weights.ref_flag ELSE 0.0 END DESC,
-            -- Final sort on id, so that if two rules have the same sorting in the previous sort they have a defined order
-            -- This prevents "we changed the table order by updating a rule, and we started getting different results"
-            m.id;
-
-    -- Return the entire matchpoint
-    RETURN matchpoint;
+    -- Loop over all the potential matchpoints
+    FOR cur_matchpoint IN
+        SELECT m.*
+          FROM  config.circ_matrix_matchpoint m
+                /*LEFT*/ JOIN permission.grp_ancestors_distance( user_object.profile ) upgad ON m.grp = upgad.id
+                /*LEFT*/ JOIN actor.org_unit_ancestors_distance( context_ou ) ctoua ON m.org_unit = ctoua.id
+                LEFT JOIN actor.org_unit_ancestors_distance( cn_object.owning_lib ) cnoua ON m.copy_owning_lib = cnoua.id
+                LEFT JOIN actor.org_unit_ancestors_distance( item_object.circ_lib ) iooua ON m.copy_circ_lib = iooua.id
+                LEFT JOIN actor.org_unit_ancestors_distance( user_object.home_ou  ) uhoua ON m.user_home_ou = uhoua.id
+          WHERE m.active
+                -- Permission Groups
+             -- AND (m.grp                      IS NULL OR upgad.id IS NOT NULL) -- Optional Permission Group?
+                -- Org Units
+             -- AND (m.org_unit                 IS NULL OR ctoua.id IS NOT NULL) -- Optional Org Unit?
+                AND (m.copy_owning_lib          IS NULL OR cnoua.id IS NOT NULL)
+                AND (m.copy_circ_lib            IS NULL OR iooua.id IS NOT NULL)
+                AND (m.user_home_ou             IS NULL OR uhoua.id IS NOT NULL)
+                -- Circ Type
+                AND (m.is_renewal               IS NULL OR m.is_renewal = renewal)
+                -- Static User Checks
+                AND (m.juvenile_flag            IS NULL OR m.juvenile_flag = user_object.juvenile)
+                AND (m.usr_age_lower_bound      IS NULL OR (user_age IS NOT NULL AND m.usr_age_lower_bound < user_age))
+                AND (m.usr_age_upper_bound      IS NULL OR (user_age IS NOT NULL AND m.usr_age_upper_bound > user_age))
+                -- Static Item Checks
+                AND (m.circ_modifier            IS NULL OR m.circ_modifier = item_object.circ_modifier)
+                AND (m.marc_type                IS NULL OR m.marc_type = COALESCE(item_object.circ_as_type, rec_descriptor.item_type))
+                AND (m.marc_form                IS NULL OR m.marc_form = rec_descriptor.item_form)
+                AND (m.marc_vr_format           IS NULL OR m.marc_vr_format = rec_descriptor.vr_format)
+                AND (m.ref_flag                 IS NULL OR m.ref_flag = item_object.ref)
+          ORDER BY
+                -- Permission Groups
+                CASE WHEN upgad.distance        IS NOT NULL THEN 2^(2*weights.grp - (upgad.distance/denominator)) ELSE 0.0 END +
+                -- Org Units
+                CASE WHEN ctoua.distance        IS NOT NULL THEN 2^(2*weights.org_unit - (ctoua.distance/denominator)) ELSE 0.0 END +
+                CASE WHEN cnoua.distance        IS NOT NULL THEN 2^(2*weights.copy_owning_lib - (cnoua.distance/denominator)) ELSE 0.0 END +
+                CASE WHEN iooua.distance        IS NOT NULL THEN 2^(2*weights.copy_circ_lib - (iooua.distance/denominator)) ELSE 0.0 END +
+                CASE WHEN uhoua.distance        IS NOT NULL THEN 2^(2*weights.user_home_ou - (uhoua.distance/denominator)) ELSE 0.0 END +
+                -- Circ Type                    -- Note: 4^x is equiv to 2^(2*x)
+                CASE WHEN m.is_renewal          IS NOT NULL THEN 4^weights.is_renewal ELSE 0.0 END +
+                -- Static User Checks
+                CASE WHEN m.juvenile_flag       IS NOT NULL THEN 4^weights.juvenile_flag ELSE 0.0 END +
+                CASE WHEN m.usr_age_lower_bound IS NOT NULL THEN 4^weights.usr_age_lower_bound ELSE 0.0 END +
+                CASE WHEN m.usr_age_upper_bound IS NOT NULL THEN 4^weights.usr_age_upper_bound ELSE 0.0 END +
+                -- Static Item Checks
+                CASE WHEN m.circ_modifier       IS NOT NULL THEN 4^weights.circ_modifier ELSE 0.0 END +
+                CASE WHEN m.marc_type           IS NOT NULL THEN 4^weights.marc_type ELSE 0.0 END +
+                CASE WHEN m.marc_form           IS NOT NULL THEN 4^weights.marc_form ELSE 0.0 END +
+                CASE WHEN m.marc_vr_format      IS NOT NULL THEN 4^weights.marc_vr_format ELSE 0.0 END +
+                CASE WHEN m.ref_flag            IS NOT NULL THEN 4^weights.ref_flag ELSE 0.0 END DESC,
+                -- Final sort on id, so that if two rules have the same sorting in the previous sort they have a defined order
+                -- This prevents "we changed the table order by updating a rule, and we started getting different results"
+                m.id LOOP
+
+        -- Record the full matching row list
+        row_list := row_list || cur_matchpoint.id;
+
+        -- No matchpoint yet?
+        IF matchpoint.id IS NULL THEN
+            -- Take the entire matchpoint as a starting point
+            matchpoint := cur_matchpoint;
+            CONTINUE; -- No need to look at this row any more.
+        END IF;
+
+        -- Incomplete matchpoint?
+        IF matchpoint.circulate IS NULL THEN
+            matchpoint.circulate := cur_matchpoint.circulate;
+        END IF;
+        IF matchpoint.duration_rule IS NULL THEN
+            matchpoint.duration_rule := cur_matchpoint.duration_rule;
+        END IF;
+        IF matchpoint.recurring_fine_rule IS NULL THEN
+            matchpoint.recurring_fine_rule := cur_matchpoint.recurring_fine_rule;
+        END IF;
+        IF matchpoint.max_fine_rule IS NULL THEN
+            matchpoint.max_fine_rule := cur_matchpoint.max_fine_rule;
+        END IF;
+        IF matchpoint.hard_due_date IS NULL THEN
+            matchpoint.hard_due_date := cur_matchpoint.hard_due_date;
+        END IF;
+        IF matchpoint.total_copy_hold_ratio IS NULL THEN
+            matchpoint.total_copy_hold_ratio := cur_matchpoint.total_copy_hold_ratio;
+        END IF;
+        IF matchpoint.available_copy_hold_ratio IS NULL THEN
+            matchpoint.available_copy_hold_ratio := cur_matchpoint.available_copy_hold_ratio;
+        END IF;
+        IF matchpoint.renewals IS NULL THEN
+            matchpoint.renewals := cur_matchpoint.renewals;
+        END IF;
+    END LOOP;
+
+    -- Check required fields
+    IF matchpoint.circulate             IS NOT NULL AND
+       matchpoint.duration_rule         IS NOT NULL AND
+       matchpoint.recurring_fine_rule   IS NOT NULL AND
+       matchpoint.max_fine_rule         IS NOT NULL THEN
+        -- All there? We have a completed match.
+        result.success := true;
+    END IF;
+
+    -- Include the assembled matchpoint, even if it isn't complete
+    result.matchpoint := matchpoint;
+
+    -- Include (for debugging) the full list of matching rows
+    result.buildrows := row_list;
+
+    -- Hand the result back to caller
+    RETURN result;
+END;
+$func$ LANGUAGE plpgsql;
+
+-- Helper function - For manual calling, it can be easier to pass in IDs instead of objects
+CREATE OR REPLACE FUNCTION action.find_circ_matrix_matchpoint( context_ou INT, match_item BIGINT, match_user INT, renewal BOOL ) RETURNS SETOF action.found_circ_matrix_matchpoint AS $func$
+DECLARE
+    item_object asset.copy%ROWTYPE;
+    user_object actor.usr%ROWTYPE;
+BEGIN
+    SELECT INTO item_object * FROM asset.copy  WHERE id = match_item;
+    SELECT INTO user_object * FROM actor.usr   WHERE id = match_user;
+
+    RETURN QUERY SELECT * FROM action.find_circ_matrix_matchpoint( context_ou, item_object, user_object, renewal );
 END;
 $func$ LANGUAGE plpgsql;
 
@@ -291,25 +363,26 @@ BEGIN
 END;
 $func$ LANGUAGE PLPGSQL;
 
-CREATE TYPE action.matrix_test_result AS ( success BOOL, matchpoint INT, fail_part TEXT );
-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$
+CREATE TYPE action.circ_matrix_test_result AS ( success BOOL, fail_part TEXT, buildrows INT[], matchpoint INT, circulate BOOL, duration_rule INT, recurring_fine_rule INT, max_fine_rule INT, hard_due_date INT, renewals INT );
+CREATE OR REPLACE FUNCTION action.item_user_circ_test( circ_ou INT, match_item BIGINT, match_user INT, renewal BOOL ) RETURNS SETOF action.circ_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;
+    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;
+    result                  action.circ_matrix_test_result;
+    circ_test               action.found_circ_matrix_matchpoint;
+    circ_matchpoint         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;
+    items_out               INT;
     context_org_list        INT[];
-    done            BOOL := FALSE;
+    done                    BOOL := FALSE;
 BEGIN
+    -- Assume success unless we hit a failure condition
     result.success := TRUE;
 
     -- Fail if the user is BARRED
@@ -335,17 +408,6 @@ BEGIN
         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;
@@ -383,37 +445,29 @@ BEGIN
         RETURN NEXT result;
     END IF;
 
-    SELECT INTO context_org_list ARRAY_ACCUM(id) FROM actor.org_unit_full_path( circ_test.org_unit );
+    SELECT INTO circ_test * FROM action.find_circ_matrix_matchpoint(circ_ou, item_object, user_object, renewal);
 
-    -- 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';
+    circ_matchpoint             := circ_test.matchpoint;
+    result.matchpoint           := circ_matchpoint.id;
+    result.circulate            := circ_matchpoint.circulate;
+    result.duration_rule        := circ_matchpoint.duration_rule;
+    result.recurring_fine_rule  := circ_matchpoint.recurring_fine_rule;
+    result.max_fine_rule        := circ_matchpoint.max_fine_rule;
+    result.hard_due_date        := circ_matchpoint.hard_due_date;
+    result.renewals             := circ_matchpoint.renewals;
+    result.buildrows            := circ_test.buildrows;
+
+    -- Fail if we couldn't find a matchpoint
+    IF circ_test.success = false THEN
+        result.fail_part := 'no_matchpoint';
         result.success := FALSE;
         done := TRUE;
         RETURN NEXT result;
+        RETURN; -- All tests after this point require a matchpoint. No sense in running on an incomplete or missing one.
     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;
+    -- Apparently....use the circ matchpoint org unit to determine what org units are valid.
+    SELECT INTO context_org_list ARRAY_ACCUM(id) FROM actor.org_unit_full_path( circ_matchpoint.org_unit );
 
     IF renewal THEN
         penalty_type = '%RENEW%';
@@ -436,8 +490,40 @@ BEGIN
         RETURN NEXT result;
     END LOOP;
 
+    -- Fail if the test is set to hard non-circulating
+    IF circ_matchpoint.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_matchpoint.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_matchpoint.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_matchpoint.available_copy_hold_ratio IS NOT NULL THEN
+        IF hold_ratio.hold_count IS NULL THEN
+            SELECT INTO hold_ratio * FROM action.copy_related_hold_stats(match_item);
+        END IF;
+        IF hold_ratio.available_copy_ratio IS NOT NULL AND hold_ratio.available_copy_ratio < circ_matchpoint.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;
+
     -- 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
+    FOR out_by_circ_mod IN SELECT * FROM config.circ_matrix_circ_mod_test WHERE matchpoint = circ_matchpoint.id LOOP
         SELECT  INTO items_out COUNT(*)
           FROM  action.circulation circ
             JOIN asset.copy cp ON (cp.id = circ.target_copy)
@@ -463,11 +549,11 @@ BEGIN
 END;
 $func$ LANGUAGE plpgsql;
 
-CREATE OR REPLACE FUNCTION action.item_user_circ_test( INT, BIGINT, INT ) RETURNS SETOF action.matrix_test_result AS $func$
+CREATE OR REPLACE FUNCTION action.item_user_circ_test( INT, BIGINT, INT ) RETURNS SETOF action.circ_matrix_test_result AS $func$
     SELECT * FROM action.item_user_circ_test( $1, $2, $3, FALSE );
 $func$ LANGUAGE SQL;
 
-CREATE OR REPLACE FUNCTION action.item_user_renew_test( INT, BIGINT, INT ) RETURNS SETOF action.matrix_test_result AS $func$
+CREATE OR REPLACE FUNCTION action.item_user_renew_test( INT, BIGINT, INT ) RETURNS SETOF action.circ_matrix_test_result AS $func$
     SELECT * FROM action.item_user_circ_test( $1, $2, $3, TRUE );
 $func$ LANGUAGE SQL;
 
index 1821b1d..a025979 100644 (file)
@@ -200,6 +200,7 @@ BEGIN
 END;
 $func$ LANGUAGE 'plpgsql';
 
+CREATE TYPE action.matrix_test_result AS ( success BOOL, matchpoint INT, fail_part TEXT );
 CREATE OR REPLACE FUNCTION action.hold_request_permit_test( pickup_ou INT, request_ou INT, match_item BIGINT, match_user INT, match_requestor INT, retargetting BOOL ) RETURNS SETOF action.matrix_test_result AS $func$
 DECLARE
     matchpoint_id        INT;
index 796a579..409656b 100644 (file)
@@ -985,419 +985,974 @@ INSERT INTO config.billing_type (id, name, owner) VALUES ( 101, oils_i18n_gettex
 SELECT SETVAL('config.billing_type_id_seq'::TEXT, 101);
 
 --006.data.permissions.sql:
-INSERT INTO permission.perm_list VALUES 
-    (-1, 'EVERYTHING', NULL),
-    (2, 'OPAC_LOGIN', oils_i18n_gettext(2, 'Allow a user to log in to the OPAC', 'ppl', 'description')),
-    (4, 'STAFF_LOGIN', oils_i18n_gettext(4, 'Allow a user to log in to the staff client', 'ppl', 'description')),
-    (5, 'MR_HOLDS', oils_i18n_gettext(5, 'Allow a user to create a metarecord holds', 'ppl', 'description')),
-    (6, 'TITLE_HOLDS', oils_i18n_gettext(6, 'Allow a user to place a hold at the title level', 'ppl', 'description')),
-    (7, 'VOLUME_HOLDS', oils_i18n_gettext(7, 'Allow a user to place a volume level hold', 'ppl', 'description')),
-    (8, 'COPY_HOLDS', oils_i18n_gettext(8, 'Allow a user to place a hold on a specific copy', 'ppl', 'description')),
-    (9, 'REQUEST_HOLDS', oils_i18n_gettext(9, '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)', 'ppl', 'description')),
-    (10, 'REQUEST_HOLDS_OVERRIDE', oils_i18n_gettext(10, '* no longer applicable', 'ppl', 'description')),
-    (11, 'VIEW_HOLD', oils_i18n_gettext(11, 'Allow a user to view another user''s holds', 'ppl', 'description')),
-    (13, 'DELETE_HOLDS', oils_i18n_gettext(13, '* no longer applicable', 'ppl', 'description')),
-    (14, 'UPDATE_HOLD', oils_i18n_gettext(14, 'Allow a user to update another user''s hold', 'ppl', 'description')),
-    (15, 'RENEW_CIRC', oils_i18n_gettext(15, 'Allow a user to renew items', 'ppl', 'description')),
-    (16, 'VIEW_USER_FINES_SUMMARY', oils_i18n_gettext(16, 'Allow a user to view bill details', 'ppl', 'description')),
-    (17, 'VIEW_USER_TRANSACTIONS', oils_i18n_gettext(17, 'Allow a user to see another user''s grocery or circulation transactions in the Bills Interface, duplicate of VIEW_TRANSACTION', 'ppl', 'description')),
-    (18, 'UPDATE_MARC', oils_i18n_gettext(18, 'Allow a user to edit a MARC record', 'ppl', 'description')),
-    (19, 'CREATE_MARC', oils_i18n_gettext(19, 'Allow a user to create new MARC records. IMPORT_MARC is usually needed also.', 'ppl', 'description')),
-    (20, 'IMPORT_MARC', oils_i18n_gettext(20, 'Allow a user to import a MARC record from the MARC editor or the Z39.50 interface', 'ppl', 'description')),
-    (21, 'CREATE_VOLUME', oils_i18n_gettext(21, 'Allow a user to create a volume', 'ppl', 'description')),
-    (22, 'UPDATE_VOLUME', oils_i18n_gettext(22, '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.', 'ppl', 'description')),
-    (23, 'DELETE_VOLUME', oils_i18n_gettext(23, 'Allow a user to delete a volume', 'ppl', 'description')),
-    (24, 'CREATE_COPY', oils_i18n_gettext(24, 'Allow a user to create a new copy object', 'ppl', 'description')),
-    (25, 'UPDATE_COPY', oils_i18n_gettext(25, 'Allow a user to edit a copy', 'ppl', 'description')),
-    (26, 'DELETE_COPY', oils_i18n_gettext(26, 'Allow a user to delete a copy', 'ppl', 'description')),
-    (27, 'RENEW_HOLD_OVERRIDE', oils_i18n_gettext(27, 'Allow a user to continue to renew an item even if it is required for a hold', 'ppl', 'description')),
-    (28, 'CREATE_USER', oils_i18n_gettext(28, 'Allow a user to create another user', 'ppl', 'description')),
-    (29, 'UPDATE_USER', oils_i18n_gettext(29, 'Allow a user to edit a user''s record', 'ppl', 'description')),
-    (30, 'DELETE_USER', oils_i18n_gettext(30, 'Allow a user to delete another user, including all associated transactions', 'ppl', 'description')),
-    (31, 'VIEW_USER', oils_i18n_gettext(31, 'Allow a user to view another user''s Patron Record', 'ppl', 'description')),
-    (32, 'COPY_CHECKIN', oils_i18n_gettext(32, 'Allow a user to check in a copy', 'ppl', 'description')),
-    (33, 'CREATE_TRANSIT', oils_i18n_gettext(33, 'Allow a user to place an item in transit', 'ppl', 'description')),
-    (34, 'VIEW_PERMISSION', oils_i18n_gettext(34, 'Allow a user to view user permissions within the user permissions editor', 'ppl', 'description')),
-    (35, 'CHECKIN_BYPASS_HOLD_FULFILL', oils_i18n_gettext(35, '* no longer applicable', 'ppl', 'description')),
-    (36, 'CREATE_PAYMENT', oils_i18n_gettext(36, 'Allow a user to record payments in the Billing Interface', 'ppl', 'description')),
-    (37, 'SET_CIRC_LOST', oils_i18n_gettext(37, 'Allow a user to mark an item as ''lost''', 'ppl', 'description')),
-    (38, 'SET_CIRC_MISSING', oils_i18n_gettext(38, 'Allow a user to mark an item as ''missing''', 'ppl', 'description')),
-    (39, 'SET_CIRC_CLAIMS_RETURNED', oils_i18n_gettext(39, 'Allow a user to mark an item as ''claims returned''', 'ppl', 'description')),
-    (41, 'CREATE_TRANSACTION', oils_i18n_gettext(41, 'Allow a user to create a new billable transaction', 'ppl', 'description')),
-    (42, 'VIEW_TRANSACTION', oils_i18n_gettext(42, 'Allow a user may view another user''s transactions', 'ppl', 'description')),
-    (43, 'CREATE_BILL', oils_i18n_gettext(43, 'Allow a user to create a new bill on a transaction', 'ppl', 'description')),
-    (44, 'VIEW_CONTAINER', oils_i18n_gettext(44, 'Allow a user to view another user''s containers (buckets)', 'ppl', 'description')),
-    (45, 'CREATE_CONTAINER', oils_i18n_gettext(45, 'Allow a user to create a new container for another user', 'ppl', 'description')),
-    (47, 'UPDATE_ORG_UNIT', oils_i18n_gettext(47, 'Allow a user to change the settings for an organization unit', 'ppl', 'description')),
-    (48, 'VIEW_CIRCULATIONS', oils_i18n_gettext(48, 'Allow a user to see what another user has checked out', 'ppl', 'description')),
-    (49, 'DELETE_CONTAINER', oils_i18n_gettext(49, 'Allow a user to delete another user''s container', 'ppl', 'description')),
-    (50, 'CREATE_CONTAINER_ITEM', oils_i18n_gettext(50, 'Allow a user to create a container item for another user', 'ppl', 'description')),
-    (51, 'CREATE_USER_GROUP_LINK', oils_i18n_gettext(51, 'Allow a user to add other users to permission groups', 'ppl', 'description')),
-    (52, 'REMOVE_USER_GROUP_LINK', oils_i18n_gettext(52, 'Allow a user to remove other users from permission groups', 'ppl', 'description')),
-    (53, 'VIEW_PERM_GROUPS', oils_i18n_gettext(53, 'Allow a user to view other users'' permission groups', 'ppl', 'description')),
-    (54, 'VIEW_PERMIT_CHECKOUT', oils_i18n_gettext(54, 'Allow a user to determine whether another user can check out an item.  A staff user who should be able to to check out an item to another patron will need this permission.', 'ppl', 'description')),
-    (55, 'UPDATE_BATCH_COPY', oils_i18n_gettext(55, 'Allow a user to edit copies in batch', 'ppl', 'description')),
-    (56, 'CREATE_PATRON_STAT_CAT', oils_i18n_gettext(56, 'User may create a new patron statistical category', 'ppl', 'description')),
-    (57, 'CREATE_COPY_STAT_CAT', oils_i18n_gettext(57, 'User may create a copy statistical category', 'ppl', 'description')),
-    (58, 'CREATE_PATRON_STAT_CAT_ENTRY', oils_i18n_gettext(58, 'User may create an entry in a patron statistical category', 'ppl', 'description')),
-    (59, 'CREATE_COPY_STAT_CAT_ENTRY', oils_i18n_gettext(59, 'User may create an entry in a copy statistical category', 'ppl', 'description')),
-    (60, 'UPDATE_PATRON_STAT_CAT', oils_i18n_gettext(60, 'User may update a patron statistical category', 'ppl', 'description')),
-    (61, 'UPDATE_COPY_STAT_CAT', oils_i18n_gettext(61, 'User may update a copy statistical category', 'ppl', 'description')),
-    (62, 'UPDATE_PATRON_STAT_CAT_ENTRY', oils_i18n_gettext(62, 'User may update an entry in a patron statistical category', 'ppl', 'description')),
-    (63, 'UPDATE_COPY_STAT_CAT_ENTRY', oils_i18n_gettext(63, 'User may update an entry in a copy statistical category', 'ppl', 'description')),
-    (65, 'CREATE_COPY_STAT_CAT_ENTRY_MAP', oils_i18n_gettext(65, 'User may link a copy to an entry in a statistical category', 'ppl', 'description')),
-    (64, 'CREATE_PATRON_STAT_CAT_ENTRY_MAP', oils_i18n_gettext(64, 'User may link another user to an entry in a statistical category', 'ppl', 'description')),
-    (66, 'DELETE_PATRON_STAT_CAT', oils_i18n_gettext(66, 'User may delete a patron statistical category', 'ppl', 'description')),
-    (67, 'DELETE_COPY_STAT_CAT', oils_i18n_gettext(67, 'User may delete a copy statistical category', 'ppl', 'description')),
-    (68, 'DELETE_PATRON_STAT_CAT_ENTRY', oils_i18n_gettext(68, 'User may delete an entry from a patron statistical category', 'ppl', 'description')),
-    (69, 'DELETE_COPY_STAT_CAT_ENTRY', oils_i18n_gettext(69, 'User may delete an entry from a copy statistical category', 'ppl', 'description')),
-    (70, 'DELETE_PATRON_STAT_CAT_ENTRY_MAP', oils_i18n_gettext(70, 'User may delete a patron statistical category entry map', 'ppl', 'description')),
-    (71, 'DELETE_COPY_STAT_CAT_ENTRY_MAP', oils_i18n_gettext(71, 'User may delete a copy statistical category entry map', 'ppl', 'description')),
-    (72, 'CREATE_NON_CAT_TYPE', oils_i18n_gettext(72, 'Allow a user to create a new non-cataloged item type', 'ppl', 'description')),
-    (73, 'UPDATE_NON_CAT_TYPE', oils_i18n_gettext(73, 'Allow a user to update a non-cataloged item type', 'ppl', 'description')),
-    (74, 'CREATE_IN_HOUSE_USE', oils_i18n_gettext(74, 'Allow a user to create a new in-house-use ', 'ppl', 'description')),
-    (75, 'COPY_CHECKOUT', oils_i18n_gettext(75, 'Allow a user to check out a copy', 'ppl', 'description')),
-    (76, 'CREATE_COPY_LOCATION', oils_i18n_gettext(76, 'Allow a user to create a new copy location', 'ppl', 'description')),
-    (77, 'UPDATE_COPY_LOCATION', oils_i18n_gettext(77, 'Allow a user to update a copy location', 'ppl', 'description')),
-    (78, 'DELETE_COPY_LOCATION', oils_i18n_gettext(78, 'Allow a user to delete a copy location', 'ppl', 'description')),
-    (79, 'CREATE_COPY_TRANSIT', oils_i18n_gettext(79, 'Allow a user to create a transit_copy object for transiting a copy', 'ppl', 'description')),
-    (80, 'COPY_TRANSIT_RECEIVE', oils_i18n_gettext(80, 'Allow a user to close out a transit on a copy', 'ppl', 'description')),
-    (81, 'VIEW_HOLD_PERMIT', oils_i18n_gettext(81, 'Allow a user to see if another user has permission to place a hold on a given copy.  A staff user who should be able to place a hold for another patron will need this permission.', 'ppl', 'description')),
-    (82, 'VIEW_COPY_CHECKOUT_HISTORY', oils_i18n_gettext(82, 'Allow a user to view which users have checked out a given copy', 'ppl', 'description')),
-    (83, 'REMOTE_Z3950_QUERY', oils_i18n_gettext(83, 'Allow a user to perform Z39.50 queries against remote servers', 'ppl', 'description')),
-    (84, 'REGISTER_WORKSTATION', oils_i18n_gettext(84, 'Allow a user to register a new workstation', 'ppl', 'description')),
-    (85, 'VIEW_COPY_NOTES', oils_i18n_gettext(85, 'Allow a user to view all notes attached to a copy', 'ppl', 'description')),
-    (86, 'VIEW_VOLUME_NOTES', oils_i18n_gettext(86, 'Allow a user to view all notes attached to a volume', 'ppl', 'description')),
-    (87, 'VIEW_TITLE_NOTES', oils_i18n_gettext(87, 'Allow a user to view all notes attached to a title', 'ppl', 'description')),
-    (88, 'CREATE_COPY_NOTE', oils_i18n_gettext(88, 'Allow a user to create a new copy note', 'ppl', 'description')),
-    (89, 'CREATE_VOLUME_NOTE', oils_i18n_gettext(89, 'Allow a user to create a new volume note', 'ppl', 'description')),
-    (90, 'CREATE_TITLE_NOTE', oils_i18n_gettext(90, 'Allow a user to create a new title note', 'ppl', 'description')),
-    (91, 'DELETE_COPY_NOTE', oils_i18n_gettext(91, 'Allow a user to delete another user''s copy notes', 'ppl', 'description')),
-    (92, 'DELETE_VOLUME_NOTE', oils_i18n_gettext(92, 'Allow a user to delete another user''s volume note', 'ppl', 'description')),
-    (93, 'DELETE_TITLE_NOTE', oils_i18n_gettext(93, 'Allow a user to delete another user''s title note', 'ppl', 'description')),
-    (94, 'UPDATE_CONTAINER', oils_i18n_gettext(94, 'Allow a user to update another user''s container', 'ppl', 'description')),
-    (95, 'CREATE_MY_CONTAINER', oils_i18n_gettext(95, 'Allow a user to create a container for themselves', 'ppl', 'description')),
-    (96, 'VIEW_HOLD_NOTIFICATION', oils_i18n_gettext(96, 'Allow a user to view notifications attached to a hold', 'ppl', 'description')),
-    (97, 'CREATE_HOLD_NOTIFICATION', oils_i18n_gettext(97, 'Allow a user to create new hold notifications', 'ppl', 'description')),
-    (98, 'UPDATE_ORG_SETTING', oils_i18n_gettext(98, 'Allow a user to update an organization unit setting', 'ppl', 'description')),
-    (99, 'OFFLINE_UPLOAD', oils_i18n_gettext(99, 'Allow a user to upload an offline script', 'ppl', 'description')),
-    (100, 'OFFLINE_VIEW', oils_i18n_gettext(100, 'Allow a user to view uploaded offline script information', 'ppl', 'description')),
-    (101, 'OFFLINE_EXECUTE', oils_i18n_gettext(101, 'Allow a user to execute an offline script batch', 'ppl', 'description')),
-    (102, 'CIRC_OVERRIDE_DUE_DATE', oils_i18n_gettext(102, 'Allow a user to change the due date on an item to any date', 'ppl', 'description')),
-    (103, 'CIRC_PERMIT_OVERRIDE', oils_i18n_gettext(103, 'Allow a user to bypass the circulation permit call for check out', 'ppl', 'description')),
-    (104, 'COPY_IS_REFERENCE.override', oils_i18n_gettext(104, 'Allow a user to override the copy_is_reference event', 'ppl', 'description')),
-    (105, 'VOID_BILLING', oils_i18n_gettext(105, 'Allow a user to void a bill', 'ppl', 'description')),
-    (106, 'CIRC_CLAIMS_RETURNED.override', oils_i18n_gettext(106, 'Allow a user to check in or check out an item that has a status of ''claims returned''', 'ppl', 'description')),
-    (107, 'COPY_BAD_STATUS.override', oils_i18n_gettext(107, 'Allow a user to check out an item in a non-circulatable status', 'ppl', 'description')),
-    (108, 'COPY_ALERT_MESSAGE.override', oils_i18n_gettext(108, 'Allow a user to check in/out an item that has an alert message', 'ppl', 'description')),
-    (109, 'COPY_STATUS_LOST.override', oils_i18n_gettext(109, 'Allow a user to remove the lost status from a copy', 'ppl', 'description')),
-    (110, 'COPY_STATUS_MISSING.override', oils_i18n_gettext(110, 'Allow a user to change the missing status on a copy', 'ppl', 'description')),
-    (111, 'ABORT_TRANSIT', oils_i18n_gettext(111, 'Allow a user to abort a copy transit if the user is at the transit destination or source', 'ppl', 'description')),
-    (112, 'ABORT_REMOTE_TRANSIT', oils_i18n_gettext(112, 'Allow a user to abort a copy transit if the user is not at the transit source or dest', 'ppl', 'description')),
-    (113, 'VIEW_ZIP_DATA', oils_i18n_gettext(113, 'Allow a user to query the ZIP code data method', 'ppl', 'description')),
-    (114, 'CANCEL_HOLDS', oils_i18n_gettext(114, 'Allow a user to cancel holds', 'ppl', 'description')),
-    (115, 'CREATE_DUPLICATE_HOLDS', oils_i18n_gettext(115, 'Allow a user to create duplicate holds (two or more holds on the same title)', 'ppl', 'description')),
-    (117, 'actor.org_unit.closed_date.update', oils_i18n_gettext(117, 'Allow a user to update a closed date interval for a given location', 'ppl', 'description')),
-    (116, 'actor.org_unit.closed_date.delete', oils_i18n_gettext(116, 'Allow a user to remove a closed date interval for a given location', 'ppl', 'description')),
-    (118, 'actor.org_unit.closed_date.create', oils_i18n_gettext(118, 'Allow a user to create a new closed date for a location', 'ppl', 'description')),
-    (119, 'DELETE_NON_CAT_TYPE', oils_i18n_gettext(119, 'Allow a user to delete a non cataloged type', 'ppl', 'description')),
-    (120, 'money.collections_tracker.create', oils_i18n_gettext(120, 'Allow a user to put someone into collections', 'ppl', 'description')),
-    (121, 'money.collections_tracker.delete', oils_i18n_gettext(121, 'Allow a user to remove someone from collections', 'ppl', 'description')),
-    (122, 'BAR_PATRON', oils_i18n_gettext(122, 'Allow a user to bar a patron', 'ppl', 'description')),
-    (123, 'UNBAR_PATRON', oils_i18n_gettext(123, 'Allow a user to un-bar a patron', 'ppl', 'description')),
-    (124, 'DELETE_WORKSTATION', oils_i18n_gettext(124, 'Allow a user to remove an existing workstation so a new one can replace it', 'ppl', 'description')),
-    (125, 'group_application.user', oils_i18n_gettext(125, 'Allow a user to add/remove users to/from the "User" group', 'ppl', 'description')),
-    (126, 'group_application.user.patron', oils_i18n_gettext(126, 'Allow a user to add/remove users to/from the "Patron" group', 'ppl', 'description')),
-    (127, 'group_application.user.staff', oils_i18n_gettext(127, 'Allow a user to add/remove users to/from the "Staff" group', 'ppl', 'description')),
-    (128, 'group_application.user.staff.circ', oils_i18n_gettext(128, 'Allow a user to add/remove users to/from the "Circulator" group', 'ppl', 'description')),
-    (129, 'group_application.user.staff.cat', oils_i18n_gettext(129, 'Allow a user to add/remove users to/from the "Cataloger" group', 'ppl', 'description')),
-    (130, 'group_application.user.staff.admin.global_admin', oils_i18n_gettext(130, 'Allow a user to add/remove users to/from the "GlobalAdmin" group', 'ppl', 'description')),
-    (131, 'group_application.user.staff.admin.local_admin', oils_i18n_gettext(131, 'Allow a user to add/remove users to/from the "LocalAdmin" group', 'ppl', 'description')),
-    (132, 'group_application.user.staff.admin.lib_manager', oils_i18n_gettext(132, 'Allow a user to add/remove users to/from the "LibraryManager" group', 'ppl', 'description')),
-    (133, 'group_application.user.staff.cat.cat1', oils_i18n_gettext(133, 'Allow a user to add/remove users to/from the "Cat1" group', 'ppl', 'description')),
-    (134, 'group_application.user.staff.supercat', oils_i18n_gettext(134, 'Allow a user to add/remove users to/from the "Supercat" group', 'ppl', 'description')),
-    (135, 'group_application.user.sip_client', oils_i18n_gettext(135, 'Allow a user to add/remove users to/from the "SIP-Client" group', 'ppl', 'description')),
-    (136, 'group_application.user.vendor', oils_i18n_gettext(136, 'Allow a user to add/remove users to/from the "Vendor" group', 'ppl', 'description')),
-    (137, 'ITEM_AGE_PROTECTED.override', oils_i18n_gettext(137, 'Allow a user to place a hold on an age-protected item', 'ppl', 'description')),
-    (138, 'MAX_RENEWALS_REACHED.override', oils_i18n_gettext(138, 'Allow a user to renew an item past the maximum renewal count', 'ppl', 'description')),
-    (139, 'PATRON_EXCEEDS_CHECKOUT_COUNT.override', oils_i18n_gettext(139, 'Allow staff to override checkout count failure', 'ppl', 'description')),
-    (140, 'PATRON_EXCEEDS_OVERDUE_COUNT.override', oils_i18n_gettext(140, 'Allow staff to override overdue count failure', 'ppl', 'description')),
-    (141, 'PATRON_EXCEEDS_FINES.override', oils_i18n_gettext(141, 'Allow staff to override fine amount checkout failure', 'ppl', 'description')),
-    (142, 'CIRC_EXCEEDS_COPY_RANGE.override', oils_i18n_gettext(142, 'Allow staff to override circulation copy range failure', 'ppl', 'description')),
-    (143, 'ITEM_ON_HOLDS_SHELF.override', oils_i18n_gettext(143, 'Allow staff to override item on holds shelf failure', 'ppl', 'description')),
-    (144, 'COPY_NOT_AVAILABLE.override', oils_i18n_gettext(144, 'Allow staff to force checkout of Missing/Lost type items', 'ppl', 'description')),
-    (146, 'HOLD_EXISTS.override', oils_i18n_gettext(146, 'Allow a user to place multiple holds on a single title', 'ppl', 'description')),
-    (147, 'RUN_REPORTS', oils_i18n_gettext(147, 'Allow a user to run reports', 'ppl', 'description')),
-    (148, 'SHARE_REPORT_FOLDER', oils_i18n_gettext(148, 'Allow a user to share report his own folders', 'ppl', 'description')),
-    (149, 'VIEW_REPORT_OUTPUT', oils_i18n_gettext(149, 'Allow a user to view report output', 'ppl', 'description')),
-    (150, 'COPY_CIRC_NOT_ALLOWED.override', oils_i18n_gettext(150, 'Allow a user to checkout an item that is marked as non-circ', 'ppl', 'description')),
-    (151, 'DELETE_CONTAINER_ITEM', oils_i18n_gettext(151, 'Allow a user to delete an item out of another user''s container', 'ppl', 'description')),
-    (152, 'ASSIGN_WORK_ORG_UNIT', oils_i18n_gettext(152, 'Allow a staff member to define where another staff member has their permissions', 'ppl', 'description')),
-    (153, 'CREATE_FUNDING_SOURCE', oils_i18n_gettext(153, 'Allow a user to create a new funding source', 'ppl', 'description')),
-    (154, 'DELETE_FUNDING_SOURCE', oils_i18n_gettext(154, 'Allow a user to delete a funding source', 'ppl', 'description')),
-    (155, 'VIEW_FUNDING_SOURCE', oils_i18n_gettext(155, 'Allow a user to view a funding source', 'ppl', 'description')),
-    (156, 'UPDATE_FUNDING_SOURCE', oils_i18n_gettext(156, 'Allow a user to update a funding source', 'ppl', 'description')),
-    (157, 'CREATE_FUND', oils_i18n_gettext(157, 'Allow a user to create a new fund', 'ppl', 'description')),
-    (158, 'DELETE_FUND', oils_i18n_gettext(158, 'Allow a user to delete a fund', 'ppl', 'description')),
-    (159, 'VIEW_FUND', oils_i18n_gettext(159, 'Allow a user to view a fund', 'ppl', 'description')),
-    (160, 'UPDATE_FUND', oils_i18n_gettext(160, 'Allow a user to update a fund', 'ppl', 'description')),
-    (161, 'CREATE_FUND_ALLOCATION', oils_i18n_gettext(161, 'Allow a user to create a new fund allocation', 'ppl', 'description')),
-    (162, 'DELETE_FUND_ALLOCATION', oils_i18n_gettext(162, 'Allow a user to delete a fund allocation', 'ppl', 'description')),
-    (163, 'VIEW_FUND_ALLOCATION', oils_i18n_gettext(163, 'Allow a user to view a fund allocation', 'ppl', 'description')),
-    (164, 'UPDATE_FUND_ALLOCATION', oils_i18n_gettext(164, 'Allow a user to update a fund allocation', 'ppl', 'description')),
-    (165, 'GENERAL_ACQ', oils_i18n_gettext(165, 'Lowest level permission required to access the ACQ interface', 'ppl', 'description')),
-    (166, 'CREATE_PROVIDER', oils_i18n_gettext(166, 'Allow a user to create a new provider', 'ppl', 'description')),
-    (167, 'DELETE_PROVIDER', oils_i18n_gettext(167, 'Allow a user to delate a provider', 'ppl', 'description')),
-    (168, 'VIEW_PROVIDER', oils_i18n_gettext(168, 'Allow a user to view a provider', 'ppl', 'description')),
-    (169, 'UPDATE_PROVIDER', oils_i18n_gettext(169, 'Allow a user to update a provider', 'ppl', 'description')),
-    (170, 'ADMIN_FUNDING_SOURCE', oils_i18n_gettext(170, 'Allow a user to create/view/update/delete a funding source', 'ppl', 'description')),
-    (171, 'ADMIN_FUND', oils_i18n_gettext(171, '(Deprecated) Allow a user to create/view/update/delete a fund', 'ppl', 'description')),
-    (172, 'MANAGE_FUNDING_SOURCE', oils_i18n_gettext(172, 'Allow a user to view/credit/debit a funding source', 'ppl', 'description')),
-    (173, 'MANAGE_FUND', oils_i18n_gettext(173, 'Allow a user to view/credit/debit a fund', 'ppl', 'description')),
-    (174, 'CREATE_PICKLIST', oils_i18n_gettext(174, 'Allows a user to create a picklist', 'ppl', 'description')),
-    (175, 'ADMIN_PROVIDER', oils_i18n_gettext(175, 'Allow a user to create/view/update/delete a provider', 'ppl', 'description')),
-    (176, 'MANAGE_PROVIDER', oils_i18n_gettext(176, 'Allow a user to view and purchase from a provider', 'ppl', 'description')),
-    (177, 'VIEW_PICKLIST', oils_i18n_gettext(177, 'Allow a user to view another users picklist', 'ppl', 'description')),
-    (178, 'DELETE_RECORD', oils_i18n_gettext(178, 'Allow a staff member to directly remove a bibliographic record', 'ppl', 'description')),
-    (179, 'ADMIN_CURRENCY_TYPE', oils_i18n_gettext(179, 'Allow a user to create/view/update/delete a currency_type', 'ppl', 'description')),
-    (180, 'MARK_BAD_DEBT', oils_i18n_gettext(180, 'Allow a user to mark a transaction as bad (unrecoverable) debt', 'ppl', 'description')),
-    (181, 'VIEW_BILLING_TYPE', oils_i18n_gettext(181, 'Allow a user to view billing types', 'ppl', 'description')),
-    (182, 'MARK_ITEM_AVAILABLE', oils_i18n_gettext(182, 'Allow a user to mark an item status as ''available''', 'ppl', 'description')),
-    (183, 'MARK_ITEM_CHECKED_OUT', oils_i18n_gettext(183, 'Allow a user to mark an item status as ''checked out''', 'ppl', 'description')),
-    (184, 'MARK_ITEM_BINDERY', oils_i18n_gettext(184, 'Allow a user to mark an item status as ''bindery''', 'ppl', 'description')),
-    (185, 'MARK_ITEM_LOST', oils_i18n_gettext(185, 'Allow a user to mark an item status as ''lost''', 'ppl', 'description')),
-    (186, 'MARK_ITEM_MISSING', oils_i18n_gettext(186, 'Allow a user to mark an item status as ''missing''', 'ppl', 'description')),
-    (187, 'MARK_ITEM_IN_PROCESS', oils_i18n_gettext(187, 'Allow a user to mark an item status as ''in process''', 'ppl', 'description')),
-    (188, 'MARK_ITEM_IN_TRANSIT', oils_i18n_gettext(188, 'Allow a user to mark an item status as ''in transit''', 'ppl', 'description')),
-    (189, 'MARK_ITEM_RESHELVING', oils_i18n_gettext(189, 'Allow a user to mark an item status as ''reshelving''', 'ppl', 'description')),
-    (190, 'MARK_ITEM_ON_HOLDS_SHELF', oils_i18n_gettext(190, 'Allow a user to mark an item status as ''on holds shelf''', 'ppl', 'description')),
-    (191, 'MARK_ITEM_ON_ORDER', oils_i18n_gettext(191, 'Allow a user to mark an item status as ''on order''', 'ppl', 'description')),
-    (192, 'MARK_ITEM_ILL', oils_i18n_gettext(192, 'Allow a user to mark an item status as ''inter-library loan''', 'ppl', 'description')),
-    (193, 'group_application.user.staff.acq', oils_i18n_gettext(193, 'Allows a user to add/remove/edit users in the "ACQ" group', 'ppl', 'description')),
-    (194, 'CREATE_PURCHASE_ORDER', oils_i18n_gettext(194, 'Allows a user to create a purchase order', 'ppl', 'description')),
-    (195, 'VIEW_PURCHASE_ORDER', oils_i18n_gettext(195, 'Allows a user to view a purchase order', 'ppl', 'description')),
-    (196, 'IMPORT_ACQ_LINEITEM_BIB_RECORD', oils_i18n_gettext(196, 'Allows a user to import a bib record from the acq staging area (on-order record) into the ILS bib data set', 'ppl', 'description')),
-    (197, 'RECEIVE_PURCHASE_ORDER', oils_i18n_gettext(197, 'Allows a user to mark a purchase order, lineitem, or individual copy as received', 'ppl', 'description')),
-    (198, 'VIEW_ORG_SETTINGS', oils_i18n_gettext(198, 'Allows a user to view all org settings at the specified level', 'ppl', 'description')),
-    (199, 'CREATE_MFHD_RECORD', oils_i18n_gettext(199, 'Allows a user to create a new MFHD record', 'ppl', 'description')),
-    (200, 'UPDATE_MFHD_RECORD', oils_i18n_gettext(200, 'Allows a user to update an MFHD record', 'ppl', 'description')),
-    (201, 'DELETE_MFHD_RECORD', oils_i18n_gettext(201, 'Allows a user to delete an MFHD record', 'ppl', 'description')),
-    (202, 'ADMIN_ACQ_FUND', oils_i18n_gettext(202, 'Allow a user to create/view/update/delete a fund', 'ppl', 'description')),
-    (203, 'group_application.user.staff.acq_admin', oils_i18n_gettext(203, 'Allows a user to add/remove/edit users in the "Acquisitions Administrators" group', 'ppl', 'description')),
-    (204,'ASSIGN_GROUP_PERM', oils_i18n_gettext(204,'FIXME: Need description for ASSIGN_GROUP_PERM', 'ppl', 'description')),
-    (205,'CREATE_AUDIENCE', oils_i18n_gettext(205,'FIXME: Need description for CREATE_AUDIENCE', 'ppl', 'description')),
-    (206,'CREATE_BIB_LEVEL', oils_i18n_gettext(206,'FIXME: Need description for CREATE_BIB_LEVEL', 'ppl', 'description')),
-    (207,'CREATE_CIRC_DURATION', oils_i18n_gettext(207,'FIXME: Need description for CREATE_CIRC_DURATION', 'ppl', 'description')),
-    (208,'CREATE_CIRC_MOD', oils_i18n_gettext(208,'FIXME: Need description for CREATE_CIRC_MOD', 'ppl', 'description')),
-    (209,'CREATE_COPY_STATUS', oils_i18n_gettext(209,'FIXME: Need description for CREATE_COPY_STATUS', 'ppl', 'description')),
-    (210,'CREATE_HOURS_OF_OPERATION', oils_i18n_gettext(210,'FIXME: Need description for CREATE_HOURS_OF_OPERATION', 'ppl', 'description')),
-    (211,'CREATE_ITEM_FORM', oils_i18n_gettext(211,'FIXME: Need description for CREATE_ITEM_FORM', 'ppl', 'description')),
-    (212,'CREATE_ITEM_TYPE', oils_i18n_gettext(212,'FIXME: Need description for CREATE_ITEM_TYPE', 'ppl', 'description')),
-    (213,'CREATE_LANGUAGE', oils_i18n_gettext(213,'FIXME: Need description for CREATE_LANGUAGE', 'ppl', 'description')),
-    (214,'CREATE_LASSO', oils_i18n_gettext(214,'FIXME: Need description for CREATE_LASSO', 'ppl', 'description')),
-    (215,'CREATE_LASSO_MAP', oils_i18n_gettext(215,'FIXME: Need description for CREATE_LASSO_MAP', 'ppl', 'description')),
-    (216,'CREATE_LIT_FORM', oils_i18n_gettext(216,'FIXME: Need description for CREATE_LIT_FORM', 'ppl', 'description')),
-    (217,'CREATE_METABIB_FIELD', oils_i18n_gettext(217,'FIXME: Need description for CREATE_METABIB_FIELD', 'ppl', 'description')),
-    (218,'CREATE_NET_ACCESS_LEVEL', oils_i18n_gettext(218,'FIXME: Need description for CREATE_NET_ACCESS_LEVEL', 'ppl', 'description')),
-    (219,'CREATE_ORG_ADDRESS', oils_i18n_gettext(219,'FIXME: Need description for CREATE_ORG_ADDRESS', 'ppl', 'description')),
-    (220,'CREATE_ORG_TYPE', oils_i18n_gettext(220,'FIXME: Need description for CREATE_ORG_TYPE', 'ppl', 'description')),
-    (221,'CREATE_ORG_UNIT', oils_i18n_gettext(221,'FIXME: Need description for CREATE_ORG_UNIT', 'ppl', 'description')),
-    (222,'CREATE_ORG_UNIT_CLOSING', oils_i18n_gettext(222,'FIXME: Need description for CREATE_ORG_UNIT_CLOSING', 'ppl', 'description')),
-    (223,'CREATE_PERM', oils_i18n_gettext(223,'FIXME: Need description for CREATE_PERM', 'ppl', 'description')),
-    (224,'CREATE_RELEVANCE_ADJUSTMENT', oils_i18n_gettext(224,'FIXME: Need description for CREATE_RELEVANCE_ADJUSTMENT', 'ppl', 'description')),
-    (225,'CREATE_SURVEY', oils_i18n_gettext(225,'FIXME: Need description for CREATE_SURVEY', 'ppl', 'description')),
-    (226,'CREATE_VR_FORMAT', oils_i18n_gettext(226,'FIXME: Need description for CREATE_VR_FORMAT', 'ppl', 'description')),
-    (227,'CREATE_XML_TRANSFORM', oils_i18n_gettext(227,'FIXME: Need description for CREATE_XML_TRANSFORM', 'ppl', 'description')),
-    (228,'DELETE_AUDIENCE', oils_i18n_gettext(228,'FIXME: Need description for DELETE_AUDIENCE', 'ppl', 'description')),
-    (229,'DELETE_BIB_LEVEL', oils_i18n_gettext(229,'FIXME: Need description for DELETE_BIB_LEVEL', 'ppl', 'description')),
-    (230,'DELETE_CIRC_DURATION', oils_i18n_gettext(230,'FIXME: Need description for DELETE_CIRC_DURATION', 'ppl', 'description')),
-    (231,'DELETE_CIRC_MOD', oils_i18n_gettext(231,'FIXME: Need description for DELETE_CIRC_MOD', 'ppl', 'description')),
-    (232,'DELETE_COPY_STATUS', oils_i18n_gettext(232,'FIXME: Need description for DELETE_COPY_STATUS', 'ppl', 'description')),
-    (233,'DELETE_HOURS_OF_OPERATION', oils_i18n_gettext(233,'FIXME: Need description for DELETE_HOURS_OF_OPERATION', 'ppl', 'description')),
-    (234,'DELETE_ITEM_FORM', oils_i18n_gettext(234,'FIXME: Need description for DELETE_ITEM_FORM', 'ppl', 'description')),
-    (235,'DELETE_ITEM_TYPE', oils_i18n_gettext(235,'FIXME: Need description for DELETE_ITEM_TYPE', 'ppl', 'description')),
-    (236,'DELETE_LANGUAGE', oils_i18n_gettext(236,'FIXME: Need description for DELETE_LANGUAGE', 'ppl', 'description')),
-    (237,'DELETE_LASSO', oils_i18n_gettext(237,'FIXME: Need description for DELETE_LASSO', 'ppl', 'description')),
-    (238,'DELETE_LASSO_MAP', oils_i18n_gettext(238,'FIXME: Need description for DELETE_LASSO_MAP', 'ppl', 'description')),
-    (239,'DELETE_LIT_FORM', oils_i18n_gettext(239,'FIXME: Need description for DELETE_LIT_FORM', 'ppl', 'description')),
-    (240,'DELETE_METABIB_FIELD', oils_i18n_gettext(240,'FIXME: Need description for DELETE_METABIB_FIELD', 'ppl', 'description')),
-    (241,'DELETE_NET_ACCESS_LEVEL', oils_i18n_gettext(241,'FIXME: Need description for DELETE_NET_ACCESS_LEVEL', 'ppl', 'description')),
-    (242,'DELETE_ORG_ADDRESS', oils_i18n_gettext(242,'FIXME: Need description for DELETE_ORG_ADDRESS', 'ppl', 'description')),
-    (243,'DELETE_ORG_TYPE', oils_i18n_gettext(243,'FIXME: Need description for DELETE_ORG_TYPE', 'ppl', 'description')),
-    (244,'DELETE_ORG_UNIT', oils_i18n_gettext(244,'FIXME: Need description for DELETE_ORG_UNIT', 'ppl', 'description')),
-    (245,'DELETE_ORG_UNIT_CLOSING', oils_i18n_gettext(245,'FIXME: Need description for DELETE_ORG_UNIT_CLOSING', 'ppl', 'description')),
-    (246,'DELETE_PERM', oils_i18n_gettext(246,'FIXME: Need description for DELETE_PERM', 'ppl', 'description')),
-    (247,'DELETE_RELEVANCE_ADJUSTMENT', oils_i18n_gettext(247,'FIXME: Need description for DELETE_RELEVANCE_ADJUSTMENT', 'ppl', 'description')),
-    (248,'DELETE_SURVEY', oils_i18n_gettext(248,'FIXME: Need description for DELETE_SURVEY', 'ppl', 'description')),
-    (249,'DELETE_TRANSIT', oils_i18n_gettext(249,'FIXME: Need description for DELETE_TRANSIT', 'ppl', 'description')),
-    (250,'DELETE_VR_FORMAT', oils_i18n_gettext(250,'FIXME: Need description for DELETE_VR_FORMAT', 'ppl', 'description')),
-    (251,'DELETE_XML_TRANSFORM', oils_i18n_gettext(251,'FIXME: Need description for DELETE_XML_TRANSFORM', 'ppl', 'description')),
-    (252,'REMOVE_GROUP_PERM', oils_i18n_gettext(252,'FIXME: Need description for REMOVE_GROUP_PERM', 'ppl', 'description')),
-    (253,'TRANSIT_COPY', oils_i18n_gettext(253,'FIXME: Need description for TRANSIT_COPY', 'ppl', 'description')),
-    (254,'UPDATE_AUDIENCE', oils_i18n_gettext(254,'FIXME: Need description for UPDATE_AUDIENCE', 'ppl', 'description')),
-    (255,'UPDATE_BIB_LEVEL', oils_i18n_gettext(255,'FIXME: Need description for UPDATE_BIB_LEVEL', 'ppl', 'description')),
-    (256,'UPDATE_CIRC_DURATION', oils_i18n_gettext(256,'FIXME: Need description for UPDATE_CIRC_DURATION', 'ppl', 'description')),
-    (257,'UPDATE_CIRC_MOD', oils_i18n_gettext(257,'FIXME: Need description for UPDATE_CIRC_MOD', 'ppl', 'description')),
-    (258,'UPDATE_COPY_NOTE', oils_i18n_gettext(258,'FIXME: Need description for UPDATE_COPY_NOTE', 'ppl', 'description')),
-    (259,'UPDATE_COPY_STATUS', oils_i18n_gettext(259,'FIXME: Need description for UPDATE_COPY_STATUS', 'ppl', 'description')),
-    (260,'UPDATE_GROUP_PERM', oils_i18n_gettext(260,'FIXME: Need description for UPDATE_GROUP_PERM', 'ppl', 'description')),
-    (261,'UPDATE_HOURS_OF_OPERATION', oils_i18n_gettext(261,'FIXME: Need description for UPDATE_HOURS_OF_OPERATION', 'ppl', 'description')),
-    (262,'UPDATE_ITEM_FORM', oils_i18n_gettext(262,'FIXME: Need description for UPDATE_ITEM_FORM', 'ppl', 'description')),
-    (263,'UPDATE_ITEM_TYPE', oils_i18n_gettext(263,'FIXME: Need description for UPDATE_ITEM_TYPE', 'ppl', 'description')),
-    (264,'UPDATE_LANGUAGE', oils_i18n_gettext(264,'FIXME: Need description for UPDATE_LANGUAGE', 'ppl', 'description')),
-    (265,'UPDATE_LASSO', oils_i18n_gettext(265,'FIXME: Need description for UPDATE_LASSO', 'ppl', 'description')),
-    (266,'UPDATE_LASSO_MAP', oils_i18n_gettext(266,'FIXME: Need description for UPDATE_LASSO_MAP', 'ppl', 'description')),
-    (267,'UPDATE_LIT_FORM', oils_i18n_gettext(267,'FIXME: Need description for UPDATE_LIT_FORM', 'ppl', 'description')),
-    (268,'UPDATE_METABIB_FIELD', oils_i18n_gettext(268,'FIXME: Need description for UPDATE_METABIB_FIELD', 'ppl', 'description')),
-    (269,'UPDATE_NET_ACCESS_LEVEL', oils_i18n_gettext(269,'FIXME: Need description for UPDATE_NET_ACCESS_LEVEL', 'ppl', 'description')),
-    (270,'UPDATE_ORG_ADDRESS', oils_i18n_gettext(270,'FIXME: Need description for UPDATE_ORG_ADDRESS', 'ppl', 'description')),
-    (271,'UPDATE_ORG_TYPE', oils_i18n_gettext(271,'FIXME: Need description for UPDATE_ORG_TYPE', 'ppl', 'description')),
-    (272,'UPDATE_ORG_UNIT_CLOSING', oils_i18n_gettext(272,'FIXME: Need description for UPDATE_ORG_UNIT_CLOSING', 'ppl', 'description')),
-    (273,'UPDATE_PERM', oils_i18n_gettext(273,'FIXME: Need description for UPDATE_PERM', 'ppl', 'description')),
-    (274,'UPDATE_RELEVANCE_ADJUSTMENT', oils_i18n_gettext(274,'FIXME: Need description for UPDATE_RELEVANCE_ADJUSTMENT', 'ppl', 'description')),
-    (275,'UPDATE_SURVEY', oils_i18n_gettext(275,'FIXME: Need description for UPDATE_SURVEY', 'ppl', 'description')),
-    (276,'UPDATE_TRANSIT', oils_i18n_gettext(276,'FIXME: Need description for UPDATE_TRANSIT', 'ppl', 'description')),
-    (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,'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')),
-    (284,'CREATE_AUTHORITY_IMPORT_QUEUE', oils_i18n_gettext(284,'FIXME: Need description for CREATE_AUTHORITY_IMPORT_QUEUE', 'ppl', 'description')),
-    (285,'CREATE_AUTHORITY_RECORD_NOTE', oils_i18n_gettext(285,'FIXME: Need description for CREATE_AUTHORITY_RECORD_NOTE', 'ppl', 'description')),
-    (286,'CREATE_BIB_IMPORT_FIELD_DEF', oils_i18n_gettext(286,'FIXME: Need description for CREATE_BIB_IMPORT_FIELD_DEF', 'ppl', 'description')),
-    (287,'CREATE_BIB_IMPORT_QUEUE', oils_i18n_gettext(287,'FIXME: Need description for CREATE_BIB_IMPORT_QUEUE', 'ppl', 'description')),
-    (288,'CREATE_LOCALE', oils_i18n_gettext(288,'FIXME: Need description for CREATE_LOCALE', 'ppl', 'description')),
-    (289,'CREATE_MARC_CODE', oils_i18n_gettext(289,'FIXME: Need description for CREATE_MARC_CODE', 'ppl', 'description')),
-    (290,'CREATE_TRANSLATION', oils_i18n_gettext(290,'FIXME: Need description for CREATE_TRANSLATION', 'ppl', 'description')),
-    (291,'DELETE_ACQ_FUNDING_SOURCE', oils_i18n_gettext(291,'FIXME: Need description for DELETE_ACQ_FUNDING_SOURCE', 'ppl', 'description')),
-    (292,'DELETE_AUTHORITY_IMPORT_IMPORT_FIELD_DEF', oils_i18n_gettext(292,'FIXME: Need description for DELETE_AUTHORITY_IMPORT_IMPORT_FIELD_DEF', 'ppl', 'description')),
-    (293,'DELETE_AUTHORITY_IMPORT_QUEUE', oils_i18n_gettext(293,'FIXME: Need description for DELETE_AUTHORITY_IMPORT_QUEUE', 'ppl', 'description')),
-    (294,'DELETE_AUTHORITY_RECORD_NOTE', oils_i18n_gettext(294,'FIXME: Need description for DELETE_AUTHORITY_RECORD_NOTE', 'ppl', 'description')),
-    (295,'DELETE_BIB_IMPORT_IMPORT_FIELD_DEF', oils_i18n_gettext(295,'FIXME: Need description for DELETE_BIB_IMPORT_IMPORT_FIELD_DEF', 'ppl', 'description')),
-    (296,'DELETE_BIB_IMPORT_QUEUE', oils_i18n_gettext(296,'FIXME: Need description for DELETE_BIB_IMPORT_QUEUE', 'ppl', 'description')),
-    (297,'DELETE_LOCALE', oils_i18n_gettext(297,'FIXME: Need description for DELETE_LOCALE', 'ppl', 'description')),
-    (298,'DELETE_MARC_CODE', oils_i18n_gettext(298,'FIXME: Need description for DELETE_MARC_CODE', 'ppl', 'description')),
-    (299,'DELETE_TRANSLATION', oils_i18n_gettext(299,'FIXME: Need description for DELETE_TRANSLATION', 'ppl', 'description')),
-    (300,'UPDATE_ACQ_FUNDING_SOURCE', oils_i18n_gettext(300,'FIXME: Need description for UPDATE_ACQ_FUNDING_SOURCE', 'ppl', 'description')),
-    (301,'UPDATE_AUTHORITY_IMPORT_IMPORT_FIELD_DEF', oils_i18n_gettext(301,'FIXME: Need description for UPDATE_AUTHORITY_IMPORT_IMPORT_FIELD_DEF', 'ppl', 'description')),
-    (302,'UPDATE_AUTHORITY_IMPORT_QUEUE', oils_i18n_gettext(302,'FIXME: Need description for UPDATE_AUTHORITY_IMPORT_QUEUE', 'ppl', 'description')),
-    (303,'UPDATE_AUTHORITY_RECORD_NOTE', oils_i18n_gettext(303,'FIXME: Need description for UPDATE_AUTHORITY_RECORD_NOTE', 'ppl', 'description')),
-    (304,'UPDATE_BIB_IMPORT_IMPORT_FIELD_DEF', oils_i18n_gettext(304,'FIXME: Need description for UPDATE_BIB_IMPORT_IMPORT_FIELD_DEF', 'ppl', 'description')),
-    (305,'UPDATE_BIB_IMPORT_QUEUE', oils_i18n_gettext(305,'FIXME: Need description for UPDATE_BIB_IMPORT_QUEUE', 'ppl', 'description')),
-    (306,'UPDATE_LOCALE', oils_i18n_gettext(306,'FIXME: Need description for UPDATE_LOCALE', 'ppl', 'description')),
-    (307,'UPDATE_MARC_CODE', oils_i18n_gettext(307,'FIXME: Need description for UPDATE_MARC_CODE', 'ppl', 'description')),
-    (308,'UPDATE_TRANSLATION', oils_i18n_gettext(308,'FIXME: Need description for UPDATE_TRANSLATION', 'ppl', 'description')),
-    (309,'VIEW_ACQ_FUNDING_SOURCE', oils_i18n_gettext(309,'FIXME: Need description for VIEW_ACQ_FUNDING_SOURCE', 'ppl', 'description')),
-    (310,'VIEW_AUTHORITY_RECORD_NOTES', oils_i18n_gettext(310,'FIXME: Need description for VIEW_AUTHORITY_RECORD_NOTES', 'ppl', 'description')),
-    (311,'CREATE_IMPORT_ITEM', oils_i18n_gettext(311,'FIXME: Need description for CREATE_IMPORT_ITEM', 'ppl', 'description')),
-    (312,'CREATE_IMPORT_ITEM_ATTR_DEF', oils_i18n_gettext(312,'FIXME: Need description for CREATE_IMPORT_ITEM_ATTR_DEF', 'ppl', 'description')),
-    (313,'CREATE_IMPORT_TRASH_FIELD', oils_i18n_gettext(313,'FIXME: Need description for CREATE_IMPORT_TRASH_FIELD', 'ppl', 'description')),
-    (314,'DELETE_IMPORT_ITEM', oils_i18n_gettext(314,'FIXME: Need description for DELETE_IMPORT_ITEM', 'ppl', 'description')),
-    (315,'DELETE_IMPORT_ITEM_ATTR_DEF', oils_i18n_gettext(315,'FIXME: Need description for DELETE_IMPORT_ITEM_ATTR_DEF', 'ppl', 'description')),
-    (316,'DELETE_IMPORT_TRASH_FIELD', oils_i18n_gettext(316,'FIXME: Need description for DELETE_IMPORT_TRASH_FIELD', 'ppl', 'description')),
-    (317,'UPDATE_IMPORT_ITEM', oils_i18n_gettext(317,'FIXME: Need description for UPDATE_IMPORT_ITEM', 'ppl', 'description')),
-    (318,'UPDATE_IMPORT_ITEM_ATTR_DEF', oils_i18n_gettext(318,'FIXME: Need description for UPDATE_IMPORT_ITEM_ATTR_DEF', 'ppl', 'description')),
-    (319,'UPDATE_IMPORT_TRASH_FIELD', oils_i18n_gettext(319,'FIXME: Need description for UPDATE_IMPORT_TRASH_FIELD', 'ppl', 'description')),
-
--- ORG UNIT Settings
-    (320,'UPDATE_ORG_UNIT_SETTING_ALL', oils_i18n_gettext(320,'FIXME: Need description for UPDATE_ORG_UNIT_SETTING_ALL', 'ppl', 'description')),
-    (321,'UPDATE_ORG_UNIT_SETTING.circ.lost_materials_processing_fee', oils_i18n_gettext(321,'FIXME: Need description for UPDATE_ORG_UNIT_SETTING.circ.lost_materials_processing_fee', 'ppl', 'description')),
-    (322,'UPDATE_ORG_UNIT_SETTING.cat.default_item_price', oils_i18n_gettext(322,'FIXME: Need description for UPDATE_ORG_UNIT_SETTING.cat.default_item_price', 'ppl', 'description')),
-    (323,'UPDATE_ORG_UNIT_SETTING.auth.opac_timeout', oils_i18n_gettext(323,'FIXME: Need description for UPDATE_ORG_UNIT_SETTING.auth.opac_timeout', 'ppl', 'description')),
-    (324,'UPDATE_ORG_UNIT_SETTING.auth.staff_timeout', oils_i18n_gettext(324,'FIXME: Need description for UPDATE_ORG_UNIT_SETTING.auth.staff_timeout', 'ppl', 'description')),
-    (325,'UPDATE_ORG_UNIT_SETTING.org.bounced_emails', oils_i18n_gettext(325,'FIXME: Need description for UPDATE_ORG_UNIT_SETTING.org.bounced_emails', 'ppl', 'description')),
-    (326,'UPDATE_ORG_UNIT_SETTING.circ.hold_expire_alert_interval', oils_i18n_gettext(326,'FIXME: Need description for UPDATE_ORG_UNIT_SETTING.circ.hold_expire_alert_interval', 'ppl', 'description')),
-    (327,'UPDATE_ORG_UNIT_SETTING.circ.hold_expire_interval', oils_i18n_gettext(327,'FIXME: Need description for UPDATE_ORG_UNIT_SETTING.circ.hold_expire_interval', 'ppl', 'description')),
-    (328,'UPDATE_ORG_UNIT_SETTING.credit.payments.allow', oils_i18n_gettext(328,'FIXME: Need description for UPDATE_ORG_UNIT_SETTING.credit.payments.allow', 'ppl', 'description')),
-    (329,'UPDATE_ORG_UNIT_SETTING.circ.void_overdue_on_lost', oils_i18n_gettext(329,'FIXME: Need description for UPDATE_ORG_UNIT_SETTING.circ.void_overdue_on_lost', 'ppl', 'description')),
-    (330,'UPDATE_ORG_UNIT_SETTING.circ.hold_stalling.soft', oils_i18n_gettext(330,'FIXME: Need description for UPDATE_ORG_UNIT_SETTING.circ.hold_stalling.soft', 'ppl', 'description')),
-    (331,'UPDATE_ORG_UNIT_SETTING.circ.hold_boundary.hard', oils_i18n_gettext(331,'FIXME: Need description for UPDATE_ORG_UNIT_SETTING.circ.hold_boundary.hard', 'ppl', 'description')),
-    (332,'UPDATE_ORG_UNIT_SETTING.circ.hold_boundary.soft', oils_i18n_gettext(332,'FIXME: Need description for UPDATE_ORG_UNIT_SETTING.circ.hold_boundary.soft', 'ppl', 'description')),
-    (333,'UPDATE_ORG_UNIT_SETTING.opac.barcode_regex', oils_i18n_gettext(333,'FIXME: Need description for UPDATE_ORG_UNIT_SETTING.opac.barcode_regex', 'ppl', 'description')),
-    (334,'UPDATE_ORG_UNIT_SETTING.global.password_regex', oils_i18n_gettext(334,'FIXME: Need description for UPDATE_ORG_UNIT_SETTING.global.password_regex', 'ppl', 'description')),
-    (335,'UPDATE_ORG_UNIT_SETTING.circ.item_checkout_history.max', oils_i18n_gettext(335,'FIXME: Need description for UPDATE_ORG_UNIT_SETTING.circ.item_checkout_history.max', 'ppl', 'description')),
-    (336,'UPDATE_ORG_UNIT_SETTING.circ.reshelving_complete.interval', oils_i18n_gettext(336,'FIXME: Need description for UPDATE_ORG_UNIT_SETTING.circ.reshelving_complete.interval', 'ppl', 'description')),
-    (337,'UPDATE_ORG_UNIT_SETTING.circ.selfcheck.patron_login_timeout', oils_i18n_gettext(337,'FIXME: Need description for UPDATE_ORG_UNIT_SETTING.circ.selfcheck.patron_login_timeout', 'ppl', 'description')),
-    (338,'UPDATE_ORG_UNIT_SETTING.circ.selfcheck.alert_on_checkout_event', oils_i18n_gettext(338,'FIXME: Need description for UPDATE_ORG_UNIT_SETTING.circ.selfcheck.alert_on_checkout_event', 'ppl', 'description')),
-    (339,'UPDATE_ORG_UNIT_SETTING.circ.selfcheck.require_patron_password', oils_i18n_gettext(339,'FIXME: Need description for UPDATE_ORG_UNIT_SETTING.circ.selfcheck.require_patron_password', 'ppl', 'description')),
-    (340,'UPDATE_ORG_UNIT_SETTING.global.juvenile_age_threshold', oils_i18n_gettext(340,'FIXME: Need description for UPDATE_ORG_UNIT_SETTING.global.juvenile_age_threshold', 'ppl', 'description')),
-    (341,'UPDATE_ORG_UNIT_SETTING.cat.bib.keep_on_empty', oils_i18n_gettext(341,'FIXME: Need description for UPDATE_ORG_UNIT_SETTING.cat.bib.keep_on_empty', 'ppl', 'description')),
-    (342,'UPDATE_ORG_UNIT_SETTING.cat.bib.alert_on_empty', oils_i18n_gettext(342,'FIXME: Need description for UPDATE_ORG_UNIT_SETTING.cat.bib.alert_on_empty', 'ppl', 'description')),
-    (343,'UPDATE_ORG_UNIT_SETTING.patron.password.use_phone', oils_i18n_gettext(343,'FIXME: Need description for UPDATE_ORG_UNIT_SETTING.patron.password.use_phone', 'ppl', 'description')),
-
--- perm to override max claims returned
-    (344,'SET_CIRC_CLAIMS_RETURNED.override', oils_i18n_gettext(344,'Allows staff to override the max claims returned value for a patron', 'ppl', 'description')),
-    (345,'UPDATE_PATRON_CLAIM_RETURN_COUNT', oils_i18n_gettext(345,'Allows staff to manually change a patron''s claims returned count', 'ppl', 'description')),
-
-    (346,'UPDATE_BILL_NOTE', oils_i18n_gettext(346,'Allows staff to edit the note for a bill on a transaction', 'ppl', 'description')),
-    (347,'UPDATE_PAYMENT_NOTE', oils_i18n_gettext(347,'Allows staff to edit the note for a payment on a transaction', 'ppl', 'description')),
-    (348, 'UPDATE_RECORD', oils_i18n_gettext(348, 'Allow a user to update and undelete records.', 'ppl', 'description')),
-    (349, 'UPDATE_PATRON_CLAIM_NEVER_CHECKED_OUT_COUNT', oils_i18n_gettext(349,'Allows staff to manually change a patron''s claims never checkout out count', 'ppl', 'description')),
-    (350, 'ADMIN_COPY_LOCATION_ORDER', oils_i18n_gettext(350, 'Allow a user to create/view/update/delete a copy location order', 'ppl', 'description')),
-
--- additional permissions
-    (352, 'ADMIN_BOOKING_RESOURCE', oils_i18n_gettext(352, 'Enables the user to create/update/delete booking resources', 'ppl', 'description')),
-    (353, 'ADMIN_BOOKING_RESOURCE_TYPE', oils_i18n_gettext(353, 'Enables the user to create/update/delete booking resource types', 'ppl', 'description')),
-    (354, 'ADMIN_BOOKING_RESOURCE_ATTR', oils_i18n_gettext(354, 'Enables the user to create/update/delete booking resource attributes', 'ppl', 'description')),
-    (355, 'ADMIN_BOOKING_RESOURCE_ATTR_MAP', oils_i18n_gettext(355, 'Enables the user to create/update/delete booking resource attribute maps', 'ppl', 'description')),
-    (356, 'ADMIN_BOOKING_RESOURCE_ATTR_VALUE', oils_i18n_gettext(356, 'Enables the user to create/update/delete booking resource attribute values', 'ppl', 'description')),
-    (357, 'ADMIN_BOOKING_RESERVATION', oils_i18n_gettext(357, 'Enables the user to create/update/delete booking reservations', 'ppl', 'description')),
-    (358, 'ADMIN_BOOKING_RESERVATION_ATTR_VALUE_MAP', oils_i18n_gettext(358, 'Enables the user to create/update/delete booking reservation attribute value maps', 'ppl', 'description')),
-    (359, 'HOLD_ITEM_CHECKED_OUT.override', oils_i18n_gettext(359, 'Allows a user to place a hold on an item that they already have checked out', 'ppl', 'description')),
-    (360, 'RETRIEVE_RESERVATION_PULL_LIST', oils_i18n_gettext(360, 'Allows a user to retrieve a booking reservation pull list', 'ppl', 'description')),
-    (361, 'CAPTURE_RESERVATION', oils_i18n_gettext(361, 'Allows a user to capture booking reservations', 'ppl', 'description')),
-    (362, 'MERGE_USERS', oils_i18n_gettext(362, 'Allows user records to be merged', 'ppl', 'description')),
-    (363, 'ALLOW_ALT_TCN', oils_i18n_gettext(363, 'Allows staff to import a record using an alternate TCN to avoid conflicts', 'ppl', 'description')),
-    (364, 'ADMIN_TRIGGER_EVENT_DEF', oils_i18n_gettext(364, 'Allow a user to administer trigger event definitions', 'ppl', 'description')),
-    (365, 'ADMIN_ACQ_CANCEL_CAUSE', oils_i18n_gettext(365, 'Allow a user to create/update/delete reasons for order cancellations', 'ppl', 'description')),
-    (366, 'ADMIN_TRIGGER_CLEANUP', oils_i18n_gettext(366, 'Allow a user to create, delete, and update trigger cleanup entries', 'ppl', 'description')),
-    (367, 'CREATE_TRIGGER_CLEANUP', oils_i18n_gettext(367, 'Allow a user to create trigger cleanup entries', 'ppl', 'description')),
-    (368, 'DELETE_TRIGGER_CLEANUP', oils_i18n_gettext(368, 'Allow a user to delete trigger cleanup entries', 'ppl', 'description')),
-    (369, 'UPDATE_TRIGGER_CLEANUP', oils_i18n_gettext(369, 'Allow a user to update trigger cleanup entries', 'ppl', 'description')),
-    (370, 'CREATE_TRIGGER_EVENT_DEF', oils_i18n_gettext(370, 'Allow a user to create trigger event definitions', 'ppl', 'description')),
-    (371, 'DELETE_TRIGGER_EVENT_DEF', oils_i18n_gettext(371, 'Allow a user to delete trigger event definitions', 'ppl', 'description')),
-    (372, 'UPDATE_TRIGGER_EVENT_DEF', oils_i18n_gettext(372, 'Allow a user to update trigger event definitions', 'ppl', 'description')),
-    (373, 'VIEW_TRIGGER_EVENT_DEF', oils_i18n_gettext(373, 'Allow a user to view trigger event definitions', 'ppl', 'description')),
-    (374, 'ADMIN_TRIGGER_HOOK', oils_i18n_gettext(374, 'Allow a user to create, update, and delete trigger hooks', 'ppl', 'description')),
-    (375, 'CREATE_TRIGGER_HOOK', oils_i18n_gettext(375, 'Allow a user to create trigger hooks', 'ppl', 'description')),
-    (376, 'DELETE_TRIGGER_HOOK', oils_i18n_gettext(376, 'Allow a user to delete trigger hooks', 'ppl', 'description')),
-    (377, 'UPDATE_TRIGGER_HOOK', oils_i18n_gettext(377, 'Allow a user to update trigger hooks', 'ppl', 'description')),
-    (378, 'ADMIN_TRIGGER_REACTOR', oils_i18n_gettext(378, 'Allow a user to create, update, and delete trigger reactors', 'ppl', 'description')),
-    (379, 'CREATE_TRIGGER_REACTOR', oils_i18n_gettext(379, 'Allow a user to create trigger reactors', 'ppl', 'description')),
-    (380, 'DELETE_TRIGGER_REACTOR', oils_i18n_gettext(380, 'Allow a user to delete trigger reactors', 'ppl', 'description')),
-    (381, 'UPDATE_TRIGGER_REACTOR', oils_i18n_gettext(381, 'Allow a user to update trigger reactors', 'ppl', 'description')),
-    (382, 'ADMIN_TRIGGER_TEMPLATE_OUTPUT', oils_i18n_gettext(382, 'Allow a user to delete trigger template output', 'ppl', 'description')),
-    (383, 'DELETE_TRIGGER_TEMPLATE_OUTPUT', oils_i18n_gettext(383, 'Allow a user to delete trigger template output', 'ppl', 'description')),
-    (384, 'ADMIN_TRIGGER_VALIDATOR', oils_i18n_gettext(384, 'Allow a user to create, update, and delete trigger validators', 'ppl', 'description')),
-    (385, 'CREATE_TRIGGER_VALIDATOR', oils_i18n_gettext(385, 'Allow a user to create trigger validators', 'ppl', 'description')),
-    (386, 'DELETE_TRIGGER_VALIDATOR', oils_i18n_gettext(386, 'Allow a user to delete trigger validators', 'ppl', 'description')),
-    (387, 'UPDATE_TRIGGER_VALIDATOR', oils_i18n_gettext(387, 'Allow a user to update trigger validators', 'ppl', 'description')),
-    (388, 'UPDATE_ORG_UNIT_SETTING.circ.block_renews_for_holds', oils_i18n_gettext(388, 'Allow a user to enable blocking of renews on items that could fulfill holds', 'ppl', 'description')),
-    (389, 'ACQ_XFER_MANUAL_DFUND_AMOUNT', oils_i18n_gettext(389, 'Allow a user to transfer different amounts of money out of one fund and into another', 'ppl', 'description')),
-    (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'))
-    ,(402, 'ADMIN_ACQ_DISTRIB_FORMULA', oils_i18n_gettext(402, 'Create/update/delete distribution formulae', 'ppl', 'description'))
-    ,(403, 'ADMIN_ACQ_CLAIM', oils_i18n_gettext(403, 'Create/update/delete acquisitions claims', 'ppl', 'description'))
-    ,(404, 'ADMIN_ACQ_CLAIM_EVENT_TYPE', oils_i18n_gettext(404, 'Create/update/delete acquisitions claim event types', 'ppl', 'description'))
-    ,(405, 'ADMIN_ACQ_CLAIM_TYPE', oils_i18n_gettext(405, 'Create/update/delete acquisitions claim types', 'ppl', 'description'))
-    ,(406, 'ADMIN_ACQ_FISCAL_YEAR', oils_i18n_gettext(406, 'Create/update/delete acquisitions fiscal years', 'ppl', 'description'))
-    ,(407, 'ADMIN_ACQ_FUND_ALLOCATION_PERCENT', oils_i18n_gettext(407, 'Create/update/delete acquisitions fund allocation percentages', 'ppl', 'description'))
-    ,(408, 'ADMIN_ACQ_FUND_TAG', oils_i18n_gettext(408, 'Create/update/delete acquisitions fund tags', 'ppl', 'description'))
-    ,(409, 'ADMIN_ACQ_LINEITEM_ALERT_TEXT', oils_i18n_gettext(409, 'Create/update/delete acquisitions lineitem alert text', 'ppl', 'description'))
-
-;
+INSERT INTO permission.perm_list ( id, code, description ) VALUES
+ ( -1, 'EVERYTHING', oils_i18n_gettext( -1, 
+    'EVERYTHING', 'ppl', 'description' )),
+ ( 1, 'OPAC_LOGIN', oils_i18n_gettext( 1, 
+    'Allow a user to log in to the OPAC', 'ppl', 'description' )),
+ ( 2, 'STAFF_LOGIN', oils_i18n_gettext( 2, 
+    'Allow a user to log in to the staff client', 'ppl', 'description' )),
+ ( 3, 'MR_HOLDS', oils_i18n_gettext( 3, 
+    'Allow a user to create a metarecord holds', 'ppl', 'description' )),
+ ( 4, 'TITLE_HOLDS', oils_i18n_gettext( 4, 
+    'Allow a user to place a hold at the title level', 'ppl', 'description' )),
+ ( 5, 'VOLUME_HOLDS', oils_i18n_gettext( 5, 
+    'Allow a user to place a volume level hold', 'ppl', 'description' )),
+ ( 6, 'COPY_HOLDS', oils_i18n_gettext( 6, 
+    'Allow a user to place a hold on a specific copy', 'ppl', 'description' )),
+ ( 7, 'REQUEST_HOLDS', oils_i18n_gettext( 7, 
+    '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)', 'ppl', 'description' )),
+ ( 8, 'REQUEST_HOLDS_OVERRIDE', oils_i18n_gettext( 8, 
+    '* no longer applicable', 'ppl', 'description' )),
+ ( 9, 'VIEW_HOLD', oils_i18n_gettext( 9, 
+    'Allow a user to view another user''s holds', 'ppl', 'description' )),
+ ( 10, 'DELETE_HOLDS', oils_i18n_gettext( 10, 
+    '* no longer applicable', 'ppl', 'description' )),
+ ( 11, 'UPDATE_HOLD', oils_i18n_gettext( 11, 
+    'Allow a user to update another user''s hold', 'ppl', 'description' )),
+ ( 12, 'RENEW_CIRC', oils_i18n_gettext( 12, 
+    'Allow a user to renew items', 'ppl', 'description' )),
+ ( 13, 'VIEW_USER_FINES_SUMMARY', oils_i18n_gettext( 13, 
+    'Allow a user to view bill details', 'ppl', 'description' )),
+ ( 14, 'VIEW_USER_TRANSACTIONS', oils_i18n_gettext( 14, 
+    'Allow a user to see another user''s grocery or circulation transactions in the Bills Interface; duplicate of VIEW_TRANSACTION', 'ppl', 'description' )),
+ ( 15, 'UPDATE_MARC', oils_i18n_gettext( 15, 
+    'Allow a user to edit a MARC record', 'ppl', 'description' )),
+ ( 16, 'CREATE_MARC', oils_i18n_gettext( 16, 
+    'Allow a user to create new MARC records', 'ppl', 'description' )),
+ ( 17, 'IMPORT_MARC', oils_i18n_gettext( 17, 
+    'Allow a user to import a MARC record via the Z39.50 interface', 'ppl', 'description' )),
+ ( 18, 'CREATE_VOLUME', oils_i18n_gettext( 18, 
+    'Allow a user to create a volume', 'ppl', 'description' )),
+ ( 19, 'UPDATE_VOLUME', oils_i18n_gettext( 19, 
+    '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.', 'ppl', 'description' )),
+ ( 20, 'DELETE_VOLUME', oils_i18n_gettext( 20, 
+    'Allow a user to delete a volume', 'ppl', 'description' )),
+ ( 21, 'CREATE_COPY', oils_i18n_gettext( 21, 
+    'Allow a user to create a new copy object', 'ppl', 'description' )),
+ ( 22, 'UPDATE_COPY', oils_i18n_gettext( 22, 
+    'Allow a user to edit a copy', 'ppl', 'description' )),
+ ( 23, 'DELETE_COPY', oils_i18n_gettext( 23, 
+    'Allow a user to delete a copy', 'ppl', 'description' )),
+ ( 24, 'RENEW_HOLD_OVERRIDE', oils_i18n_gettext( 24, 
+    'Allow a user to continue to renew an item even if it is required for a hold', 'ppl', 'description' )),
+ ( 25, 'CREATE_USER', oils_i18n_gettext( 25, 
+    'Allow a user to create another user', 'ppl', 'description' )),
+ ( 26, 'UPDATE_USER', oils_i18n_gettext( 26, 
+    'Allow a user to edit a user''s record', 'ppl', 'description' )),
+ ( 27, 'DELETE_USER', oils_i18n_gettext( 27, 
+    'Allow a user to mark a user as deleted', 'ppl', 'description' )),
+ ( 28, 'VIEW_USER', oils_i18n_gettext( 28, 
+    'Allow a user to view another user''s Patron Record', 'ppl', 'description' )),
+ ( 29, 'COPY_CHECKIN', oils_i18n_gettext( 29, 
+    'Allow a user to check in a copy', 'ppl', 'description' )),
+ ( 30, 'CREATE_TRANSIT', oils_i18n_gettext( 30, 
+    'Allow a user to place an item in transit', 'ppl', 'description' )),
+ ( 31, 'VIEW_PERMISSION', oils_i18n_gettext( 31, 
+    'Allow a user to view user permissions within the user permissions editor', 'ppl', 'description' )),
+ ( 32, 'CHECKIN_BYPASS_HOLD_FULFILL', oils_i18n_gettext( 32, 
+    '* no longer applicable', 'ppl', 'description' )),
+ ( 33, 'CREATE_PAYMENT', oils_i18n_gettext( 33, 
+    'Allow a user to record payments in the Billing Interface', 'ppl', 'description' )),
+ ( 34, 'SET_CIRC_LOST', oils_i18n_gettext( 34, 
+    'Allow a user to mark an item as ''lost''', 'ppl', 'description' )),
+ ( 35, 'SET_CIRC_MISSING', oils_i18n_gettext( 35, 
+    'Allow a user to mark an item as ''missing''', 'ppl', 'description' )),
+ ( 36, 'SET_CIRC_CLAIMS_RETURNED', oils_i18n_gettext( 36, 
+    'Allow a user to mark an item as ''claims returned''', 'ppl', 'description' )),
+ ( 37, 'CREATE_TRANSACTION', oils_i18n_gettext( 37, 
+    'Allow a user to create a new billable transaction', 'ppl', 'description' )),
+ ( 38, 'VIEW_TRANSACTION', oils_i18n_gettext( 38, 
+    'Allow a user may view another user''s transactions', 'ppl', 'description' )),
+ ( 39, 'CREATE_BILL', oils_i18n_gettext( 39, 
+    'Allow a user to create a new bill on a transaction', 'ppl', 'description' )),
+ ( 40, 'VIEW_CONTAINER', oils_i18n_gettext( 40, 
+    'Allow a user to view another user''s containers (buckets)', 'ppl', 'description' )),
+ ( 41, 'CREATE_CONTAINER', oils_i18n_gettext( 41, 
+    'Allow a user to create a new container for another user', 'ppl', 'description' )),
+ ( 42, 'UPDATE_ORG_UNIT', oils_i18n_gettext( 42, 
+    'Allow a user to change the settings for an organization unit', 'ppl', 'description' )),
+ ( 43, 'VIEW_CIRCULATIONS', oils_i18n_gettext( 43, 
+    'Allow a user to see what another user has checked out', 'ppl', 'description' )),
+ ( 44, 'DELETE_CONTAINER', oils_i18n_gettext( 44, 
+    'Allow a user to delete another user''s container', 'ppl', 'description' )),
+ ( 45, 'CREATE_CONTAINER_ITEM', oils_i18n_gettext( 45, 
+    'Allow a user to create a container item for another user', 'ppl', 'description' )),
+ ( 46, 'CREATE_USER_GROUP_LINK', oils_i18n_gettext( 46, 
+    'Allow a user to add other users to permission groups', 'ppl', 'description' )),
+ ( 47, 'REMOVE_USER_GROUP_LINK', oils_i18n_gettext( 47, 
+    'Allow a user to remove other users from permission groups', 'ppl', 'description' )),
+ ( 48, 'VIEW_PERM_GROUPS', oils_i18n_gettext( 48, 
+    'Allow a user to view other users'' permission groups', 'ppl', 'description' )),
+ ( 49, 'VIEW_PERMIT_CHECKOUT', oils_i18n_gettext( 49, 
+    'Allow a user to determine whether another user can check out an item', 'ppl', 'description' )),
+ ( 50, 'UPDATE_BATCH_COPY', oils_i18n_gettext( 50, 
+    'Allow a user to edit copies in batch', 'ppl', 'description' )),
+ ( 51, 'CREATE_PATRON_STAT_CAT', oils_i18n_gettext( 51, 
+    'User may create a new patron statistical category', 'ppl', 'description' )),
+ ( 52, 'CREATE_COPY_STAT_CAT', oils_i18n_gettext( 52, 
+    'User may create a copy statistical category', 'ppl', 'description' )),
+ ( 53, 'CREATE_PATRON_STAT_CAT_ENTRY', oils_i18n_gettext( 53, 
+    'User may create an entry in a patron statistical category', 'ppl', 'description' )),
+ ( 54, 'CREATE_COPY_STAT_CAT_ENTRY', oils_i18n_gettext( 54, 
+    'User may create an entry in a copy statistical category', 'ppl', 'description' )),
+ ( 55, 'UPDATE_PATRON_STAT_CAT', oils_i18n_gettext( 55, 
+    'User may update a patron statistical category', 'ppl', 'description' )),
+ ( 56, 'UPDATE_COPY_STAT_CAT', oils_i18n_gettext( 56, 
+    'User may update a copy statistical category', 'ppl', 'description' )),
+ ( 57, 'UPDATE_PATRON_STAT_CAT_ENTRY', oils_i18n_gettext( 57, 
+    'User may update an entry in a patron statistical category', 'ppl', 'description' )),
+ ( 58, 'UPDATE_COPY_STAT_CAT_ENTRY', oils_i18n_gettext( 58, 
+    'User may update an entry in a copy statistical category', 'ppl', 'description' )),
+ ( 59, 'CREATE_PATRON_STAT_CAT_ENTRY_MAP', oils_i18n_gettext( 59, 
+    'User may link another user to an entry in a statistical category', 'ppl', 'description' )),
+ ( 60, 'CREATE_COPY_STAT_CAT_ENTRY_MAP', oils_i18n_gettext( 60, 
+    'User may link a copy to an entry in a statistical category', 'ppl', 'description' )),
+ ( 61, 'DELETE_PATRON_STAT_CAT', oils_i18n_gettext( 61, 
+    'User may delete a patron statistical category', 'ppl', 'description' )),
+ ( 62, 'DELETE_COPY_STAT_CAT', oils_i18n_gettext( 62, 
+    'User may delete a copy statistical category', 'ppl', 'description' )),
+ ( 63, 'DELETE_PATRON_STAT_CAT_ENTRY', oils_i18n_gettext( 63, 
+    'User may delete an entry from a patron statistical category', 'ppl', 'description' )),
+ ( 64, 'DELETE_COPY_STAT_CAT_ENTRY', oils_i18n_gettext( 64, 
+    'User may delete an entry from a copy statistical category', 'ppl', 'description' )),
+ ( 65, 'DELETE_PATRON_STAT_CAT_ENTRY_MAP', oils_i18n_gettext( 65, 
+    'User may delete a patron statistical category entry map', 'ppl', 'description' )),
+ ( 66, 'DELETE_COPY_STAT_CAT_ENTRY_MAP', oils_i18n_gettext( 66, 
+    'User may delete a copy statistical category entry map', 'ppl', 'description' )),
+ ( 67, 'CREATE_NON_CAT_TYPE', oils_i18n_gettext( 67, 
+    'Allow a user to create a new non-cataloged item type', 'ppl', 'description' )),
+ ( 68, 'UPDATE_NON_CAT_TYPE', oils_i18n_gettext( 68, 
+    'Allow a user to update a non-cataloged item type', 'ppl', 'description' )),
+ ( 69, 'CREATE_IN_HOUSE_USE', oils_i18n_gettext( 69, 
+    'Allow a user to create a new in-house-use ', 'ppl', 'description' )),
+ ( 70, 'COPY_CHECKOUT', oils_i18n_gettext( 70, 
+    'Allow a user to check out a copy', 'ppl', 'description' )),
+ ( 71, 'CREATE_COPY_LOCATION', oils_i18n_gettext( 71, 
+    'Allow a user to create a new copy location', 'ppl', 'description' )),
+ ( 72, 'UPDATE_COPY_LOCATION', oils_i18n_gettext( 72, 
+    'Allow a user to update a copy location', 'ppl', 'description' )),
+ ( 73, 'DELETE_COPY_LOCATION', oils_i18n_gettext( 73, 
+    'Allow a user to delete a copy location', 'ppl', 'description' )),
+ ( 74, 'CREATE_COPY_TRANSIT', oils_i18n_gettext( 74, 
+    'Allow a user to create a transit_copy object for transiting a copy', 'ppl', 'description' )),
+ ( 75, 'COPY_TRANSIT_RECEIVE', oils_i18n_gettext( 75, 
+    'Allow a user to close out a transit on a copy', 'ppl', 'description' )),
+ ( 76, 'VIEW_HOLD_PERMIT', oils_i18n_gettext( 76, 
+    'Allow a user to see if another user has permission to place a hold on a given copy', 'ppl', 'description' )),
+ ( 77, 'VIEW_COPY_CHECKOUT_HISTORY', oils_i18n_gettext( 77, 
+    'Allow a user to view which users have checked out a given copy', 'ppl', 'description' )),
+ ( 78, 'REMOTE_Z3950_QUERY', oils_i18n_gettext( 78, 
+    'Allow a user to perform Z39.50 queries against remote servers', 'ppl', 'description' )),
+ ( 79, 'REGISTER_WORKSTATION', oils_i18n_gettext( 79, 
+    'Allow a user to register a new workstation', 'ppl', 'description' )),
+ ( 80, 'VIEW_COPY_NOTES', oils_i18n_gettext( 80, 
+    'Allow a user to view all notes attached to a copy', 'ppl', 'description' )),
+ ( 81, 'VIEW_VOLUME_NOTES', oils_i18n_gettext( 81, 
+    'Allow a user to view all notes attached to a volume', 'ppl', 'description' )),
+ ( 82, 'VIEW_TITLE_NOTES', oils_i18n_gettext( 82, 
+    'Allow a user to view all notes attached to a title', 'ppl', 'description' )),
+ ( 83, 'CREATE_COPY_NOTE', oils_i18n_gettext( 83, 
+    'Allow a user to create a new copy note', 'ppl', 'description' )),
+ ( 84, 'CREATE_VOLUME_NOTE', oils_i18n_gettext( 84, 
+    'Allow a user to create a new volume note', 'ppl', 'description' )),
+ ( 85, 'CREATE_TITLE_NOTE', oils_i18n_gettext( 85, 
+    'Allow a user to create a new title note', 'ppl', 'description' )),
+ ( 86, 'DELETE_COPY_NOTE', oils_i18n_gettext( 86, 
+    'Allow a user to delete another user''s copy notes', 'ppl', 'description' )),
+ ( 87, 'DELETE_VOLUME_NOTE', oils_i18n_gettext( 87, 
+    'Allow a user to delete another user''s volume note', 'ppl', 'description' )),
+ ( 88, 'DELETE_TITLE_NOTE', oils_i18n_gettext( 88, 
+    'Allow a user to delete another user''s title note', 'ppl', 'description' )),
+ ( 89, 'UPDATE_CONTAINER', oils_i18n_gettext( 89, 
+    'Allow a user to update another user''s container', 'ppl', 'description' )),
+ ( 90, 'CREATE_MY_CONTAINER', oils_i18n_gettext( 90, 
+    'Allow a user to create a container for themselves', 'ppl', 'description' )),
+ ( 91, 'VIEW_HOLD_NOTIFICATION', oils_i18n_gettext( 91, 
+    'Allow a user to view notifications attached to a hold', 'ppl', 'description' )),
+ ( 92, 'CREATE_HOLD_NOTIFICATION', oils_i18n_gettext( 92, 
+    'Allow a user to create new hold notifications', 'ppl', 'description' )),
+ ( 93, 'UPDATE_ORG_SETTING', oils_i18n_gettext( 93, 
+    'Allow a user to update an organization unit setting', 'ppl', 'description' )),
+ ( 94, 'OFFLINE_UPLOAD', oils_i18n_gettext( 94, 
+    'Allow a user to upload an offline script', 'ppl', 'description' )),
+ ( 95, 'OFFLINE_VIEW', oils_i18n_gettext( 95, 
+    'Allow a user to view uploaded offline script information', 'ppl', 'description' )),
+ ( 96, 'OFFLINE_EXECUTE', oils_i18n_gettext( 96, 
+    'Allow a user to execute an offline script batch', 'ppl', 'description' )),
+ ( 97, 'CIRC_OVERRIDE_DUE_DATE', oils_i18n_gettext( 97, 
+    'Allow a user to change the due date on an item to any date', 'ppl', 'description' )),
+ ( 98, 'CIRC_PERMIT_OVERRIDE', oils_i18n_gettext( 98, 
+    'Allow a user to bypass the circulation permit call for check out', 'ppl', 'description' )),
+ ( 99, 'COPY_IS_REFERENCE.override', oils_i18n_gettext( 99, 
+    'Allow a user to override the copy_is_reference event', 'ppl', 'description' )),
+ ( 100, 'VOID_BILLING', oils_i18n_gettext( 100, 
+    'Allow a user to void a bill', 'ppl', 'description' )),
+ ( 101, 'CIRC_CLAIMS_RETURNED.override', oils_i18n_gettext( 101, 
+    'Allow a user to check in or check out an item that has a status of ''claims returned''', 'ppl', 'description' )),
+ ( 102, 'COPY_BAD_STATUS.override', oils_i18n_gettext( 102, 
+    'Allow a user to check out an item in a non-circulatable status', 'ppl', 'description' )),
+ ( 103, 'COPY_ALERT_MESSAGE.override', oils_i18n_gettext( 103, 
+    'Allow a user to check in/out an item that has an alert message', 'ppl', 'description' )),
+ ( 104, 'COPY_STATUS_LOST.override', oils_i18n_gettext( 104, 
+    'Allow a user to remove the lost status from a copy', 'ppl', 'description' )),
+ ( 105, 'COPY_STATUS_MISSING.override', oils_i18n_gettext( 105, 
+    'Allow a user to change the missing status on a copy', 'ppl', 'description' )),
+ ( 106, 'ABORT_TRANSIT', oils_i18n_gettext( 106, 
+    'Allow a user to abort a copy transit if the user is at the transit destination or source', 'ppl', 'description' )),
+ ( 107, 'ABORT_REMOTE_TRANSIT', oils_i18n_gettext( 107, 
+    'Allow a user to abort a copy transit if the user is not at the transit source or dest', 'ppl', 'description' )),
+ ( 108, 'VIEW_ZIP_DATA', oils_i18n_gettext( 108, 
+    'Allow a user to query the ZIP code data method', 'ppl', 'description' )),
+ ( 109, 'CANCEL_HOLDS', oils_i18n_gettext( 109, 
+    'Allow a user to cancel holds', 'ppl', 'description' )),
+ ( 110, 'CREATE_DUPLICATE_HOLDS', oils_i18n_gettext( 110, 
+    'Allow a user to create duplicate holds (two or more holds on the same title)', 'ppl', 'description' )),
+ ( 111, 'actor.org_unit.closed_date.delete', oils_i18n_gettext( 111, 
+    'Allow a user to remove a closed date interval for a given location', 'ppl', 'description' )),
+ ( 112, 'actor.org_unit.closed_date.update', oils_i18n_gettext( 112, 
+    'Allow a user to update a closed date interval for a given location', 'ppl', 'description' )),
+ ( 113, 'actor.org_unit.closed_date.create', oils_i18n_gettext( 113, 
+    'Allow a user to create a new closed date for a location', 'ppl', 'description' )),
+ ( 114, 'DELETE_NON_CAT_TYPE', oils_i18n_gettext( 114, 
+    'Allow a user to delete a non cataloged type', 'ppl', 'description' )),
+ ( 115, 'money.collections_tracker.create', oils_i18n_gettext( 115, 
+    'Allow a user to put someone into collections', 'ppl', 'description' )),
+ ( 116, 'money.collections_tracker.delete', oils_i18n_gettext( 116, 
+    'Allow a user to remove someone from collections', 'ppl', 'description' )),
+ ( 117, 'BAR_PATRON', oils_i18n_gettext( 117, 
+    'Allow a user to bar a patron', 'ppl', 'description' )),
+ ( 118, 'UNBAR_PATRON', oils_i18n_gettext( 118, 
+    'Allow a user to un-bar a patron', 'ppl', 'description' )),
+ ( 119, 'DELETE_WORKSTATION', oils_i18n_gettext( 119, 
+    'Allow a user to remove an existing workstation so a new one can replace it', 'ppl', 'description' )),
+ ( 120, 'group_application.user', oils_i18n_gettext( 120, 
+    'Allow a user to add/remove users to/from the "User" group', 'ppl', 'description' )),
+ ( 121, 'group_application.user.patron', oils_i18n_gettext( 121, 
+    'Allow a user to add/remove users to/from the "Patron" group', 'ppl', 'description' )),
+ ( 122, 'group_application.user.staff', oils_i18n_gettext( 122, 
+    'Allow a user to add/remove users to/from the "Staff" group', 'ppl', 'description' )),
+ ( 123, 'group_application.user.staff.circ', oils_i18n_gettext( 123, 
+    'Allow a user to add/remove users to/from the "Circulator" group', 'ppl', 'description' )),
+ ( 124, 'group_application.user.staff.cat', oils_i18n_gettext( 124, 
+    'Allow a user to add/remove users to/from the "Cataloger" group', 'ppl', 'description' )),
+ ( 125, 'group_application.user.staff.admin.global_admin', oils_i18n_gettext( 125, 
+    'Allow a user to add/remove users to/from the "GlobalAdmin" group', 'ppl', 'description' )),
+ ( 126, 'group_application.user.staff.admin.local_admin', oils_i18n_gettext( 126, 
+    'Allow a user to add/remove users to/from the "LocalAdmin" group', 'ppl', 'description' )),
+ ( 127, 'group_application.user.staff.admin.lib_manager', oils_i18n_gettext( 127, 
+    'Allow a user to add/remove users to/from the "LibraryManager" group', 'ppl', 'description' )),
+ ( 128, 'group_application.user.staff.cat.cat1', oils_i18n_gettext( 128, 
+    'Allow a user to add/remove users to/from the "Cat1" group', 'ppl', 'description' )),
+ ( 129, 'group_application.user.staff.supercat', oils_i18n_gettext( 129, 
+    'Allow a user to add/remove users to/from the "Supercat" group', 'ppl', 'description' )),
+ ( 130, 'group_application.user.sip_client', oils_i18n_gettext( 130, 
+    'Allow a user to add/remove users to/from the "SIP-Client" group', 'ppl', 'description' )),
+ ( 131, 'group_application.user.vendor', oils_i18n_gettext( 131, 
+    'Allow a user to add/remove users to/from the "Vendor" group', 'ppl', 'description' )),
+ ( 132, 'ITEM_AGE_PROTECTED.override', oils_i18n_gettext( 132, 
+    'Allow a user to place a hold on an age-protected item', 'ppl', 'description' )),
+ ( 133, 'MAX_RENEWALS_REACHED.override', oils_i18n_gettext( 133, 
+    'Allow a user to renew an item past the maximum renewal count', 'ppl', 'description' )),
+ ( 134, 'PATRON_EXCEEDS_CHECKOUT_COUNT.override', oils_i18n_gettext( 134, 
+    'Allow staff to override checkout count failure', 'ppl', 'description' )),
+ ( 135, 'PATRON_EXCEEDS_OVERDUE_COUNT.override', oils_i18n_gettext( 135, 
+    'Allow staff to override overdue count failure', 'ppl', 'description' )),
+ ( 136, 'PATRON_EXCEEDS_FINES.override', oils_i18n_gettext( 136, 
+    'Allow staff to override fine amount checkout failure', 'ppl', 'description' )),
+ ( 137, 'CIRC_EXCEEDS_COPY_RANGE.override', oils_i18n_gettext( 137, 
+    'Allow staff to override circulation copy range failure', 'ppl', 'description' )),
+ ( 138, 'ITEM_ON_HOLDS_SHELF.override', oils_i18n_gettext( 138, 
+    'Allow staff to override item on holds shelf failure', 'ppl', 'description' )),
+ ( 139, 'COPY_NOT_AVAILABLE.override', oils_i18n_gettext( 139, 
+    'Allow staff to force checkout of Missing/Lost type items', 'ppl', 'description' )),
+ ( 140, 'HOLD_EXISTS.override', oils_i18n_gettext( 140, 
+    'Allow a user to place multiple holds on a single title', 'ppl', 'description' )),
+ ( 141, 'RUN_REPORTS', oils_i18n_gettext( 141, 
+    'Allow a user to run reports', 'ppl', 'description' )),
+ ( 142, 'SHARE_REPORT_FOLDER', oils_i18n_gettext( 142, 
+    'Allow a user to share report his own folders', 'ppl', 'description' )),
+ ( 143, 'VIEW_REPORT_OUTPUT', oils_i18n_gettext( 143, 
+    'Allow a user to view report output', 'ppl', 'description' )),
+ ( 144, 'COPY_CIRC_NOT_ALLOWED.override', oils_i18n_gettext( 144, 
+    'Allow a user to checkout an item that is marked as non-circ', 'ppl', 'description' )),
+ ( 145, 'DELETE_CONTAINER_ITEM', oils_i18n_gettext( 145, 
+    'Allow a user to delete an item out of another user''s container', 'ppl', 'description' )),
+ ( 146, 'ASSIGN_WORK_ORG_UNIT', oils_i18n_gettext( 146, 
+    'Allow a staff member to define where another staff member has their permissions', 'ppl', 'description' )),
+ ( 147, 'CREATE_FUNDING_SOURCE', oils_i18n_gettext( 147, 
+    'Allow a user to create a new funding source', 'ppl', 'description' )),
+ ( 148, 'DELETE_FUNDING_SOURCE', oils_i18n_gettext( 148, 
+    'Allow a user to delete a funding source', 'ppl', 'description' )),
+ ( 149, 'VIEW_FUNDING_SOURCE', oils_i18n_gettext( 149, 
+    'Allow a user to view a funding source', 'ppl', 'description' )),
+ ( 150, 'UPDATE_FUNDING_SOURCE', oils_i18n_gettext( 150, 
+    'Allow a user to update a funding source', 'ppl', 'description' )),
+ ( 151, 'CREATE_FUND', oils_i18n_gettext( 151, 
+    'Allow a user to create a new fund', 'ppl', 'description' )),
+ ( 152, 'DELETE_FUND', oils_i18n_gettext( 152, 
+    'Allow a user to delete a fund', 'ppl', 'description' )),
+ ( 153, 'VIEW_FUND', oils_i18n_gettext( 153, 
+    'Allow a user to view a fund', 'ppl', 'description' )),
+ ( 154, 'UPDATE_FUND', oils_i18n_gettext( 154, 
+    'Allow a user to update a fund', 'ppl', 'description' )),
+ ( 155, 'CREATE_FUND_ALLOCATION', oils_i18n_gettext( 155, 
+    'Allow a user to create a new fund allocation', 'ppl', 'description' )),
+ ( 156, 'DELETE_FUND_ALLOCATION', oils_i18n_gettext( 156, 
+    'Allow a user to delete a fund allocation', 'ppl', 'description' )),
+ ( 157, 'VIEW_FUND_ALLOCATION', oils_i18n_gettext( 157, 
+    'Allow a user to view a fund allocation', 'ppl', 'description' )),
+ ( 158, 'UPDATE_FUND_ALLOCATION', oils_i18n_gettext( 158, 
+    'Allow a user to update a fund allocation', 'ppl', 'description' )),
+ ( 159, 'GENERAL_ACQ', oils_i18n_gettext( 159, 
+    'Lowest level permission required to access the ACQ interface', 'ppl', 'description' )),
+ ( 160, 'CREATE_PROVIDER', oils_i18n_gettext( 160, 
+    'Allow a user to create a new provider', 'ppl', 'description' )),
+ ( 161, 'DELETE_PROVIDER', oils_i18n_gettext( 161, 
+    'Allow a user to delate a provider', 'ppl', 'description' )),
+ ( 162, 'VIEW_PROVIDER', oils_i18n_gettext( 162, 
+    'Allow a user to view a provider', 'ppl', 'description' )),
+ ( 163, 'UPDATE_PROVIDER', oils_i18n_gettext( 163, 
+    'Allow a user to update a provider', 'ppl', 'description' )),
+ ( 164, 'ADMIN_FUNDING_SOURCE', oils_i18n_gettext( 164, 
+    'Allow a user to create/view/update/delete a funding source', 'ppl', 'description' )),
+ ( 165, 'ADMIN_FUND', oils_i18n_gettext( 165, 
+    '(Deprecated) Allow a user to create/view/update/delete a fund', 'ppl', 'description' )),
+ ( 166, 'MANAGE_FUNDING_SOURCE', oils_i18n_gettext( 166, 
+    'Allow a user to view/credit/debit a funding source', 'ppl', 'description' )),
+ ( 167, 'MANAGE_FUND', oils_i18n_gettext( 167, 
+    'Allow a user to view/credit/debit a fund', 'ppl', 'description' )),
+ ( 168, 'CREATE_PICKLIST', oils_i18n_gettext( 168, 
+    'Allows a user to create a picklist', 'ppl', 'description' )),
+ ( 169, 'ADMIN_PROVIDER', oils_i18n_gettext( 169, 
+    'Allow a user to create/view/update/delete a provider', 'ppl', 'description' )),
+ ( 170, 'MANAGE_PROVIDER', oils_i18n_gettext( 170, 
+    'Allow a user to view and purchase from a provider', 'ppl', 'description' )),
+ ( 171, 'VIEW_PICKLIST', oils_i18n_gettext( 171, 
+    'Allow a user to view another users picklist', 'ppl', 'description' )),
+ ( 172, 'DELETE_RECORD', oils_i18n_gettext( 172, 
+    'Allow a staff member to directly remove a bibliographic record', 'ppl', 'description' )),
+ ( 173, 'ADMIN_CURRENCY_TYPE', oils_i18n_gettext( 173, 
+    'Allow a user to create/view/update/delete a currency_type', 'ppl', 'description' )),
+ ( 174, 'MARK_BAD_DEBT', oils_i18n_gettext( 174, 
+    'Allow a user to mark a transaction as bad (unrecoverable) debt', 'ppl', 'description' )),
+ ( 175, 'VIEW_BILLING_TYPE', oils_i18n_gettext( 175, 
+    'Allow a user to view billing types', 'ppl', 'description' )),
+ ( 176, 'MARK_ITEM_AVAILABLE', oils_i18n_gettext( 176, 
+    'Allow a user to mark an item status as ''available''', 'ppl', 'description' )),
+ ( 177, 'MARK_ITEM_CHECKED_OUT', oils_i18n_gettext( 177, 
+    'Allow a user to mark an item status as ''checked out''', 'ppl', 'description' )),
+ ( 178, 'MARK_ITEM_BINDERY', oils_i18n_gettext( 178, 
+    'Allow a user to mark an item status as ''bindery''', 'ppl', 'description' )),
+ ( 179, 'MARK_ITEM_LOST', oils_i18n_gettext( 179, 
+    'Allow a user to mark an item status as ''lost''', 'ppl', 'description' )),
+ ( 180, 'MARK_ITEM_MISSING', oils_i18n_gettext( 180, 
+    'Allow a user to mark an item status as ''missing''', 'ppl', 'description' )),
+ ( 181, 'MARK_ITEM_IN_PROCESS', oils_i18n_gettext( 181, 
+    'Allow a user to mark an item status as ''in process''', 'ppl', 'description' )),
+ ( 182, 'MARK_ITEM_IN_TRANSIT', oils_i18n_gettext( 182, 
+    'Allow a user to mark an item status as ''in transit''', 'ppl', 'description' )),
+ ( 183, 'MARK_ITEM_RESHELVING', oils_i18n_gettext( 183, 
+    'Allow a user to mark an item status as ''reshelving''', 'ppl', 'description' )),
+ ( 184, 'MARK_ITEM_ON_HOLDS_SHELF', oils_i18n_gettext( 184, 
+    'Allow a user to mark an item status as ''on holds shelf''', 'ppl', 'description' )),
+ ( 185, 'MARK_ITEM_ON_ORDER', oils_i18n_gettext( 185, 
+    'Allow a user to mark an item status as ''on order''', 'ppl', 'description' )),
+ ( 186, 'MARK_ITEM_ILL', oils_i18n_gettext( 186, 
+    'Allow a user to mark an item status as ''inter-library loan''', 'ppl', 'description' )),
+ ( 187, 'group_application.user.staff.acq', oils_i18n_gettext( 187, 
+    'Allows a user to add/remove/edit users in the "ACQ" group', 'ppl', 'description' )),
+ ( 188, 'CREATE_PURCHASE_ORDER', oils_i18n_gettext( 188, 
+    'Allows a user to create a purchase order', 'ppl', 'description' )),
+ ( 189, 'VIEW_PURCHASE_ORDER', oils_i18n_gettext( 189, 
+    'Allows a user to view a purchase order', 'ppl', 'description' )),
+ ( 190, 'IMPORT_ACQ_LINEITEM_BIB_RECORD', oils_i18n_gettext( 190, 
+    'Allows a user to import a bib record from the acq staging area (on-order record) into the ILS bib data set', 'ppl', 'description' )),
+ ( 191, 'RECEIVE_PURCHASE_ORDER', oils_i18n_gettext( 191, 
+    'Allows a user to mark a purchase order, lineitem, or individual copy as received', 'ppl', 'description' )),
+ ( 192, 'VIEW_ORG_SETTINGS', oils_i18n_gettext( 192, 
+    'Allows a user to view all org settings at the specified level', 'ppl', 'description' )),
+ ( 193, 'CREATE_MFHD_RECORD', oils_i18n_gettext( 193, 
+    'Allows a user to create a new MFHD record', 'ppl', 'description' )),
+ ( 194, 'UPDATE_MFHD_RECORD', oils_i18n_gettext( 194, 
+    'Allows a user to update an MFHD record', 'ppl', 'description' )),
+ ( 195, 'DELETE_MFHD_RECORD', oils_i18n_gettext( 195, 
+    'Allows a user to delete an MFHD record', 'ppl', 'description' )),
+ ( 196, 'ADMIN_ACQ_FUND', oils_i18n_gettext( 196, 
+    'Allow a user to create/view/update/delete a fund', 'ppl', 'description' )),
+ ( 197, 'group_application.user.staff.acq_admin', oils_i18n_gettext( 197, 
+    'Allows a user to add/remove/edit users in the "Acquisitions Administrators" group', 'ppl', 'description' )),
+ ( 198, 'SET_CIRC_CLAIMS_RETURNED.override', oils_i18n_gettext( 198, 
+    'Allows staff to override the max claims returned value for a patron', 'ppl', 'description' )),
+ ( 199, 'UPDATE_PATRON_CLAIM_RETURN_COUNT', oils_i18n_gettext( 199, 
+    'Allows staff to manually change a patron''s claims returned count', 'ppl', 'description' )),
+ ( 200, 'UPDATE_BILL_NOTE', oils_i18n_gettext( 200, 
+    'Allows staff to edit the note for a bill on a transaction', 'ppl', 'description' )),
+ ( 201, 'UPDATE_PAYMENT_NOTE', oils_i18n_gettext( 201, 
+    'Allows staff to edit the note for a payment on a transaction', 'ppl', 'description' )),
+ ( 202, 'UPDATE_PATRON_CLAIM_NEVER_CHECKED_OUT_COUNT', oils_i18n_gettext( 202, 
+    'Allows staff to manually change a patron''s claims never checkout out count', 'ppl', 'description' )),
+ ( 203, 'ADMIN_COPY_LOCATION_ORDER', oils_i18n_gettext( 203, 
+    'Allow a user to create/view/update/delete a copy location order', 'ppl', 'description' )),
+ ( 204, 'ASSIGN_GROUP_PERM', oils_i18n_gettext( 204, 
+    'ASSIGN_GROUP_PERM', 'ppl', 'description' )),
+ ( 205, 'CREATE_AUDIENCE', oils_i18n_gettext( 205, 
+    'CREATE_AUDIENCE', 'ppl', 'description' )),
+ ( 206, 'CREATE_BIB_LEVEL', oils_i18n_gettext( 206, 
+    'CREATE_BIB_LEVEL', 'ppl', 'description' )),
+ ( 207, 'CREATE_CIRC_DURATION', oils_i18n_gettext( 207, 
+    'CREATE_CIRC_DURATION', 'ppl', 'description' )),
+ ( 208, 'CREATE_CIRC_MOD', oils_i18n_gettext( 208, 
+    'CREATE_CIRC_MOD', 'ppl', 'description' )),
+ ( 209, 'CREATE_COPY_STATUS', oils_i18n_gettext( 209, 
+    'CREATE_COPY_STATUS', 'ppl', 'description' )),
+ ( 210, 'CREATE_HOURS_OF_OPERATION', oils_i18n_gettext( 210, 
+    'CREATE_HOURS_OF_OPERATION', 'ppl', 'description' )),
+ ( 211, 'CREATE_ITEM_FORM', oils_i18n_gettext( 211, 
+    'CREATE_ITEM_FORM', 'ppl', 'description' )),
+ ( 212, 'CREATE_ITEM_TYPE', oils_i18n_gettext( 212, 
+    'CREATE_ITEM_TYPE', 'ppl', 'description' )),
+ ( 213, 'CREATE_LANGUAGE', oils_i18n_gettext( 213, 
+    'CREATE_LANGUAGE', 'ppl', 'description' )),
+ ( 214, 'CREATE_LASSO', oils_i18n_gettext( 214, 
+    'CREATE_LASSO', 'ppl', 'description' )),
+ ( 215, 'CREATE_LASSO_MAP', oils_i18n_gettext( 215, 
+    'CREATE_LASSO_MAP', 'ppl', 'description' )),
+ ( 216, 'CREATE_LIT_FORM', oils_i18n_gettext( 216, 
+    'CREATE_LIT_FORM', 'ppl', 'description' )),
+ ( 217, 'CREATE_METABIB_FIELD', oils_i18n_gettext( 217, 
+    'CREATE_METABIB_FIELD', 'ppl', 'description' )),
+ ( 218, 'CREATE_NET_ACCESS_LEVEL', oils_i18n_gettext( 218, 
+    'CREATE_NET_ACCESS_LEVEL', 'ppl', 'description' )),
+ ( 219, 'CREATE_ORG_ADDRESS', oils_i18n_gettext( 219, 
+    'CREATE_ORG_ADDRESS', 'ppl', 'description' )),
+ ( 220, 'CREATE_ORG_TYPE', oils_i18n_gettext( 220, 
+    'CREATE_ORG_TYPE', 'ppl', 'description' )),
+ ( 221, 'CREATE_ORG_UNIT', oils_i18n_gettext( 221, 
+    'CREATE_ORG_UNIT', 'ppl', 'description' )),
+ ( 222, 'CREATE_ORG_UNIT_CLOSING', oils_i18n_gettext( 222, 
+    'CREATE_ORG_UNIT_CLOSING', 'ppl', 'description' )),
+ ( 223, 'CREATE_PERM', oils_i18n_gettext( 223, 
+    'CREATE_PERM', 'ppl', 'description' )),
+ ( 224, 'CREATE_RELEVANCE_ADJUSTMENT', oils_i18n_gettext( 224, 
+    'CREATE_RELEVANCE_ADJUSTMENT', 'ppl', 'description' )),
+ ( 225, 'CREATE_SURVEY', oils_i18n_gettext( 225, 
+    'CREATE_SURVEY', 'ppl', 'description' )),
+ ( 226, 'CREATE_VR_FORMAT', oils_i18n_gettext( 226, 
+    'CREATE_VR_FORMAT', 'ppl', 'description' )),
+ ( 227, 'CREATE_XML_TRANSFORM', oils_i18n_gettext( 227, 
+    'CREATE_XML_TRANSFORM', 'ppl', 'description' )),
+ ( 228, 'DELETE_AUDIENCE', oils_i18n_gettext( 228, 
+    'DELETE_AUDIENCE', 'ppl', 'description' )),
+ ( 229, 'DELETE_BIB_LEVEL', oils_i18n_gettext( 229, 
+    'DELETE_BIB_LEVEL', 'ppl', 'description' )),
+ ( 230, 'DELETE_CIRC_DURATION', oils_i18n_gettext( 230, 
+    'DELETE_CIRC_DURATION', 'ppl', 'description' )),
+ ( 231, 'DELETE_CIRC_MOD', oils_i18n_gettext( 231, 
+    'DELETE_CIRC_MOD', 'ppl', 'description' )),
+ ( 232, 'DELETE_COPY_STATUS', oils_i18n_gettext( 232, 
+    'DELETE_COPY_STATUS', 'ppl', 'description' )),
+ ( 233, 'DELETE_HOURS_OF_OPERATION', oils_i18n_gettext( 233, 
+    'DELETE_HOURS_OF_OPERATION', 'ppl', 'description' )),
+ ( 234, 'DELETE_ITEM_FORM', oils_i18n_gettext( 234, 
+    'DELETE_ITEM_FORM', 'ppl', 'description' )),
+ ( 235, 'DELETE_ITEM_TYPE', oils_i18n_gettext( 235, 
+    'DELETE_ITEM_TYPE', 'ppl', 'description' )),
+ ( 236, 'DELETE_LANGUAGE', oils_i18n_gettext( 236, 
+    'DELETE_LANGUAGE', 'ppl', 'description' )),
+ ( 237, 'DELETE_LASSO', oils_i18n_gettext( 237, 
+    'DELETE_LASSO', 'ppl', 'description' )),
+ ( 238, 'DELETE_LASSO_MAP', oils_i18n_gettext( 238, 
+    'DELETE_LASSO_MAP', 'ppl', 'description' )),
+ ( 239, 'DELETE_LIT_FORM', oils_i18n_gettext( 239, 
+    'DELETE_LIT_FORM', 'ppl', 'description' )),
+ ( 240, 'DELETE_METABIB_FIELD', oils_i18n_gettext( 240, 
+    'DELETE_METABIB_FIELD', 'ppl', 'description' )),
+ ( 241, 'DELETE_NET_ACCESS_LEVEL', oils_i18n_gettext( 241, 
+    'DELETE_NET_ACCESS_LEVEL', 'ppl', 'description' )),
+ ( 242, 'DELETE_ORG_ADDRESS', oils_i18n_gettext( 242, 
+    'DELETE_ORG_ADDRESS', 'ppl', 'description' )),
+ ( 243, 'DELETE_ORG_TYPE', oils_i18n_gettext( 243, 
+    'DELETE_ORG_TYPE', 'ppl', 'description' )),
+ ( 244, 'DELETE_ORG_UNIT', oils_i18n_gettext( 244, 
+    'DELETE_ORG_UNIT', 'ppl', 'description' )),
+ ( 245, 'DELETE_ORG_UNIT_CLOSING', oils_i18n_gettext( 245, 
+    'DELETE_ORG_UNIT_CLOSING', 'ppl', 'description' )),
+ ( 246, 'DELETE_PERM', oils_i18n_gettext( 246, 
+    'DELETE_PERM', 'ppl', 'description' )),
+ ( 247, 'DELETE_RELEVANCE_ADJUSTMENT', oils_i18n_gettext( 247, 
+    'DELETE_RELEVANCE_ADJUSTMENT', 'ppl', 'description' )),
+ ( 248, 'DELETE_SURVEY', oils_i18n_gettext( 248, 
+    'DELETE_SURVEY', 'ppl', 'description' )),
+ ( 249, 'DELETE_TRANSIT', oils_i18n_gettext( 249, 
+    'DELETE_TRANSIT', 'ppl', 'description' )),
+ ( 250, 'DELETE_VR_FORMAT', oils_i18n_gettext( 250, 
+    'DELETE_VR_FORMAT', 'ppl', 'description' )),
+ ( 251, 'DELETE_XML_TRANSFORM', oils_i18n_gettext( 251, 
+    'DELETE_XML_TRANSFORM', 'ppl', 'description' )),
+ ( 252, 'REMOVE_GROUP_PERM', oils_i18n_gettext( 252, 
+    'REMOVE_GROUP_PERM', 'ppl', 'description' )),
+ ( 253, 'TRANSIT_COPY', oils_i18n_gettext( 253, 
+    'TRANSIT_COPY', 'ppl', 'description' )),
+ ( 254, 'UPDATE_AUDIENCE', oils_i18n_gettext( 254, 
+    'UPDATE_AUDIENCE', 'ppl', 'description' )),
+ ( 255, 'UPDATE_BIB_LEVEL', oils_i18n_gettext( 255, 
+    'UPDATE_BIB_LEVEL', 'ppl', 'description' )),
+ ( 256, 'UPDATE_CIRC_DURATION', oils_i18n_gettext( 256, 
+    'UPDATE_CIRC_DURATION', 'ppl', 'description' )),
+ ( 257, 'UPDATE_CIRC_MOD', oils_i18n_gettext( 257, 
+    'UPDATE_CIRC_MOD', 'ppl', 'description' )),
+ ( 258, 'UPDATE_COPY_NOTE', oils_i18n_gettext( 258, 
+    'UPDATE_COPY_NOTE', 'ppl', 'description' )),
+ ( 259, 'UPDATE_COPY_STATUS', oils_i18n_gettext( 259, 
+    'UPDATE_COPY_STATUS', 'ppl', 'description' )),
+ ( 260, 'UPDATE_GROUP_PERM', oils_i18n_gettext( 260, 
+    'UPDATE_GROUP_PERM', 'ppl', 'description' )),
+ ( 261, 'UPDATE_HOURS_OF_OPERATION', oils_i18n_gettext( 261, 
+    'UPDATE_HOURS_OF_OPERATION', 'ppl', 'description' )),
+ ( 262, 'UPDATE_ITEM_FORM', oils_i18n_gettext( 262, 
+    'UPDATE_ITEM_FORM', 'ppl', 'description' )),
+ ( 263, 'UPDATE_ITEM_TYPE', oils_i18n_gettext( 263, 
+    'UPDATE_ITEM_TYPE', 'ppl', 'description' )),
+ ( 264, 'UPDATE_LANGUAGE', oils_i18n_gettext( 264, 
+    'UPDATE_LANGUAGE', 'ppl', 'description' )),
+ ( 265, 'UPDATE_LASSO', oils_i18n_gettext( 265, 
+    'UPDATE_LASSO', 'ppl', 'description' )),
+ ( 266, 'UPDATE_LASSO_MAP', oils_i18n_gettext( 266, 
+    'UPDATE_LASSO_MAP', 'ppl', 'description' )),
+ ( 267, 'UPDATE_LIT_FORM', oils_i18n_gettext( 267, 
+    'UPDATE_LIT_FORM', 'ppl', 'description' )),
+ ( 268, 'UPDATE_METABIB_FIELD', oils_i18n_gettext( 268, 
+    'UPDATE_METABIB_FIELD', 'ppl', 'description' )),
+ ( 269, 'UPDATE_NET_ACCESS_LEVEL', oils_i18n_gettext( 269, 
+    'UPDATE_NET_ACCESS_LEVEL', 'ppl', 'description' )),
+ ( 270, 'UPDATE_ORG_ADDRESS', oils_i18n_gettext( 270, 
+    'UPDATE_ORG_ADDRESS', 'ppl', 'description' )),
+ ( 271, 'UPDATE_ORG_TYPE', oils_i18n_gettext( 271, 
+    'UPDATE_ORG_TYPE', 'ppl', 'description' )),
+ ( 272, 'UPDATE_ORG_UNIT_CLOSING', oils_i18n_gettext( 272, 
+    'UPDATE_ORG_UNIT_CLOSING', 'ppl', 'description' )),
+ ( 273, 'UPDATE_PERM', oils_i18n_gettext( 273, 
+    'UPDATE_PERM', 'ppl', 'description' )),
+ ( 274, 'UPDATE_RELEVANCE_ADJUSTMENT', oils_i18n_gettext( 274, 
+    'UPDATE_RELEVANCE_ADJUSTMENT', 'ppl', 'description' )),
+ ( 275, 'UPDATE_SURVEY', oils_i18n_gettext( 275, 
+    'UPDATE_SURVEY', 'ppl', 'description' )),
+ ( 276, 'UPDATE_TRANSIT', oils_i18n_gettext( 276, 
+    'UPDATE_TRANSIT', 'ppl', 'description' )),
+ ( 277, 'UPDATE_VOLUME_NOTE', oils_i18n_gettext( 277, 
+    'UPDATE_VOLUME_NOTE', 'ppl', 'description' )),
+ ( 278, 'UPDATE_VR_FORMAT', oils_i18n_gettext( 278, 
+    'UPDATE_VR_FORMAT', 'ppl', 'description' )),
+ ( 279, 'UPDATE_XML_TRANSFORM', oils_i18n_gettext( 279, 
+    'UPDATE_XML_TRANSFORM', 'ppl', 'description' )),
+ ( 280, 'MERGE_BIB_RECORDS', oils_i18n_gettext( 280, 
+    'MERGE_BIB_RECORDS', 'ppl', 'description' )),
+ ( 281, 'UPDATE_PICKUP_LIB_FROM_HOLDS_SHELF', oils_i18n_gettext( 281, 
+    'UPDATE_PICKUP_LIB_FROM_HOLDS_SHELF', 'ppl', 'description' )),
+ ( 282, 'CREATE_ACQ_FUNDING_SOURCE', oils_i18n_gettext( 282, 
+    'CREATE_ACQ_FUNDING_SOURCE', 'ppl', 'description' )),
+ ( 283, 'CREATE_AUTHORITY_IMPORT_IMPORT_FIELD_DEF', oils_i18n_gettext( 283, 
+    'CREATE_AUTHORITY_IMPORT_IMPORT_FIELD_DEF', 'ppl', 'description' )),
+ ( 284, 'CREATE_AUTHORITY_IMPORT_QUEUE', oils_i18n_gettext( 284, 
+    'CREATE_AUTHORITY_IMPORT_QUEUE', 'ppl', 'description' )),
+ ( 285, 'CREATE_AUTHORITY_RECORD_NOTE', oils_i18n_gettext( 285, 
+    'CREATE_AUTHORITY_RECORD_NOTE', 'ppl', 'description' )),
+ ( 286, 'CREATE_BIB_IMPORT_FIELD_DEF', oils_i18n_gettext( 286, 
+    'CREATE_BIB_IMPORT_FIELD_DEF', 'ppl', 'description' )),
+ ( 287, 'CREATE_BIB_IMPORT_QUEUE', oils_i18n_gettext( 287, 
+    'CREATE_BIB_IMPORT_QUEUE', 'ppl', 'description' )),
+ ( 288, 'CREATE_LOCALE', oils_i18n_gettext( 288, 
+    'CREATE_LOCALE', 'ppl', 'description' )),
+ ( 289, 'CREATE_MARC_CODE', oils_i18n_gettext( 289, 
+    'CREATE_MARC_CODE', 'ppl', 'description' )),
+ ( 290, 'CREATE_TRANSLATION', oils_i18n_gettext( 290, 
+    'CREATE_TRANSLATION', 'ppl', 'description' )),
+ ( 291, 'DELETE_ACQ_FUNDING_SOURCE', oils_i18n_gettext( 291, 
+    'DELETE_ACQ_FUNDING_SOURCE', 'ppl', 'description' )),
+ ( 292, 'DELETE_AUTHORITY_IMPORT_IMPORT_FIELD_DEF', oils_i18n_gettext( 292, 
+    'DELETE_AUTHORITY_IMPORT_IMPORT_FIELD_DEF', 'ppl', 'description' )),
+ ( 293, 'DELETE_AUTHORITY_IMPORT_QUEUE', oils_i18n_gettext( 293, 
+    'DELETE_AUTHORITY_IMPORT_QUEUE', 'ppl', 'description' )),
+ ( 294, 'DELETE_AUTHORITY_RECORD_NOTE', oils_i18n_gettext( 294, 
+    'DELETE_AUTHORITY_RECORD_NOTE', 'ppl', 'description' )),
+ ( 295, 'DELETE_BIB_IMPORT_IMPORT_FIELD_DEF', oils_i18n_gettext( 295, 
+    'DELETE_BIB_IMPORT_IMPORT_FIELD_DEF', 'ppl', 'description' )),
+ ( 296, 'DELETE_BIB_IMPORT_QUEUE', oils_i18n_gettext( 296, 
+    'DELETE_BIB_IMPORT_QUEUE', 'ppl', 'description' )),
+ ( 297, 'DELETE_LOCALE', oils_i18n_gettext( 297, 
+    'DELETE_LOCALE', 'ppl', 'description' )),
+ ( 298, 'DELETE_MARC_CODE', oils_i18n_gettext( 298, 
+    'DELETE_MARC_CODE', 'ppl', 'description' )),
+ ( 299, 'DELETE_TRANSLATION', oils_i18n_gettext( 299, 
+    'DELETE_TRANSLATION', 'ppl', 'description' )),
+ ( 300, 'UPDATE_ACQ_FUNDING_SOURCE', oils_i18n_gettext( 300, 
+    'UPDATE_ACQ_FUNDING_SOURCE', 'ppl', 'description' )),
+ ( 301, 'UPDATE_AUTHORITY_IMPORT_IMPORT_FIELD_DEF', oils_i18n_gettext( 301, 
+    'UPDATE_AUTHORITY_IMPORT_IMPORT_FIELD_DEF', 'ppl', 'description' )),
+ ( 302, 'UPDATE_AUTHORITY_IMPORT_QUEUE', oils_i18n_gettext( 302, 
+    'UPDATE_AUTHORITY_IMPORT_QUEUE', 'ppl', 'description' )),
+ ( 303, 'UPDATE_AUTHORITY_RECORD_NOTE', oils_i18n_gettext( 303, 
+    'UPDATE_AUTHORITY_RECORD_NOTE', 'ppl', 'description' )),
+ ( 304, 'UPDATE_BIB_IMPORT_IMPORT_FIELD_DEF', oils_i18n_gettext( 304, 
+    'UPDATE_BIB_IMPORT_IMPORT_FIELD_DEF', 'ppl', 'description' )),
+ ( 305, 'UPDATE_BIB_IMPORT_QUEUE', oils_i18n_gettext( 305, 
+    'UPDATE_BIB_IMPORT_QUEUE', 'ppl', 'description' )),
+ ( 306, 'UPDATE_LOCALE', oils_i18n_gettext( 306, 
+    'UPDATE_LOCALE', 'ppl', 'description' )),
+ ( 307, 'UPDATE_MARC_CODE', oils_i18n_gettext( 307, 
+    'UPDATE_MARC_CODE', 'ppl', 'description' )),
+ ( 308, 'UPDATE_TRANSLATION', oils_i18n_gettext( 308, 
+    'UPDATE_TRANSLATION', 'ppl', 'description' )),
+ ( 309, 'VIEW_ACQ_FUNDING_SOURCE', oils_i18n_gettext( 309, 
+    'VIEW_ACQ_FUNDING_SOURCE', 'ppl', 'description' )),
+ ( 310, 'VIEW_AUTHORITY_RECORD_NOTES', oils_i18n_gettext( 310, 
+    'VIEW_AUTHORITY_RECORD_NOTES', 'ppl', 'description' )),
+ ( 311, 'CREATE_IMPORT_ITEM', oils_i18n_gettext( 311, 
+    'CREATE_IMPORT_ITEM', 'ppl', 'description' )),
+ ( 312, 'CREATE_IMPORT_ITEM_ATTR_DEF', oils_i18n_gettext( 312, 
+    'CREATE_IMPORT_ITEM_ATTR_DEF', 'ppl', 'description' )),
+ ( 313, 'CREATE_IMPORT_TRASH_FIELD', oils_i18n_gettext( 313, 
+    'CREATE_IMPORT_TRASH_FIELD', 'ppl', 'description' )),
+ ( 314, 'DELETE_IMPORT_ITEM', oils_i18n_gettext( 314, 
+    'DELETE_IMPORT_ITEM', 'ppl', 'description' )),
+ ( 315, 'DELETE_IMPORT_ITEM_ATTR_DEF', oils_i18n_gettext( 315, 
+    'DELETE_IMPORT_ITEM_ATTR_DEF', 'ppl', 'description' )),
+ ( 316, 'DELETE_IMPORT_TRASH_FIELD', oils_i18n_gettext( 316, 
+    'DELETE_IMPORT_TRASH_FIELD', 'ppl', 'description' )),
+ ( 317, 'UPDATE_IMPORT_ITEM', oils_i18n_gettext( 317, 
+    'UPDATE_IMPORT_ITEM', 'ppl', 'description' )),
+ ( 318, 'UPDATE_IMPORT_ITEM_ATTR_DEF', oils_i18n_gettext( 318, 
+    'UPDATE_IMPORT_ITEM_ATTR_DEF', 'ppl', 'description' )),
+ ( 319, 'UPDATE_IMPORT_TRASH_FIELD', oils_i18n_gettext( 319, 
+    'UPDATE_IMPORT_TRASH_FIELD', 'ppl', 'description' )),
+ ( 320, 'UPDATE_ORG_UNIT_SETTING_ALL', oils_i18n_gettext( 320, 
+    'UPDATE_ORG_UNIT_SETTING_ALL', 'ppl', 'description' )),
+ ( 321, 'UPDATE_ORG_UNIT_SETTING.circ.lost_materials_processing_fee', oils_i18n_gettext( 321, 
+    'UPDATE_ORG_UNIT_SETTING.circ.lost_materials_processing_fee', 'ppl', 'description' )),
+ ( 322, 'UPDATE_ORG_UNIT_SETTING.cat.default_item_price', oils_i18n_gettext( 322, 
+    'UPDATE_ORG_UNIT_SETTING.cat.default_item_price', 'ppl', 'description' )),
+ ( 323, 'UPDATE_ORG_UNIT_SETTING.auth.opac_timeout', oils_i18n_gettext( 323, 
+    'UPDATE_ORG_UNIT_SETTING.auth.opac_timeout', 'ppl', 'description' )),
+ ( 324, 'UPDATE_ORG_UNIT_SETTING.auth.staff_timeout', oils_i18n_gettext( 324, 
+    'UPDATE_ORG_UNIT_SETTING.auth.staff_timeout', 'ppl', 'description' )),
+ ( 325, 'UPDATE_ORG_UNIT_SETTING.org.bounced_emails', oils_i18n_gettext( 325, 
+    'UPDATE_ORG_UNIT_SETTING.org.bounced_emails', 'ppl', 'description' )),
+ ( 326, 'UPDATE_ORG_UNIT_SETTING.circ.hold_expire_alert_interval', oils_i18n_gettext( 326, 
+    'UPDATE_ORG_UNIT_SETTING.circ.hold_expire_alert_interval', 'ppl', 'description' )),
+ ( 327, 'UPDATE_ORG_UNIT_SETTING.circ.hold_expire_interval', oils_i18n_gettext( 327, 
+    'UPDATE_ORG_UNIT_SETTING.circ.hold_expire_interval', 'ppl', 'description' )),
+ ( 328, 'UPDATE_ORG_UNIT_SETTING.credit.payments.allow', oils_i18n_gettext( 328, 
+    'UPDATE_ORG_UNIT_SETTING.credit.payments.allow', 'ppl', 'description' )),
+ ( 329, 'UPDATE_ORG_UNIT_SETTING.circ.void_overdue_on_lost', oils_i18n_gettext( 329, 
+    'UPDATE_ORG_UNIT_SETTING.circ.void_overdue_on_lost', 'ppl', 'description' )),
+ ( 330, 'UPDATE_ORG_UNIT_SETTING.circ.hold_stalling.soft', oils_i18n_gettext( 330, 
+    'UPDATE_ORG_UNIT_SETTING.circ.hold_stalling.soft', 'ppl', 'description' )),
+ ( 331, 'UPDATE_ORG_UNIT_SETTING.circ.hold_boundary.hard', oils_i18n_gettext( 331, 
+    'UPDATE_ORG_UNIT_SETTING.circ.hold_boundary.hard', 'ppl', 'description' )),
+ ( 332, 'UPDATE_ORG_UNIT_SETTING.circ.hold_boundary.soft', oils_i18n_gettext( 332, 
+    'UPDATE_ORG_UNIT_SETTING.circ.hold_boundary.soft', 'ppl', 'description' )),
+ ( 333, 'UPDATE_ORG_UNIT_SETTING.opac.barcode_regex', oils_i18n_gettext( 333, 
+    'UPDATE_ORG_UNIT_SETTING.opac.barcode_regex', 'ppl', 'description' )),
+ ( 334, 'UPDATE_ORG_UNIT_SETTING.global.password_regex', oils_i18n_gettext( 334, 
+    'UPDATE_ORG_UNIT_SETTING.global.password_regex', 'ppl', 'description' )),
+ ( 335, 'UPDATE_ORG_UNIT_SETTING.circ.item_checkout_history.max', oils_i18n_gettext( 335, 
+    'UPDATE_ORG_UNIT_SETTING.circ.item_checkout_history.max', 'ppl', 'description' )),
+ ( 336, 'UPDATE_ORG_UNIT_SETTING.circ.reshelving_complete.interval', oils_i18n_gettext( 336, 
+    'UPDATE_ORG_UNIT_SETTING.circ.reshelving_complete.interval', 'ppl', 'description' )),
+ ( 337, 'UPDATE_ORG_UNIT_SETTING.circ.selfcheck.patron_login_timeout', oils_i18n_gettext( 337, 
+    'UPDATE_ORG_UNIT_SETTING.circ.selfcheck.patron_login_timeout', 'ppl', 'description' )),
+ ( 338, 'UPDATE_ORG_UNIT_SETTING.circ.selfcheck.alert_on_checkout_event', oils_i18n_gettext( 338, 
+    'UPDATE_ORG_UNIT_SETTING.circ.selfcheck.alert_on_checkout_event', 'ppl', 'description' )),
+ ( 339, 'UPDATE_ORG_UNIT_SETTING.circ.selfcheck.require_patron_password', oils_i18n_gettext( 339, 
+    'UPDATE_ORG_UNIT_SETTING.circ.selfcheck.require_patron_password', 'ppl', 'description' )),
+ ( 340, 'UPDATE_ORG_UNIT_SETTING.global.juvenile_age_threshold', oils_i18n_gettext( 340, 
+    'UPDATE_ORG_UNIT_SETTING.global.juvenile_age_threshold', 'ppl', 'description' )),
+ ( 341, 'UPDATE_ORG_UNIT_SETTING.cat.bib.keep_on_empty', oils_i18n_gettext( 341, 
+    'UPDATE_ORG_UNIT_SETTING.cat.bib.keep_on_empty', 'ppl', 'description' )),
+ ( 342, 'UPDATE_ORG_UNIT_SETTING.cat.bib.alert_on_empty', oils_i18n_gettext( 342, 
+    'UPDATE_ORG_UNIT_SETTING.cat.bib.alert_on_empty', 'ppl', 'description' )),
+ ( 343, 'UPDATE_ORG_UNIT_SETTING.patron.password.use_phone', oils_i18n_gettext( 343, 
+    'UPDATE_ORG_UNIT_SETTING.patron.password.use_phone', 'ppl', 'description' )),
+ ( 344, 'HOLD_ITEM_CHECKED_OUT.override', oils_i18n_gettext( 344, 
+    'Allows a user to place a hold on an item that they already have checked out', 'ppl', 'description' )),
+ ( 345, 'ADMIN_ACQ_CANCEL_CAUSE', oils_i18n_gettext( 345, 
+    'Allow a user to create/update/delete reasons for order cancellations', 'ppl', 'description' )),
+ ( 346, 'ACQ_XFER_MANUAL_DFUND_AMOUNT', oils_i18n_gettext( 346, 
+    'Allow a user to transfer different amounts of money out of one fund and into another', 'ppl', 'description' )),
+ ( 347, 'OVERRIDE_HOLD_HAS_LOCAL_COPY', oils_i18n_gettext( 347, 
+    'Allow a user to override the circ.holds.hold_has_copy_at.block setting', 'ppl', 'description' )),
+ ( 348, 'UPDATE_PICKUP_LIB_FROM_TRANSIT', oils_i18n_gettext( 348, 
+    'Allow a user to change the pickup and transit destination for a captured hold item already in transit', 'ppl', 'description' )),
+ ( 349, 'COPY_NEEDED_FOR_HOLD.override', oils_i18n_gettext( 349, 
+    'Allow a user to force renewal of an item that could fulfill a hold request', 'ppl', 'description' )),
+ ( 350, 'MERGE_AUTH_RECORDS', oils_i18n_gettext( 350, 
+    'Allow a user to merge authority records together', 'ppl', 'description' )),
+ ( 351, 'ALLOW_ALT_TCN', oils_i18n_gettext( 351, 
+    'Allows staff to import a record using an alternate TCN to avoid conflicts', 'ppl', 'description' )),
+ ( 352, 'ADMIN_TRIGGER_EVENT_DEF', oils_i18n_gettext( 352, 
+    'Allow a user to administer trigger event definitions', 'ppl', 'description' )),
+ ( 353, 'ADMIN_TRIGGER_CLEANUP', oils_i18n_gettext( 353, 
+    'Allow a user to create, delete, and update trigger cleanup entries', 'ppl', 'description' )),
+ ( 354, 'CREATE_TRIGGER_CLEANUP', oils_i18n_gettext( 354, 
+    'Allow a user to create trigger cleanup entries', 'ppl', 'description' )),
+ ( 355, 'DELETE_TRIGGER_CLEANUP', oils_i18n_gettext( 355, 
+    'Allow a user to delete trigger cleanup entries', 'ppl', 'description' )),
+ ( 356, 'UPDATE_TRIGGER_CLEANUP', oils_i18n_gettext( 356, 
+    'Allow a user to update trigger cleanup entries', 'ppl', 'description' )),
+ ( 357, 'CREATE_TRIGGER_EVENT_DEF', oils_i18n_gettext( 357, 
+    'Allow a user to create trigger event definitions', 'ppl', 'description' )),
+ ( 358, 'DELETE_TRIGGER_EVENT_DEF', oils_i18n_gettext( 358, 
+    'Allow a user to delete trigger event definitions', 'ppl', 'description' )),
+ ( 359, 'UPDATE_TRIGGER_EVENT_DEF', oils_i18n_gettext( 359, 
+    'Allow a user to update trigger event definitions', 'ppl', 'description' )),
+ ( 360, 'VIEW_TRIGGER_EVENT_DEF', oils_i18n_gettext( 360, 
+    'Allow a user to view trigger event definitions', 'ppl', 'description' )),
+ ( 361, 'ADMIN_TRIGGER_HOOK', oils_i18n_gettext( 361, 
+    'Allow a user to create, update, and delete trigger hooks', 'ppl', 'description' )),
+ ( 362, 'CREATE_TRIGGER_HOOK', oils_i18n_gettext( 362, 
+    'Allow a user to create trigger hooks', 'ppl', 'description' )),
+ ( 363, 'DELETE_TRIGGER_HOOK', oils_i18n_gettext( 363, 
+    'Allow a user to delete trigger hooks', 'ppl', 'description' )),
+ ( 364, 'UPDATE_TRIGGER_HOOK', oils_i18n_gettext( 364, 
+    'Allow a user to update trigger hooks', 'ppl', 'description' )),
+ ( 365, 'ADMIN_TRIGGER_REACTOR', oils_i18n_gettext( 365, 
+    'Allow a user to create, update, and delete trigger reactors', 'ppl', 'description' )),
+ ( 366, 'CREATE_TRIGGER_REACTOR', oils_i18n_gettext( 366, 
+    'Allow a user to create trigger reactors', 'ppl', 'description' )),
+ ( 367, 'DELETE_TRIGGER_REACTOR', oils_i18n_gettext( 367, 
+    'Allow a user to delete trigger reactors', 'ppl', 'description' )),
+ ( 368, 'UPDATE_TRIGGER_REACTOR', oils_i18n_gettext( 368, 
+    'Allow a user to update trigger reactors', 'ppl', 'description' )),
+ ( 369, 'ADMIN_TRIGGER_TEMPLATE_OUTPUT', oils_i18n_gettext( 369, 
+    'Allow a user to delete trigger template output', 'ppl', 'description' )),
+ ( 370, 'DELETE_TRIGGER_TEMPLATE_OUTPUT', oils_i18n_gettext( 370, 
+    'Allow a user to delete trigger template output', 'ppl', 'description' )),
+ ( 371, 'ADMIN_TRIGGER_VALIDATOR', oils_i18n_gettext( 371, 
+    'Allow a user to create, update, and delete trigger validators', 'ppl', 'description' )),
+ ( 372, 'CREATE_TRIGGER_VALIDATOR', oils_i18n_gettext( 372, 
+    'Allow a user to create trigger validators', 'ppl', 'description' )),
+ ( 373, 'DELETE_TRIGGER_VALIDATOR', oils_i18n_gettext( 373, 
+    'Allow a user to delete trigger validators', 'ppl', 'description' )),
+ ( 374, 'UPDATE_TRIGGER_VALIDATOR', oils_i18n_gettext( 374, 
+    'Allow a user to update trigger validators', 'ppl', 'description' )),
+ ( 376, 'ADMIN_BOOKING_RESOURCE', oils_i18n_gettext( 376, 
+    'Enables the user to create/update/delete booking resources', 'ppl', 'description' )),
+ ( 377, 'ADMIN_BOOKING_RESOURCE_TYPE', oils_i18n_gettext( 377, 
+    'Enables the user to create/update/delete booking resource types', 'ppl', 'description' )),
+ ( 378, 'ADMIN_BOOKING_RESOURCE_ATTR', oils_i18n_gettext( 378, 
+    'Enables the user to create/update/delete booking resource attributes', 'ppl', 'description' )),
+ ( 379, 'ADMIN_BOOKING_RESOURCE_ATTR_MAP', oils_i18n_gettext( 379, 
+    'Enables the user to create/update/delete booking resource attribute maps', 'ppl', 'description' )),
+ ( 380, 'ADMIN_BOOKING_RESOURCE_ATTR_VALUE', oils_i18n_gettext( 380, 
+    'Enables the user to create/update/delete booking resource attribute values', 'ppl', 'description' )),
+ ( 381, 'ADMIN_BOOKING_RESERVATION', oils_i18n_gettext( 381, 
+    'Enables the user to create/update/delete booking reservations', 'ppl', 'description' )),
+ ( 382, 'ADMIN_BOOKING_RESERVATION_ATTR_VALUE_MAP', oils_i18n_gettext( 382, 
+    'Enables the user to create/update/delete booking reservation attribute value maps', 'ppl', 'description' )),
+ ( 383, 'RETRIEVE_RESERVATION_PULL_LIST', oils_i18n_gettext( 383, 
+    'Allows a user to retrieve a booking reservation pull list', 'ppl', 'description' )),
+ ( 384, 'CAPTURE_RESERVATION', oils_i18n_gettext( 384, 
+    'Allows a user to capture booking reservations', 'ppl', 'description' )),
+ ( 385, 'UPDATE_RECORD', oils_i18n_gettext( 385, 
+    'UPDATE_RECORD', 'ppl', 'description' )),
+ ( 386, 'UPDATE_ORG_UNIT_SETTING.circ.block_renews_for_holds', oils_i18n_gettext( 386, 
+    'UPDATE_ORG_UNIT_SETTING.circ.block_renews_for_holds', 'ppl', 'description' )),
+ ( 387, 'MERGE_USERS', oils_i18n_gettext( 387, 
+    'Allows user records to be merged', 'ppl', 'description' )),
+ ( 388, 'ISSUANCE_HOLDS', oils_i18n_gettext( 388, 
+    'Allow a user to place holds on serials issuances', 'ppl', 'description' )),
+ ( 389, 'VIEW_CREDIT_CARD_PROCESSING', oils_i18n_gettext( 389, 
+    'View org unit settings related to credit card processing', 'ppl', 'description' )),
+ ( 390, 'ADMIN_CREDIT_CARD_PROCESSING', oils_i18n_gettext( 390, 
+    'Update org unit settings related to credit card processing', 'ppl', 'description' )),
+ ( 391, 'ADMIN_ACQ_CLAIM', oils_i18n_gettext( 391, 
+    'ADMIN_ACQ_CLAIM', 'ppl', 'description' )),
+ ( 392, 'ADMIN_ACQ_CLAIM_EVENT_TYPE', oils_i18n_gettext( 392, 
+    'ADMIN_ACQ_CLAIM_EVENT_TYPE', 'ppl', 'description' )),
+ ( 393, 'ADMIN_ACQ_CLAIM_TYPE', oils_i18n_gettext( 393, 
+    'ADMIN_ACQ_CLAIM_TYPE', 'ppl', 'description' )),
+ ( 394, 'ADMIN_ACQ_DISTRIB_FORMULA', oils_i18n_gettext( 394, 
+    'ADMIN_ACQ_DISTRIB_FORMULA', 'ppl', 'description' )),
+ ( 395, 'ADMIN_ACQ_FISCAL_YEAR', oils_i18n_gettext( 395, 
+    'ADMIN_ACQ_FISCAL_YEAR', 'ppl', 'description' )),
+ ( 396, 'ADMIN_ACQ_FUND_ALLOCATION_PERCENT', oils_i18n_gettext( 396, 
+    'ADMIN_ACQ_FUND_ALLOCATION_PERCENT', 'ppl', 'description' )),
+ ( 397, 'ADMIN_ACQ_FUND_TAG', oils_i18n_gettext( 397, 
+    'ADMIN_ACQ_FUND_TAG', 'ppl', 'description' )),
+ ( 398, 'ADMIN_ACQ_LINEITEM_ALERT_TEXT', oils_i18n_gettext( 398, 
+    'ADMIN_ACQ_LINEITEM_ALERT_TEXT', 'ppl', 'description' )),
+ ( 399, 'ADMIN_AGE_PROTECT_RULE', oils_i18n_gettext( 399, 
+    'ADMIN_AGE_PROTECT_RULE', 'ppl', 'description' )),
+ ( 400, 'ADMIN_ASSET_COPY_TEMPLATE', oils_i18n_gettext( 400, 
+    'ADMIN_ASSET_COPY_TEMPLATE', 'ppl', 'description' )),
+ ( 401, 'ADMIN_BOOKING_RESERVATION_ATTR_MAP', oils_i18n_gettext( 401, 
+    'ADMIN_BOOKING_RESERVATION_ATTR_MAP', 'ppl', 'description' )),
+ ( 402, 'ADMIN_CIRC_MATRIX_MATCHPOINT', oils_i18n_gettext( 402, 
+    'ADMIN_CIRC_MATRIX_MATCHPOINT', 'ppl', 'description' )),
+ ( 403, 'ADMIN_CIRC_MOD', oils_i18n_gettext( 403, 
+    'ADMIN_CIRC_MOD', 'ppl', 'description' )),
+ ( 404, 'ADMIN_CLAIM_POLICY', oils_i18n_gettext( 404, 
+    'ADMIN_CLAIM_POLICY', 'ppl', 'description' )),
+ ( 405, 'ADMIN_CONFIG_REMOTE_ACCOUNT', oils_i18n_gettext( 405, 
+    'ADMIN_CONFIG_REMOTE_ACCOUNT', 'ppl', 'description' )),
+ ( 406, 'ADMIN_FIELD_DOC', oils_i18n_gettext( 406, 
+    'ADMIN_FIELD_DOC', 'ppl', 'description' )),
+ ( 407, 'ADMIN_GLOBAL_FLAG', oils_i18n_gettext( 407, 
+    'ADMIN_GLOBAL_FLAG', 'ppl', 'description' )),
+ ( 408, 'ADMIN_GROUP_PENALTY_THRESHOLD', oils_i18n_gettext( 408, 
+    'ADMIN_GROUP_PENALTY_THRESHOLD', 'ppl', 'description' )),
+ ( 409, 'ADMIN_HOLD_CANCEL_CAUSE', oils_i18n_gettext( 409, 
+    'ADMIN_HOLD_CANCEL_CAUSE', 'ppl', 'description' )),
+ ( 410, 'ADMIN_HOLD_MATRIX_MATCHPOINT', oils_i18n_gettext( 410, 
+    'ADMIN_HOLD_MATRIX_MATCHPOINT', 'ppl', 'description' )),
+ ( 411, 'ADMIN_IDENT_TYPE', oils_i18n_gettext( 411, 
+    'ADMIN_IDENT_TYPE', 'ppl', 'description' )),
+ ( 412, 'ADMIN_IMPORT_ITEM_ATTR_DEF', oils_i18n_gettext( 412, 
+    'ADMIN_IMPORT_ITEM_ATTR_DEF', 'ppl', 'description' )),
+ ( 413, 'ADMIN_INDEX_NORMALIZER', oils_i18n_gettext( 413, 
+    'ADMIN_INDEX_NORMALIZER', 'ppl', 'description' )),
+ ( 414, 'ADMIN_INVOICE', oils_i18n_gettext( 414, 
+    'ADMIN_INVOICE', 'ppl', 'description' )),
+ ( 415, 'ADMIN_INVOICE_METHOD', oils_i18n_gettext( 415, 
+    'ADMIN_INVOICE_METHOD', 'ppl', 'description' )),
+ ( 416, 'ADMIN_INVOICE_PAYMENT_METHOD', oils_i18n_gettext( 416, 
+    'ADMIN_INVOICE_PAYMENT_METHOD', 'ppl', 'description' )),
+ ( 417, 'ADMIN_LINEITEM_MARC_ATTR_DEF', oils_i18n_gettext( 417, 
+    'ADMIN_LINEITEM_MARC_ATTR_DEF', 'ppl', 'description' )),
+ ( 418, 'ADMIN_MARC_CODE', oils_i18n_gettext( 418, 
+    'ADMIN_MARC_CODE', 'ppl', 'description' )),
+ ( 419, 'ADMIN_MAX_FINE_RULE', oils_i18n_gettext( 419, 
+    'ADMIN_MAX_FINE_RULE', 'ppl', 'description' )),
+ ( 420, 'ADMIN_MERGE_PROFILE', oils_i18n_gettext( 420, 
+    'ADMIN_MERGE_PROFILE', 'ppl', 'description' )),
+ ( 421, 'ADMIN_ORG_UNIT_SETTING_TYPE', oils_i18n_gettext( 421, 
+    'ADMIN_ORG_UNIT_SETTING_TYPE', 'ppl', 'description' )),
+ ( 422, 'ADMIN_RECURRING_FINE_RULE', oils_i18n_gettext( 422, 
+    'ADMIN_RECURRING_FINE_RULE', 'ppl', 'description' )),
+ ( 423, 'ADMIN_SERIAL_SUBSCRIPTION', oils_i18n_gettext( 423, 
+    'ADMIN_SERIAL_SUBSCRIPTION', 'ppl', 'description' )),
+ ( 424, 'ADMIN_STANDING_PENALTY', oils_i18n_gettext( 424, 
+    'ADMIN_STANDING_PENALTY', 'ppl', 'description' )),
+ ( 425, 'ADMIN_SURVEY', oils_i18n_gettext( 425, 
+    'ADMIN_SURVEY', 'ppl', 'description' )),
+ ( 426, 'ADMIN_USER_REQUEST_TYPE', oils_i18n_gettext( 426, 
+    'ADMIN_USER_REQUEST_TYPE', 'ppl', 'description' )),
+ ( 427, 'ADMIN_USER_SETTING_GROUP', oils_i18n_gettext( 427, 
+    'ADMIN_USER_SETTING_GROUP', 'ppl', 'description' )),
+ ( 428, 'ADMIN_USER_SETTING_TYPE', oils_i18n_gettext( 428, 
+    'ADMIN_USER_SETTING_TYPE', 'ppl', 'description' )),
+ ( 429, 'ADMIN_Z3950_SOURCE', oils_i18n_gettext( 429, 
+    'ADMIN_Z3950_SOURCE', 'ppl', 'description' )),
+ ( 430, 'CREATE_BIB_BTYPE', oils_i18n_gettext( 430, 
+    'CREATE_BIB_BTYPE', 'ppl', 'description' )),
+ ( 431, 'CREATE_BIBLIO_FINGERPRINT', oils_i18n_gettext( 431, 
+    'CREATE_BIBLIO_FINGERPRINT', 'ppl', 'description' )),
+ ( 432, 'CREATE_BIB_SOURCE', oils_i18n_gettext( 432, 
+    'CREATE_BIB_SOURCE', 'ppl', 'description' )),
+ ( 433, 'CREATE_BILLING_TYPE', oils_i18n_gettext( 433, 
+    'CREATE_BILLING_TYPE', 'ppl', 'description' )),
+ ( 434, 'CREATE_CN_BTYPE', oils_i18n_gettext( 434, 
+    'CREATE_CN_BTYPE', 'ppl', 'description' )),
+ ( 435, 'CREATE_COPY_BTYPE', oils_i18n_gettext( 435, 
+    'CREATE_COPY_BTYPE', 'ppl', 'description' )),
+ ( 436, 'CREATE_INVOICE', oils_i18n_gettext( 436, 
+    'CREATE_INVOICE', 'ppl', 'description' )),
+ ( 437, 'CREATE_INVOICE_ITEM_TYPE', oils_i18n_gettext( 437, 
+    'CREATE_INVOICE_ITEM_TYPE', 'ppl', 'description' )),
+ ( 438, 'CREATE_INVOICE_METHOD', oils_i18n_gettext( 438, 
+    'CREATE_INVOICE_METHOD', 'ppl', 'description' )),
+ ( 439, 'CREATE_MERGE_PROFILE', oils_i18n_gettext( 439, 
+    'CREATE_MERGE_PROFILE', 'ppl', 'description' )),
+ ( 440, 'CREATE_METABIB_CLASS', oils_i18n_gettext( 440, 
+    'CREATE_METABIB_CLASS', 'ppl', 'description' )),
+ ( 441, 'CREATE_METABIB_SEARCH_ALIAS', oils_i18n_gettext( 441, 
+    'CREATE_METABIB_SEARCH_ALIAS', 'ppl', 'description' )),
+ ( 442, 'CREATE_USER_BTYPE', oils_i18n_gettext( 442, 
+    'CREATE_USER_BTYPE', 'ppl', 'description' )),
+ ( 443, 'DELETE_BIB_BTYPE', oils_i18n_gettext( 443, 
+    'DELETE_BIB_BTYPE', 'ppl', 'description' )),
+ ( 444, 'DELETE_BIBLIO_FINGERPRINT', oils_i18n_gettext( 444, 
+    'DELETE_BIBLIO_FINGERPRINT', 'ppl', 'description' )),
+ ( 445, 'DELETE_BIB_SOURCE', oils_i18n_gettext( 445, 
+    'DELETE_BIB_SOURCE', 'ppl', 'description' )),
+ ( 446, 'DELETE_BILLING_TYPE', oils_i18n_gettext( 446, 
+    'DELETE_BILLING_TYPE', 'ppl', 'description' )),
+ ( 447, 'DELETE_CN_BTYPE', oils_i18n_gettext( 447, 
+    'DELETE_CN_BTYPE', 'ppl', 'description' )),
+ ( 448, 'DELETE_COPY_BTYPE', oils_i18n_gettext( 448, 
+    'DELETE_COPY_BTYPE', 'ppl', 'description' )),
+ ( 449, 'DELETE_INVOICE_ITEM_TYPE', oils_i18n_gettext( 449, 
+    'DELETE_INVOICE_ITEM_TYPE', 'ppl', 'description' )),
+ ( 450, 'DELETE_INVOICE_METHOD', oils_i18n_gettext( 450, 
+    'DELETE_INVOICE_METHOD', 'ppl', 'description' )),
+ ( 451, 'DELETE_MERGE_PROFILE', oils_i18n_gettext( 451, 
+    'DELETE_MERGE_PROFILE', 'ppl', 'description' )),
+ ( 452, 'DELETE_METABIB_CLASS', oils_i18n_gettext( 452, 
+    'DELETE_METABIB_CLASS', 'ppl', 'description' )),
+ ( 453, 'DELETE_METABIB_SEARCH_ALIAS', oils_i18n_gettext( 453, 
+    'DELETE_METABIB_SEARCH_ALIAS', 'ppl', 'description' )),
+ ( 454, 'DELETE_USER_BTYPE', oils_i18n_gettext( 454, 
+    'DELETE_USER_BTYPE', 'ppl', 'description' )),
+ ( 455, 'MANAGE_CLAIM', oils_i18n_gettext( 455, 
+    'MANAGE_CLAIM', 'ppl', 'description' )),
+ ( 456, 'UPDATE_BIB_BTYPE', oils_i18n_gettext( 456, 
+    'UPDATE_BIB_BTYPE', 'ppl', 'description' )),
+ ( 457, 'UPDATE_BIBLIO_FINGERPRINT', oils_i18n_gettext( 457, 
+    'UPDATE_BIBLIO_FINGERPRINT', 'ppl', 'description' )),
+ ( 458, 'UPDATE_BIB_SOURCE', oils_i18n_gettext( 458, 
+    'UPDATE_BIB_SOURCE', 'ppl', 'description' )),
+ ( 459, 'UPDATE_BILLING_TYPE', oils_i18n_gettext( 459, 
+    'UPDATE_BILLING_TYPE', 'ppl', 'description' )),
+ ( 460, 'UPDATE_CN_BTYPE', oils_i18n_gettext( 460, 
+    'UPDATE_CN_BTYPE', 'ppl', 'description' )),
+ ( 461, 'UPDATE_COPY_BTYPE', oils_i18n_gettext( 461, 
+    'UPDATE_COPY_BTYPE', 'ppl', 'description' )),
+ ( 462, 'UPDATE_INVOICE_ITEM_TYPE', oils_i18n_gettext( 462, 
+    'UPDATE_INVOICE_ITEM_TYPE', 'ppl', 'description' )),
+ ( 463, 'UPDATE_INVOICE_METHOD', oils_i18n_gettext( 463, 
+    'UPDATE_INVOICE_METHOD', 'ppl', 'description' )),
+ ( 464, 'UPDATE_MERGE_PROFILE', oils_i18n_gettext( 464, 
+    'UPDATE_MERGE_PROFILE', 'ppl', 'description' )),
+ ( 465, 'UPDATE_METABIB_CLASS', oils_i18n_gettext( 465, 
+    'UPDATE_METABIB_CLASS', 'ppl', 'description' )),
+ ( 466, 'UPDATE_METABIB_SEARCH_ALIAS', oils_i18n_gettext( 466, 
+    'UPDATE_METABIB_SEARCH_ALIAS', 'ppl', 'description' )),
+ ( 467, 'UPDATE_USER_BTYPE', oils_i18n_gettext( 467, 
+    'UPDATE_USER_BTYPE', 'ppl', 'description' )),
+ ( 468, 'user_request.create', oils_i18n_gettext( 468, 
+    'user_request.create', 'ppl', 'description' )),
+ ( 469, 'user_request.delete', oils_i18n_gettext( 469, 
+    'user_request.delete', 'ppl', 'description' )),
+ ( 470, 'user_request.update', oils_i18n_gettext( 470, 
+    'user_request.update', 'ppl', 'description' )),
+ ( 471, 'user_request.view', oils_i18n_gettext( 471, 
+    'user_request.view', 'ppl', 'description' )),
+ ( 472, 'VIEW_ACQ_FUND_ALLOCATION_PERCENT', oils_i18n_gettext( 472, 
+    'VIEW_ACQ_FUND_ALLOCATION_PERCENT', 'ppl', 'description' )),
+ ( 473, 'VIEW_CIRC_MATRIX_MATCHPOINT', oils_i18n_gettext( 473, 
+    'VIEW_CIRC_MATRIX_MATCHPOINT', 'ppl', 'description' )),
+ ( 474, 'VIEW_CLAIM', oils_i18n_gettext( 474, 
+    'VIEW_CLAIM', 'ppl', 'description' )),
+ ( 475, 'VIEW_GROUP_PENALTY_THRESHOLD', oils_i18n_gettext( 475, 
+    'VIEW_GROUP_PENALTY_THRESHOLD', 'ppl', 'description' )),
+ ( 476, 'VIEW_HOLD_MATRIX_MATCHPOINT', oils_i18n_gettext( 476, 
+    'VIEW_HOLD_MATRIX_MATCHPOINT', 'ppl', 'description' )),
+ ( 477, 'VIEW_INVOICE', oils_i18n_gettext( 477, 
+    'VIEW_INVOICE', 'ppl', 'description' )),
+ ( 478, 'VIEW_MERGE_PROFILE', oils_i18n_gettext( 478, 
+    'VIEW_MERGE_PROFILE', 'ppl', 'description' )),
+ ( 479, 'VIEW_SERIAL_SUBSCRIPTION', oils_i18n_gettext( 479, 
+    'VIEW_SERIAL_SUBSCRIPTION', 'ppl', 'description' )),
+ ( 480, 'VIEW_STANDING_PENALTY', oils_i18n_gettext( 480, 
+    'VIEW_STANDING_PENALTY', 'ppl', 'description' )),
+ ( 481, 'ADMIN_SERIAL_CAPTION_PATTERN', oils_i18n_gettext( 481, 
+    'ADMIN_SERIAL_CAPTION_PATTERN', 'ppl', 'description' )),
+ ( 482, 'ADMIN_SERIAL_DISTRIBUTION', oils_i18n_gettext( 482, 
+    'ADMIN_SERIAL_DISTRIBUTION', 'ppl', 'description' )),
+ ( 483, 'ADMIN_SERIAL_STREAM', oils_i18n_gettext( 483, 
+    'ADMIN_SERIAL_STREAM', 'ppl', 'description' )),
+ ( 484, 'RECEIVE_SERIAL', oils_i18n_gettext(484, 'Receive serial items', 'ppl', 'description'));
 
 
 SELECT SETVAL('permission.perm_list_id_seq'::TEXT, 1000);
@@ -1619,7 +2174,7 @@ SELECT SETVAL('asset.copy_location_id_seq'::TEXT, 100);
 INSERT INTO asset.call_number VALUES (-1,1,NOW(),1,NOW(),-1,1,'UNCATALOGED');
 
 -- circ matrix
-INSERT INTO config.circ_matrix_matchpoint (org_unit,grp,duration_rule,recurring_fine_rule,max_fine_rule) VALUES (1,1,11,1,1);
+INSERT INTO config.circ_matrix_matchpoint (org_unit,grp,circulate,duration_rule,recurring_fine_rule,max_fine_rule) VALUES (1,1,true,11,1,1);
 
 INSERT INTO config.circ_matrix_weights(name, org_unit, grp, circ_modifier, marc_type, marc_form, marc_vr_format, copy_circ_lib, copy_owning_lib, user_home_ou, ref_flag, juvenile_flag, is_renewal, usr_age_upper_bound, usr_age_lower_bound) VALUES 
     ('Default', 10.0, 11.0, 5.0, 4.0, 3.0, 2.0, 8.0, 8.0, 8.0, 1.0, 6.0, 7.0, 0.0, 0.0),
@@ -1671,375 +2226,369 @@ INSERT into config.org_unit_setting_type
 ( name, label, description, datatype ) VALUES
 
 ( 'auth.opac_timeout',
-  'OPAC Inactivity Timeout (in seconds)',
-  null,
-  'integer' ),
+    oils_i18n_gettext('auth.opac_timeout', 'OPAC Inactivity Timeout (in seconds)', 'coust', 'label'),
+    oils_i18n_gettext('auth.opac_timeout', 'OPAC Inactivity Timeout (in seconds)', 'coust', 'description'),
+    'integer'),
 
 ( 'auth.staff_timeout',
-  'Staff Login Inactivity Timeout (in seconds)',
-  null,
-  'integer' ),
+    oils_i18n_gettext('auth.staff_timeout', 'Staff Login Inactivity Timeout (in seconds)', 'coust', 'label'),
+    oils_i18n_gettext('auth.staff_timeout', 'Staff Login Inactivity Timeout (in seconds)', 'coust', 'description'),
+    'integer'),
 
 ( 'circ.lost_materials_processing_fee',
-  'Lost Materials Processing Fee',
-  null,
-  'currency' ),
+    oils_i18n_gettext('circ.lost_materials_processing_fee', 'Lost Materials Processing Fee', 'coust', 'label'),
+    oils_i18n_gettext('circ.lost_materials_processing_fee', 'Lost Materials Processing Fee', 'coust', 'description'),
+    'currency'),
 
 ( 'cat.default_item_price',
-  'Default Item Price',
-  null,
-  'currency' ),
+    oils_i18n_gettext('cat.default_item_price', 'Default Item Price', 'coust', 'label'),
+    oils_i18n_gettext('cat.default_item_price', 'Default Item Price', 'coust', 'description'),
+    'currency'),
 
 ( 'org.bounced_emails',
-  'Sending email address for patron notices',
-  null,
-  'string' ),
+    oils_i18n_gettext('org.bounced_emails', 'Sending email address for patron notices', 'coust', 'label'),
+    oils_i18n_gettext('org.bounced_emails', 'Sending email address for patron notices', 'coust', 'description'),
+    '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' ),
+    oils_i18n_gettext('circ.hold_expire_alert_interval', 'Holds: Expire Alert Interval', 'coust', 'label'),
+    oils_i18n_gettext('circ.hold_expire_alert_interval', 'Amount of time before a hold expires at which point the patron should be alerted', 'coust', 'description'),
+    'interval'),
 
 ( 'circ.hold_expire_interval',
-  'Holds: Expire Interval',
-  'Amount of time after a hold is placed before the hold expires.  Example "100 days"',
-  'interval' ),
+    oils_i18n_gettext('circ.hold_expire_interval', 'Holds: Expire Interval', 'coust', 'label'),
+    oils_i18n_gettext('circ.hold_expire_interval', 'Amount of time after a hold is placed before the hold expires.  Example "100 days"', 'coust', 'description'),
+    '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' ),
+    oils_i18n_gettext('credit.payments.allow', 'Allow Credit Card Payments', 'coust', 'label'),
+    oils_i18n_gettext('credit.payments.allow', 'If enabled, patrons will be able to pay fines accrued at this location via credit card', 'coust', 'description'),
+    'bool'),
 
 ( 'global.default_locale',
-  'Global Default Locale',
-  null,
-  'string' ),
+    oils_i18n_gettext('global.default_locale', 'Global Default Locale', 'coust', 'label'),
+    oils_i18n_gettext('global.default_locale', 'Global Default Locale', 'coust', 'description'),
+    'string'),
 
 ( 'circ.void_overdue_on_lost',
-  'Void overdue fines when items are marked lost',
-  null,
-  'bool' ),
+    oils_i18n_gettext('circ.void_overdue_on_lost', 'Void overdue fines when items are marked lost', 'coust', 'label'),
+    oils_i18n_gettext('circ.void_overdue_on_lost', 'Void overdue fines when items are marked lost', 'coust', 'description'),
+    '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' ),
+    oils_i18n_gettext('circ.hold_stalling.soft', 'Holds: Soft stalling interval', 'coust', 'label'),
+    oils_i18n_gettext('circ.hold_stalling.soft', 'How long to wait before allowing remote items to be opportunistically captured for a hold.  Example "5 days"', 'coust', 'description'),
+    'interval'),
 
 ( 'circ.hold_stalling_hard',
-  'Holds: Hard stalling interval',
-  '',
-  'interval' ),
+    oils_i18n_gettext('circ.hold_stalling_hard', 'Holds: Hard stalling interval', 'coust', 'label'),
+    oils_i18n_gettext('circ.hold_stalling_hard', '', 'coust', 'description'),
+    'interval'),
 
 ( 'circ.hold_boundary.hard',
-  'Holds: Hard boundary',
-  null,
-  'integer' ),
+    oils_i18n_gettext('circ.hold_boundary.hard', 'Holds: Hard boundary', 'coust', 'label'),
+    oils_i18n_gettext('circ.hold_boundary.hard', 'Holds: Hard boundary', 'coust', 'description'),
+    'integer'),
 
 ( 'circ.hold_boundary.soft',
-  'Holds: Soft boundary',
-  null,
-  'integer' ),
+    oils_i18n_gettext('circ.hold_boundary.soft', 'Holds: Soft boundary', 'coust', 'label'),
+    oils_i18n_gettext('circ.hold_boundary.soft', 'Holds: Soft boundary', 'coust', 'description'),
+    'integer'),
 
 ( 'opac.barcode_regex',
-  'Patron barcode format',
-  'Regular expression defining the patron barcode format',
-  'string' ),
+    oils_i18n_gettext('opac.barcode_regex', 'Patron barcode format', 'coust', 'label'),
+    oils_i18n_gettext('opac.barcode_regex', 'Regular expression defining the patron barcode format', 'coust', 'description'),
+    'string'),
 
 ( 'global.password_regex',
-  'Password format',
-  'Regular expression defining the password format',
-  'string' ),
+    oils_i18n_gettext('global.password_regex', 'Password format', 'coust', 'label'),
+    oils_i18n_gettext('global.password_regex', 'Regular expression defining the password format', 'coust', 'description'),
+    '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' ),
+    oils_i18n_gettext('circ.item_checkout_history.max', 'Maximum previous checkouts displayed', 'coust', 'label'),
+    oils_i18n_gettext('circ.item_checkout_history.max', 'This is the maximum number of previous circulations the staff client will display when investigating item details', 'coust', 'description'),
+    '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' ),
+    oils_i18n_gettext('circ.reshelving_complete.interval', 'Change reshelving status interval', 'coust', 'label'),
+    oils_i18n_gettext('circ.reshelving_complete.interval', 'Amount of time to wait before changing an item from "reshelving" status to "available".  Examples: "1 day", "6 hours"', 'coust', 'description'),
+    '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' ),
+    oils_i18n_gettext('circ.holds.default_estimated_wait_interval', 'Holds: Default Estimated Wait', 'coust', 'label'),
+    oils_i18n_gettext('circ.holds.default_estimated_wait_interval', '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.', 'coust', 'description'),
+    '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' ),
+    oils_i18n_gettext('circ.holds.min_estimated_wait_interval', 'Holds: Minimum Estimated Wait', 'coust', 'label'),
+    oils_i18n_gettext('circ.holds.min_estimated_wait_interval', '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.', 'coust', 'description'),
+    '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' ),
+    oils_i18n_gettext('circ.selfcheck.patron_login_timeout', 'Selfcheck: Patron Login Timeout (in seconds)', 'coust', 'label'),
+    oils_i18n_gettext('circ.selfcheck.patron_login_timeout', 'Number of seconds of inactivity before the patron is logged out of the selfcheck interface', 'coust', 'description'),
+    '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' ),
+    oils_i18n_gettext('circ.selfcheck.alert.popup', 'Selfcheck: Pop-up alert for errors', 'coust', 'label'),
+    oils_i18n_gettext('circ.selfcheck.alert.popup', 'If true, checkout/renewal errors will cause a pop-up window in addition to the on-screen message', 'coust', 'description'),
+    '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' ),
+    oils_i18n_gettext('circ.selfcheck.require_patron_password', 'Selfcheck: Require patron password', 'coust', 'label'),
+    oils_i18n_gettext('circ.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', 'coust', 'description'),
+    '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' ),
+    oils_i18n_gettext('global.juvenile_age_threshold', 'Juvenile Age Threshold', 'coust', 'label'),
+    oils_i18n_gettext('global.juvenile_age_threshold', 'The age at which a user is no long considered a juvenile.  For example, "18 years".', 'coust', 'description'),
+    'interval'),
 
 ( 'cat.bib.keep_on_empty',
-  'Retain empty bib records',
-  'Retain a bib record even when all attached copies are deleted',
-  'bool' ),
+    oils_i18n_gettext('cat.bib.keep_on_empty', 'Retain empty bib records', 'coust', 'label'),
+    oils_i18n_gettext('cat.bib.keep_on_empty', 'Retain a bib record even when all attached copies are deleted', 'coust', 'description'),
+    'bool'),
 
 ( 'cat.bib.alert_on_empty',
-  'Alert on empty bib records',
-  'Alert staff when the last copy for a record is being deleted',
-  'bool' ),
+    oils_i18n_gettext('cat.bib.alert_on_empty', 'Alert on empty bib records', 'coust', 'label'),
+    oils_i18n_gettext('cat.bib.alert_on_empty', 'Alert staff when the last copy for a record is being deleted', 'coust', 'description'),
+    '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' ),
+    oils_i18n_gettext('patron.password.use_phone', 'Patron: password from phone #', 'coust', 'label'),
+    oils_i18n_gettext('patron.password.use_phone', 'Use the last 4 digits of the patrons phone number as the default password when creating new users', 'coust', 'description'),
+    'bool'),
 
 ( 'circ.charge_on_damaged',
-  'Charge item price when marked damaged',
-  'Charge item price when marked damaged',
-  'bool' ),
+    oils_i18n_gettext('circ.charge_on_damaged', 'Charge item price when marked damaged', 'coust', 'label'),
+    oils_i18n_gettext('circ.charge_on_damaged', 'Charge item price when marked damaged', 'coust', 'description'),
+    'bool'),
 
 ( 'circ.charge_lost_on_zero',
-  'Charge lost on zero',
-  '',
-  'bool' ),
+    oils_i18n_gettext('circ.charge_lost_on_zero', 'Charge lost on zero', 'coust', 'label'),
+    oils_i18n_gettext('circ.charge_lost_on_zero', '', 'coust', 'description'),
+    'bool'),
 
 ( 'circ.damaged_item_processing_fee',
-  'Charge processing fee for damaged items',
-  'Charge processing fee for damaged items',
-  'currency' ),
+    oils_i18n_gettext('circ.damaged_item_processing_fee', 'Charge processing fee for damaged items', 'coust', 'label'),
+    oils_i18n_gettext('circ.damaged_item_processing_fee', 'Charge processing fee for damaged items', 'coust', 'description'),
+    'currency'),
 
 ( 'circ.void_lost_on_checkin',
-  'Circ: Void lost item billing when returned',
-  'Void lost item billing when returned',
-  'bool' ),
+    oils_i18n_gettext('circ.void_lost_on_checkin', 'Circ: Void lost item billing when returned', 'coust', 'label'),
+    oils_i18n_gettext('circ.void_lost_on_checkin', 'Void lost item billing when returned', 'coust', 'description'),
+    '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' ),
+    oils_i18n_gettext('circ.max_accept_return_of_lost', 'Circ: Void lost max interval', 'coust', 'label'),
+    oils_i18n_gettext('circ.max_accept_return_of_lost', 'Items that have been lost this long will not result in voided billings when returned.  E.g. ''6 months''', 'coust', 'description'),
+    'interval'),
 
 ( 'circ.void_lost_proc_fee_on_checkin',
-  'Circ: Void processing fee on lost item return',
-  'Void processing fee when lost item returned',
-  'bool' ),
+    oils_i18n_gettext('circ.void_lost_proc_fee_on_checkin', 'Circ: Void processing fee on lost item return', 'coust', 'label'),
+    oils_i18n_gettext('circ.void_lost_proc_fee_on_checkin', 'Void processing fee when lost item returned', 'coust', 'description'),
+    'bool'),
 
 ( 'circ.restore_overdue_on_lost_return',
-  'Circ: Restore overdues on lost item return',
-  'Restore overdue fines on lost item return',
-  'bool' ),
+    oils_i18n_gettext('circ.restore_overdue_on_lost_return', 'Circ: Restore overdues on lost item return', 'coust', 'label'),
+    oils_i18n_gettext('circ.restore_overdue_on_lost_return', 'Restore overdue fines on lost item return', 'coust', 'description'),
+    'bool'),
 
 ( 'circ.lost_immediately_available',
-  'Circ: Lost items usable on checkin',
-  'Lost items are usable on checkin instead of going ''home'' first',
-  'bool' ),
+    oils_i18n_gettext('circ.lost_immediately_available', 'Circ: Lost items usable on checkin', 'coust', 'label'),
+    oils_i18n_gettext('circ.lost_immediately_available', 'Lost items are usable on checkin instead of going ''home'' first', 'coust', 'description'),
+    'bool'),
 
 ( 'circ.holds_fifo',
-  'Holds: FIFO',
-  'Force holds to a more strict First-In, First-Out capture',
-  'bool' ),
+    oils_i18n_gettext('circ.holds_fifo', 'Holds: FIFO', 'coust', 'label'),
+    oils_i18n_gettext('circ.holds_fifo', 'Force holds to a more strict First-In, First-Out capture', 'coust', 'description'),
+    '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' ),
+    oils_i18n_gettext('opac.allow_pending_address', 'OPAC: Allow pending addresses', 'coust', 'label'),
+    oils_i18n_gettext('opac.allow_pending_address', 'If enabled, patrons can create and edit existing addresses.  Addresses are kept in a pending state until staff approves the changes', 'coust', 'description'),
+    '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' ),
+    oils_i18n_gettext('ui.circ.show_billing_tab_on_bills', 'Show billing tab first when bills are present', 'coust', 'label'),
+    oils_i18n_gettext('ui.circ.show_billing_tab_on_bills', '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', 'coust', 'description'),
+    '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' ),
+    oils_i18n_gettext('ui.general.idle_timeout', 'GUI: Idle timeout', 'coust', 'label'),
+    oils_i18n_gettext('ui.general.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).', 'coust', 'description'),
+    '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' ),
+    oils_i18n_gettext('ui.circ.in_house_use.entry_cap', 'GUI: Record In-House Use: Maximum # of uses allowed per entry.', 'coust', 'label'),
+    oils_i18n_gettext('ui.circ.in_house_use.entry_cap', 'The # of uses entry in the Record In-House Use interface may not exceed the value of this setting.', 'coust', 'description'),
+    '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' ),
+    oils_i18n_gettext('ui.circ.in_house_use.entry_warn', 'GUI: Record In-House Use: # of uses threshold for Are You Sure? dialog.', 'coust', 'label'),
+    oils_i18n_gettext('ui.circ.in_house_use.entry_warn', 'In the Record In-House Use interface, a submission attempt will warn if the # of uses field exceeds the value of this setting.', 'coust', 'description'),
+    'integer'),
 
 ( 'acq.default_circ_modifier',
-  'Default circulation modifier',
-  null,
-  'string' ),
+    oils_i18n_gettext('acq.default_circ_modifier', 'Default circulation modifier', 'coust', 'label'),
+    oils_i18n_gettext('acq.default_circ_modifier', 'Default circulation modifier', 'coust', 'description'),
+    'string'),
 
 ( 'acq.tmp_barcode_prefix',
-  'Temporary barcode prefix',
-  null,
-  'string' ),
+    oils_i18n_gettext('acq.tmp_barcode_prefix', 'Temporary barcode prefix', 'coust', 'label'),
+    oils_i18n_gettext('acq.tmp_barcode_prefix', 'Temporary barcode prefix', 'coust', 'description'),
+    'string'),
 
 ( 'acq.tmp_callnumber_prefix',
-  'Temporary call number prefix',
-  null,
-  'string' ),
+    oils_i18n_gettext('acq.tmp_callnumber_prefix', 'Temporary call number prefix', 'coust', 'label'),
+    oils_i18n_gettext('acq.tmp_callnumber_prefix', 'Temporary call number prefix', 'coust', 'description'),
+    'string'),
 
 ( 'ui.circ.patron_summary.horizontal',
-  'Patron circulation summary is horizontal',
-  null,
-  'bool' ),
+    oils_i18n_gettext('ui.circ.patron_summary.horizontal', 'Patron circulation summary is horizontal', 'coust', 'label'),
+    oils_i18n_gettext('ui.circ.patron_summary.horizontal', 'Patron circulation summary is horizontal', 'coust', 'description'),
+    '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' ),
+    'bool'),
 
 ( 'ui.general.button_bar',
-  'Button bar',
-  null,
-  'bool' ),
+    oils_i18n_gettext('ui.general.button_bar', 'Button bar', 'coust', 'label'),
+    oils_i18n_gettext('ui.general.button_bar', 'Button bar', 'coust', 'description'),
+    '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' ),
+    oils_i18n_gettext('circ.hold_shelf_status_delay', 'Hold Shelf Status Delay', 'coust', 'label'),
+    oils_i18n_gettext('circ.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.', 'coust', 'description'),
+    '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' ),
+    oils_i18n_gettext('circ.patron_invalid_address_apply_penalty', 'Invalid patron address penalty', 'coust', 'label'),
+    oils_i18n_gettext('circ.patron_invalid_address_apply_penalty', 'When set, if a patron address is set to invalid, a penalty is applied.', 'coust', 'description'),
+    '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'),
+    oils_i18n_gettext('circ.checkout_fills_related_hold', 'Checkout Fills Related Hold', 'coust', 'label'),
+    oils_i18n_gettext('circ.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', 'coust', 'description'),
+    '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' ),
+    oils_i18n_gettext('circ.selfcheck.auto_override_checkout_events', 'Selfcheck override events list', 'coust', 'label'),
+    oils_i18n_gettext('circ.selfcheck.auto_override_checkout_events', 'List of checkout/renewal events that the selfcheck interface should automatically override instead instead of alerting and stopping the transaction', 'coust', 'description'),
+    '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' ),
+    oils_i18n_gettext('circ.staff_client.do_not_auto_attempt_print', 'Disable Automatic Print Attempt Type List', 'coust', 'label'),
+    oils_i18n_gettext('circ.staff_client.do_not_auto_attempt_print', '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).', 'coust', 'description'),
+    'array'),
 
 ( 'ui.patron.default_inet_access_level',
-  'Default level of patrons'' internet access',
-  null,
-  'integer' ),
+    oils_i18n_gettext('ui.patron.default_inet_access_level', 'Default level of patrons'' internet access', 'coust', 'label'),
+    oils_i18n_gettext('ui.patron.default_inet_access_level', 'Default level of patrons'' internet access', 'coust', 'description'),
+    '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' ),
+    oils_i18n_gettext('circ.max_patron_claim_return_count', 'Max Patron Claims Returned Count', 'coust', 'label'),
+    oils_i18n_gettext('circ.max_patron_claim_return_count', 'When this count is exceeded, a staff override is required to mark the item as claims returned', 'coust', 'description'),
+    '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' ),
+    oils_i18n_gettext('circ.obscure_dob', 'Obscure the Date of Birth field', 'coust', 'label'),
+    oils_i18n_gettext('circ.obscure_dob', '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.', 'coust', 'description'),
+    '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' ),
+    oils_i18n_gettext('circ.auto_hide_patron_summary', 'GUI: Toggle off the patron summary sidebar after first view.', 'coust', 'label'),
+    oils_i18n_gettext('circ.auto_hide_patron_summary', 'When true, the patron summary sidebar will collapse after a new patron sub-interface is selected.', 'coust', 'description'),
+    'bool'),
 
 ( 'credit.processor.default',
-    'Credit card processing: Name default credit processor',
-    'This might be "AuthorizeNet", "PayPal", etc.',
-    'string' ),
+    oils_i18n_gettext('credit.processor.default', 'Credit card processing: Name default credit processor', 'coust', 'label'),
+    oils_i18n_gettext('credit.processor.default', 'This might be "AuthorizeNet", "PayPal", etc.', 'coust', 'description'),
+    'string'),
 
 ( 'credit.processor.authorizenet.enabled',
-    'Credit card processing: Enable AuthorizeNet payments',
-    '',
-    'bool' ),
+    oils_i18n_gettext('credit.processor.authorizenet.enabled', 'Credit card processing: Enable AuthorizeNet payments', 'coust', 'label'),
+    oils_i18n_gettext('credit.processor.authorizenet.enabled', '', 'coust', 'description'),
+    'bool'),
 
 ( 'credit.processor.authorizenet.login',
-    'Credit card processing: AuthorizeNet login',
-    '',
-    'string' ),
+    oils_i18n_gettext('credit.processor.authorizenet.login', 'Credit card processing: AuthorizeNet login', 'coust', 'label'),
+    oils_i18n_gettext('credit.processor.authorizenet.login', '', 'coust', 'description'),
+    'string'),
 
 ( 'credit.processor.authorizenet.password',
-    'Credit card processing: AuthorizeNet password',
-    '',
-    'string' ),
+    oils_i18n_gettext('credit.processor.authorizenet.password', 'Credit card processing: AuthorizeNet password', 'coust', 'label'),
+    oils_i18n_gettext('credit.processor.authorizenet.password', '', 'coust', 'description'),
+    'string'),
 
 ( 'credit.processor.authorizenet.server',
-    'Credit card processing: AuthorizeNet server',
-    'Required if using a developer/test account with AuthorizeNet',
-    'string' ),
+    oils_i18n_gettext('credit.processor.authorizenet.server', 'Credit card processing: AuthorizeNet server', 'coust', 'label'),
+    oils_i18n_gettext('credit.processor.authorizenet.server', 'Required if using a developer/test account with AuthorizeNet', 'coust', 'description'),
+    'string'),
 
 ( 'credit.processor.authorizenet.testmode',
-    'Credit card processing: AuthorizeNet test mode',
-    '',
-    'bool' ),
+    oils_i18n_gettext('credit.processor.authorizenet.testmode', 'Credit card processing: AuthorizeNet test mode', 'coust', 'label'),
+    oils_i18n_gettext('credit.processor.authorizenet.testmode', '', 'coust', 'description'),
+    'bool'),
 
 ( 'credit.processor.paypal.enabled',
-    'Credit card processing: Enable PayPal payments',
-    '',
-    'bool' ),
+    oils_i18n_gettext('credit.processor.paypal.enabled', 'Credit card processing: Enable PayPal payments', 'coust', 'label'),
+    oils_i18n_gettext('credit.processor.paypal.enabled', '', 'coust', 'description'),
+    'bool'),
 ( 'credit.processor.paypal.login',
-    'Credit card processing: PayPal login',
-    '',
-    'string' ),
+    oils_i18n_gettext('credit.processor.paypal.login', 'Credit card processing: PayPal login', 'coust', 'label'),
+    oils_i18n_gettext('credit.processor.paypal.login', '', 'coust', 'description'),
+    'string'),
 ( 'credit.processor.paypal.password',
-    'Credit card processing: PayPal password',
-    '',
-    'string' ),
+    oils_i18n_gettext('credit.processor.paypal.password', 'Credit card processing: PayPal password', 'coust', 'label'),
+    oils_i18n_gettext('credit.processor.paypal.password', '', 'coust', 'description'),
+    'string'),
 ( 'credit.processor.paypal.signature',
-    'Credit card processing: PayPal signature',
-    '',
-    'string' ),
+    oils_i18n_gettext('credit.processor.paypal.signature', 'Credit card processing: PayPal signature', 'coust', 'label'),
+    oils_i18n_gettext('credit.processor.paypal.signature', '', 'coust', 'description'),
+    'string'),
 ( 'credit.processor.paypal.testmode',
-    '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'
-),
+    oils_i18n_gettext('credit.processor.paypal.testmode', 'Credit card processing: PayPal test mode', 'coust', 'label'),
+    oils_i18n_gettext('credit.processor.paypal.testmode', '', 'coust', 'description'),
+    'bool'),
+( 'credit.processor.payflowpro.enabled',
+    oils_i18n_gettext('credit.processor.payflowpro.enabled', 'Credit card processing: Enable PayflowPro payments', 'coust', 'label'),
+    oils_i18n_gettext('credit.processor.payflowpro.enabled', 'This is NOT the same thing as the settings labeled with just "PayPal."', 'coust', 'description'),
+    'bool'),
+( 'credit.processor.payflowpro.login',
+    oils_i18n_gettext('credit.processor.payflowpro.login', 'Credit card processing: PayflowPro login/merchant ID', 'coust', 'label'),
+    oils_i18n_gettext('credit.processor.payflowpro.login', 'Often the same thing as the PayPal manager login', 'coust', 'description'),
+    'string'),
+( 'credit.processor.payflowpro.password',
+    oils_i18n_gettext('credit.processor.payflowpro.password', 'Credit card processing: PayflowPro password', 'coust', 'label'),
+    oils_i18n_gettext('credit.processor.payflowpro.password', 'PayflowPro password', 'coust', 'description'),
+    'string'),
+( 'credit.processor.payflowpro.testmode',
+    oils_i18n_gettext('credit.processor.payflowpro.testmode', 'Credit card processing: PayflowPro test mode', 'coust', 'label'),
+    oils_i18n_gettext('credit.processor.payflowpro.testmode', 'Do not really process transactions, but stay in test mode - uses pilot-payflowpro.paypal.com instead of the usual host', 'coust', 'description'),
+    'bool'),
+( 'credit.processor.payflowpro.vendor',
+    oils_i18n_gettext('credit.processor.payflowpro.vendor', 'Credit card processing: PayflowPro vendor', 'coust', 'label'),
+    oils_i18n_gettext('credit.processor.payflowpro.vendor', 'Often the same thing as the login', 'coust', 'description'),
+    'string'),
+( 'credit.processor.payflowpro.partner',
+    oils_i18n_gettext('credit.processor.payflowpro.partner', 'Credit card processing: PayflowPro partner', 'coust', 'label'),
+    oils_i18n_gettext('credit.processor.payflowpro.partner', 'Often "PayPal" or "VeriSign", sometimes others', 'coust', 'description'),
+    'string'),
 
 ( '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' ),
+    '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' ),
+    'interval'),
 
 ( 'lib.courier_code',
     oils_i18n_gettext('lib.courier_code', 'Courier Code', 'coust', 'label'),
@@ -2049,7 +2598,7 @@ INSERT into config.org_unit_setting_type
 ( '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' ),
+    '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'),
@@ -2067,9 +2616,8 @@ INSERT into config.org_unit_setting_type
     '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',
+    oils_i18n_gettext('opac.fully_compressed_serial_holdings', 'OPAC: Use fully compressed serial holdings', 'coust', 'label'),
+    oils_i18n_gettext('opac.fully_compressed_serial_holdings', 'Show fully compressed serial holdings for all libraries at and below the current context unit', 'coust', 'description'),
     'bool')
 ;
 
@@ -2241,8 +2789,8 @@ INSERT INTO actor.org_unit_setting (org_unit, name, value) VALUES (
 INSERT into config.org_unit_setting_type
 ( name, label, description, datatype, fm_class ) VALUES
 ( 'acq.default_copy_location',
-  'Default copy location',
-  null,
+  oils_i18n_gettext( 'acq.default_copy_location', 'Default copy location', 'coust', 'label'),
+  oils_i18n_gettext( 'acq.default_copy_location', 'Default copy location', 'coust', 'description'),
   'link',
   'acpl' );
 
diff --git a/Open-ILS/src/sql/Pg/upgrade/0487.circ_matrix_fallthrough.sql b/Open-ILS/src/sql/Pg/upgrade/0487.circ_matrix_fallthrough.sql
new file mode 100644 (file)
index 0000000..0c4b71e
--- /dev/null
@@ -0,0 +1,404 @@
+BEGIN;
+
+INSERT INTO config.upgrade_log (version) VALUES ('0487'); -- tsbere via miker
+
+-- Circ matchpoint table changes
+
+ALTER TABLE config.circ_matrix_matchpoint
+    ALTER COLUMN circulate DROP NOT NULL, -- Fallthrough enable
+    ALTER COLUMN circulate DROP DEFAULT, -- Stop defaulting to true to enable default to fallthrough
+    ALTER COLUMN duration_rule DROP NOT NULL, -- Fallthrough enable
+    ALTER COLUMN recurring_fine_rule DROP NOT NULL, -- Fallthrough enable
+    ALTER COLUMN max_fine_rule DROP NOT NULL, -- Fallthrough enable
+    ADD COLUMN renewals INT; -- Renewals override
+
+-- Changing return types requires explicit dropping of old versions
+DROP FUNCTION action.find_circ_matrix_matchpoint( context_ou INT, match_item BIGINT, match_user INT, renewal BOOL );
+DROP FUNCTION action.item_user_circ_test( circ_ou INT, match_item BIGINT, match_user INT, renewal BOOL );
+DROP FUNCTION action.item_user_circ_test( INT, BIGINT, INT );
+DROP FUNCTION action.item_user_renew_test( INT, BIGINT, INT );
+
+-- New return types
+CREATE TYPE action.found_circ_matrix_matchpoint AS ( success BOOL, matchpoint config.circ_matrix_matchpoint, buildrows INT[] );
+CREATE TYPE action.circ_matrix_test_result AS ( success BOOL, fail_part TEXT, buildrows INT[], matchpoint INT, circulate BOOL, duration_rule INT, recurring_fine_rule INT, max_fine_rule INT, hard_due_date INT, renewals INT );
+
+-- Replacement functions
+CREATE OR REPLACE FUNCTION action.find_circ_matrix_matchpoint( context_ou INT, item_object asset.copy, user_object actor.usr, renewal BOOL ) RETURNS action.found_circ_matrix_matchpoint AS $func$
+DECLARE
+    cn_object       asset.call_number%ROWTYPE;
+    rec_descriptor  metabib.rec_descriptor%ROWTYPE;
+    cur_matchpoint  config.circ_matrix_matchpoint%ROWTYPE;
+    matchpoint      config.circ_matrix_matchpoint%ROWTYPE;
+    weights         config.circ_matrix_weights%ROWTYPE;
+    user_age        INTERVAL;
+    denominator     NUMERIC(6,2);
+    row_list        INT[];
+    result          action.found_circ_matrix_matchpoint;
+BEGIN
+    -- Assume failure
+    result.success = false;
+
+    -- Fetch useful data
+    SELECT INTO cn_object       * FROM asset.call_number        WHERE id = item_object.call_number;
+    SELECT INTO rec_descriptor  * FROM metabib.rec_descriptor   WHERE record = cn_object.record;
+
+    -- Pre-generate this so we only calc it once
+    IF user_object.dob IS NOT NULL THEN
+        SELECT INTO user_age age(user_object.dob);
+    END IF;
+
+    -- Grab the closest set circ weight setting.
+    SELECT INTO weights cw.*
+      FROM config.weight_assoc wa
+           JOIN config.circ_matrix_weights cw ON (cw.id = wa.circ_weights)
+           JOIN actor.org_unit_ancestors_distance( context_ou ) d ON (wa.org_unit = d.id)
+      WHERE active
+      ORDER BY d.distance
+      LIMIT 1;
+
+    -- No weights? Bad admin! Defaults to handle that anyway.
+    IF weights.id IS NULL THEN
+        weights.grp                 := 11.0;
+        weights.org_unit            := 10.0;
+        weights.circ_modifier       := 5.0;
+        weights.marc_type           := 4.0;
+        weights.marc_form           := 3.0;
+        weights.marc_vr_format      := 2.0;
+        weights.copy_circ_lib       := 8.0;
+        weights.copy_owning_lib     := 8.0;
+        weights.user_home_ou        := 8.0;
+        weights.ref_flag            := 1.0;
+        weights.juvenile_flag       := 6.0;
+        weights.is_renewal          := 7.0;
+        weights.usr_age_lower_bound := 0.0;
+        weights.usr_age_upper_bound := 0.0;
+    END IF;
+
+    -- Determine the max (expected) depth (+1) of the org tree and max depth of the permisson tree
+    -- If you break your org tree with funky parenting this may be wrong
+    -- Note: This CTE is duplicated in the find_hold_matrix_matchpoint function, and it may be a good idea to split it off to a function
+    -- We use one denominator for all tree-based checks for when permission groups and org units have the same weighting
+    WITH all_distance(distance) AS (
+            SELECT depth AS distance FROM actor.org_unit_type
+        UNION
+                   SELECT distance AS distance FROM permission.grp_ancestors_distance((SELECT id FROM permission.grp_tree WHERE parent IS NULL))
+       )
+    SELECT INTO denominator MAX(distance) + 1 FROM all_distance;
+
+    -- Loop over all the potential matchpoints
+    FOR cur_matchpoint IN
+        SELECT m.*
+          FROM  config.circ_matrix_matchpoint m
+                /*LEFT*/ JOIN permission.grp_ancestors_distance( user_object.profile ) upgad ON m.grp = upgad.id
+                /*LEFT*/ JOIN actor.org_unit_ancestors_distance( context_ou ) ctoua ON m.org_unit = ctoua.id
+                LEFT JOIN actor.org_unit_ancestors_distance( cn_object.owning_lib ) cnoua ON m.copy_owning_lib = cnoua.id
+                LEFT JOIN actor.org_unit_ancestors_distance( item_object.circ_lib ) iooua ON m.copy_circ_lib = iooua.id
+                LEFT JOIN actor.org_unit_ancestors_distance( user_object.home_ou  ) uhoua ON m.user_home_ou = uhoua.id
+          WHERE m.active
+                -- Permission Groups
+             -- AND (m.grp                      IS NULL OR upgad.id IS NOT NULL) -- Optional Permission Group?
+                -- Org Units
+             -- AND (m.org_unit                 IS NULL OR ctoua.id IS NOT NULL) -- Optional Org Unit?
+                AND (m.copy_owning_lib          IS NULL OR cnoua.id IS NOT NULL)
+                AND (m.copy_circ_lib            IS NULL OR iooua.id IS NOT NULL)
+                AND (m.user_home_ou             IS NULL OR uhoua.id IS NOT NULL)
+                -- Circ Type
+                AND (m.is_renewal               IS NULL OR m.is_renewal = renewal)
+                -- Static User Checks
+                AND (m.juvenile_flag            IS NULL OR m.juvenile_flag = user_object.juvenile)
+                AND (m.usr_age_lower_bound      IS NULL OR (user_age IS NOT NULL AND m.usr_age_lower_bound < user_age))
+                AND (m.usr_age_upper_bound      IS NULL OR (user_age IS NOT NULL AND m.usr_age_upper_bound > user_age))
+                -- Static Item Checks
+                AND (m.circ_modifier            IS NULL OR m.circ_modifier = item_object.circ_modifier)
+                AND (m.marc_type                IS NULL OR m.marc_type = COALESCE(item_object.circ_as_type, rec_descriptor.item_type))
+                AND (m.marc_form                IS NULL OR m.marc_form = rec_descriptor.item_form)
+                AND (m.marc_vr_format           IS NULL OR m.marc_vr_format = rec_descriptor.vr_format)
+                AND (m.ref_flag                 IS NULL OR m.ref_flag = item_object.ref)
+          ORDER BY
+                -- Permission Groups
+                CASE WHEN upgad.distance        IS NOT NULL THEN 2^(2*weights.grp - (upgad.distance/denominator)) ELSE 0.0 END +
+                -- Org Units
+                CASE WHEN ctoua.distance        IS NOT NULL THEN 2^(2*weights.org_unit - (ctoua.distance/denominator)) ELSE 0.0 END +
+                CASE WHEN cnoua.distance        IS NOT NULL THEN 2^(2*weights.copy_owning_lib - (cnoua.distance/denominator)) ELSE 0.0 END +
+                CASE WHEN iooua.distance        IS NOT NULL THEN 2^(2*weights.copy_circ_lib - (iooua.distance/denominator)) ELSE 0.0 END +
+                CASE WHEN uhoua.distance        IS NOT NULL THEN 2^(2*weights.user_home_ou - (uhoua.distance/denominator)) ELSE 0.0 END +
+                -- Circ Type                    -- Note: 4^x is equiv to 2^(2*x)
+                CASE WHEN m.is_renewal          IS NOT NULL THEN 4^weights.is_renewal ELSE 0.0 END +
+                -- Static User Checks
+                CASE WHEN m.juvenile_flag       IS NOT NULL THEN 4^weights.juvenile_flag ELSE 0.0 END +
+                CASE WHEN m.usr_age_lower_bound IS NOT NULL THEN 4^weights.usr_age_lower_bound ELSE 0.0 END +
+                CASE WHEN m.usr_age_upper_bound IS NOT NULL THEN 4^weights.usr_age_upper_bound ELSE 0.0 END +
+                -- Static Item Checks
+                CASE WHEN m.circ_modifier       IS NOT NULL THEN 4^weights.circ_modifier ELSE 0.0 END +
+                CASE WHEN m.marc_type           IS NOT NULL THEN 4^weights.marc_type ELSE 0.0 END +
+                CASE WHEN m.marc_form           IS NOT NULL THEN 4^weights.marc_form ELSE 0.0 END +
+                CASE WHEN m.marc_vr_format      IS NOT NULL THEN 4^weights.marc_vr_format ELSE 0.0 END +
+                CASE WHEN m.ref_flag            IS NOT NULL THEN 4^weights.ref_flag ELSE 0.0 END DESC,
+                -- Final sort on id, so that if two rules have the same sorting in the previous sort they have a defined order
+                -- This prevents "we changed the table order by updating a rule, and we started getting different results"
+                m.id LOOP
+
+        -- Record the full matching row list
+        row_list := row_list || cur_matchpoint.id;
+
+        -- No matchpoint yet?
+        IF matchpoint.id IS NULL THEN
+            -- Take the entire matchpoint as a starting point
+            matchpoint := cur_matchpoint;
+            CONTINUE; -- No need to look at this row any more.
+        END IF;
+
+        -- Incomplete matchpoint?
+        IF matchpoint.circulate IS NULL THEN
+            matchpoint.circulate := cur_matchpoint.circulate;
+        END IF;
+        IF matchpoint.duration_rule IS NULL THEN
+            matchpoint.duration_rule := cur_matchpoint.duration_rule;
+        END IF;
+        IF matchpoint.recurring_fine_rule IS NULL THEN
+            matchpoint.recurring_fine_rule := cur_matchpoint.recurring_fine_rule;
+        END IF;
+        IF matchpoint.max_fine_rule IS NULL THEN
+            matchpoint.max_fine_rule := cur_matchpoint.max_fine_rule;
+        END IF;
+        IF matchpoint.hard_due_date IS NULL THEN
+            matchpoint.hard_due_date := cur_matchpoint.hard_due_date;
+        END IF;
+        IF matchpoint.total_copy_hold_ratio IS NULL THEN
+            matchpoint.total_copy_hold_ratio := cur_matchpoint.total_copy_hold_ratio;
+        END IF;
+        IF matchpoint.available_copy_hold_ratio IS NULL THEN
+            matchpoint.available_copy_hold_ratio := cur_matchpoint.available_copy_hold_ratio;
+        END IF;
+        IF matchpoint.renewals IS NULL THEN
+            matchpoint.renewals := cur_matchpoint.renewals;
+        END IF;
+    END LOOP;
+
+    -- Check required fields
+    IF matchpoint.circulate             IS NOT NULL AND
+       matchpoint.duration_rule         IS NOT NULL AND
+       matchpoint.recurring_fine_rule   IS NOT NULL AND
+       matchpoint.max_fine_rule         IS NOT NULL THEN
+        -- All there? We have a completed match.
+        result.success := true;
+    END IF;
+
+    -- Include the assembled matchpoint, even if it isn't complete
+    result.matchpoint := matchpoint;
+
+    -- Include (for debugging) the full list of matching rows
+    result.buildrows := row_list;
+
+    -- Hand the result back to caller
+    RETURN result;
+END;
+$func$ LANGUAGE plpgsql;
+
+-- Helper function - For manual calling, it can be easier to pass in IDs instead of objects
+CREATE OR REPLACE FUNCTION action.find_circ_matrix_matchpoint( context_ou INT, match_item BIGINT, match_user INT, renewal BOOL ) RETURNS SETOF action.found_circ_matrix_matchpoint AS $func$
+DECLARE
+    item_object asset.copy%ROWTYPE;
+    user_object actor.usr%ROWTYPE;
+BEGIN
+    SELECT INTO item_object * FROM asset.copy  WHERE id = match_item;
+    SELECT INTO user_object * FROM actor.usr   WHERE id = match_user;
+
+    RETURN QUERY SELECT * FROM action.find_circ_matrix_matchpoint( context_ou, item_object, user_object, renewal );
+END;
+$func$ LANGUAGE plpgsql;
+
+CREATE OR REPLACE FUNCTION action.item_user_circ_test( circ_ou INT, match_item BIGINT, match_user INT, renewal BOOL ) RETURNS SETOF action.circ_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.circ_matrix_test_result;
+    circ_test               action.found_circ_matrix_matchpoint;
+    circ_matchpoint         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;
+    items_out               INT;
+    context_org_list        INT[];
+    done                    BOOL := FALSE;
+BEGIN
+    -- Assume success unless we hit a failure condition
+    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;
+
+    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 circ_test * FROM action.find_circ_matrix_matchpoint(circ_ou, item_object, user_object, renewal);
+
+    circ_matchpoint             := circ_test.matchpoint;
+    result.matchpoint           := circ_matchpoint.id;
+    result.circulate            := circ_matchpoint.circulate;
+    result.duration_rule        := circ_matchpoint.duration_rule;
+    result.recurring_fine_rule  := circ_matchpoint.recurring_fine_rule;
+    result.max_fine_rule        := circ_matchpoint.max_fine_rule;
+    result.hard_due_date        := circ_matchpoint.hard_due_date;
+    result.renewals             := circ_matchpoint.renewals;
+    result.buildrows            := circ_test.buildrows;
+
+    -- Fail if we couldn't find a matchpoint
+    IF circ_test.success = false THEN
+        result.fail_part := 'no_matchpoint';
+        result.success := FALSE;
+        done := TRUE;
+        RETURN NEXT result;
+        RETURN; -- All tests after this point require a matchpoint. No sense in running on an incomplete or missing one.
+    END IF;
+
+    -- Apparently....use the circ matchpoint org unit to determine what org units are valid.
+    SELECT INTO context_org_list ARRAY_ACCUM(id) FROM actor.org_unit_full_path( circ_matchpoint.org_unit );
+
+    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 unnest(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 test is set to hard non-circulating
+    IF circ_matchpoint.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_matchpoint.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_matchpoint.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_matchpoint.available_copy_hold_ratio IS NOT NULL THEN
+        IF hold_ratio.hold_count IS NULL THEN
+            SELECT INTO hold_ratio * FROM action.copy_related_hold_stats(match_item);
+        END IF;
+        IF hold_ratio.available_copy_ratio IS NOT NULL AND hold_ratio.available_copy_ratio < circ_matchpoint.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;
+
+    -- 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_matchpoint.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 unnest(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 OR REPLACE FUNCTION action.item_user_circ_test( INT, BIGINT, INT ) RETURNS SETOF action.circ_matrix_test_result AS $func$
+    SELECT * FROM action.item_user_circ_test( $1, $2, $3, FALSE );
+$func$ LANGUAGE SQL;
+
+CREATE OR REPLACE FUNCTION action.item_user_renew_test( INT, BIGINT, INT ) RETURNS SETOF action.circ_matrix_test_result AS $func$
+    SELECT * FROM action.item_user_circ_test( $1, $2, $3, TRUE );
+$func$ LANGUAGE SQL;
+
+COMMIT;
diff --git a/Open-ILS/src/sql/Pg/upgrade/0488.function.maintain_901_tcn.sql b/Open-ILS/src/sql/Pg/upgrade/0488.function.maintain_901_tcn.sql
new file mode 100644 (file)
index 0000000..8301db8
--- /dev/null
@@ -0,0 +1,68 @@
+BEGIN;
+
+INSERT INTO config.upgrade_log (version) VALUES ('0488'); -- dbs
+
+CREATE OR REPLACE FUNCTION maintain_901 () RETURNS TRIGGER AS $func$
+DECLARE
+    use_id_for_tcn BOOLEAN;
+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
+        -- Set TCN value to record ID?
+        SELECT enabled FROM config.global_flag INTO use_id_for_tcn
+            WHERE name = 'cat.bib.use_id_for_tcn';
+
+        IF use_id_for_tcn = 't' THEN
+            NEW.tcn_value := NEW.id;
+        END IF;
+
+        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;
index dff54ee..5941388 100644 (file)
@@ -112,9 +112,15 @@ if(!dojo._hasResource["openils.BibTemplate"]) {
                                     try { (new Function( 'BT', 'slotXML', 'slot', unescape(cb.innerHTML) ))(BT,bib,slot) } catch (e) {/*meh*/}
                                 });
 
+                                var query = slot.getAttribute('query');
+                                var xml_root = bib.documentElement || bib;
+
+                                // Opera (as of 11.01) fails with quotes in queries
+                                if (dojo.isOpera) query = query.replace(/"|'/g, '');
+
                                 var item_list = dojo.query(
-                                    slot.getAttribute('query'),
-                                    bib
+                                    query,
+                                    xml_root // Make Opera work by querying from the root element
                                 );
 
                                 if (item_limit) {
index ba05bc1..1db121a 100644 (file)
@@ -142,6 +142,14 @@ if(!dojo._hasResource['openils.widget.AutoFieldWidget']) {
          */
         getDisplayString : function() {
             var value = this.widgetValue;
+            if(this.inherits) {
+                switch(value) {
+                    case null :
+                    case undefined :
+                    case 'unset' :
+                        return openils.widget.AutoFieldWidget.localeStrings.INHERITED;
+                }
+            }
             switch(this.idlField.datatype) {
                 case 'bool':
                     switch(value) {
@@ -272,13 +280,13 @@ if(!dojo._hasResource['openils.widget.AutoFieldWidget']) {
                         break;
 
                     case 'bool':
-                        if(this.ternary) {
+                        if(this.ternary || this.inherits) {
                             dojo.require('dijit.form.FilteringSelect');
                             var store = new dojo.data.ItemFileReadStore({
                                 data:{
                                     identifier : 'value',
                                     items:[
-                                        {label : openils.widget.AutoFieldWidget.localeStrings.UNSET, value : 'unset'},
+                                        {label : (this.inherits ? openils.widget.AutoFieldWidget.localeStrings.INHERITED : openils.widget.AutoFieldWidget.localeStrings.UNSET), value : 'unset'},
                                         {label : openils.widget.AutoFieldWidget.localeStrings.TRUE, value : 'true'},
                                         {label : openils.widget.AutoFieldWidget.localeStrings.FALSE, value : 'false'}
                                     ]
index 94f24bf..3e99b28 100644 (file)
@@ -611,15 +611,17 @@ if(!dojo._hasResource['openils.widget.AutoGrid']) {
 
     openils.widget.AutoGrid.defaultGetter = function(rowIndex, item) {
         if(!item) return '';
+        if(!this.grid.overrideWidgetArgs[this.field])
+            this.grid.overrideWidgetArgs[this.field] = {};
         var val = this.grid.store.getValue(item, this.field);
-        var autoWidget = new openils.widget.AutoFieldWidget({
+        var autoWidget = new openils.widget.AutoFieldWidget(dojo.mixin({
             fmClass: this.grid.fmClass,
             fmField: this.field,
             widgetValue : val,
             readOnly : true,
             forceSync : true, // prevents many simultaneous requests for the same data
             suppressLinkedFields : this.grid.suppressLinkedFields
-        });
+        },this.grid.overrideWidgetArgs[this.field]));
 
         autoWidget.build();
 
index e3262de..1fd41ad 100644 (file)
@@ -77,6 +77,20 @@ if(!dojo._hasResource['openils.widget.EditPane']) {
                     if(field.name == this.fmIDL.pkey && this.mode == 'create' && this.fmIDL.pkey_sequence)
                         continue; /* don't show auto-generated fields on create */
 
+                    if(!this.overrideWidgetArgs[field.name])
+                        this.overrideWidgetArgs[field.name] = {};
+
+                    if(this.overrideWidgetArgs[field.name].hrbefore && this.paneStackCount <= 1) {
+                        var hrTr = document.createElement('tr');
+                        var hrTd = document.createElement('td');
+                        var hr = document.createElement('hr');
+                        hrTd.colSpan = 2;
+                        dojo.addClass(hrTd, 'openils-widget-editpane-hr-cell');
+                        hrTd.appendChild(hr);
+                        hrTr.appendChild(hrTd);
+                        tbody.appendChild(hrTr);
+                    }
+
                     if((idx++ % this.paneStackCount) == 0 || !currentRow) {
                         // time to start a new row
                         currentRow = document.createElement('tr');
@@ -107,9 +121,6 @@ if(!dojo._hasResource['openils.widget.EditPane']) {
                     currentRow.appendChild(valTd);
                     //dojo.addClass(docTd, 'oils-fm-edit-pane-help');
 
-                    if(!this.overrideWidgetArgs[field.name])
-                        this.overrideWidgetArgs[field.name] = {};
-
                     var args = dojo.mixin(
                         {   // defaults
                             idlField : field, 
index 4d19f34..bc77c06 100644 (file)
@@ -1,5 +1,6 @@
 {
     "TRUE" : "True",
     "FALSE" : "False",
-    "UNSET" : "Unset"
+    "UNSET" : "Unset",
+    "INHERITED" : "Inherited"
 }
index aeeacef..bc4bb97 100644 (file)
@@ -373,6 +373,11 @@ SelfCheckManager.prototype.handleAlert = function(message, shouldPopup, sound) {
 
     dojo.byId('oils-selfck-status-div').innerHTML = message;
 
+    if(shouldPopup)
+        openils.Util.addCSSClass( dojo.byId('oils-selfck-status-div'), 'checkout_failure' );
+    else
+        openils.Util.removeCSSClass( dojo.byId('oils-selfck-status-div'), 'checkout_failure' );
+
     if(shouldPopup && this.orgSettings[SET_ALERT_POPUP]) 
         alert(message);
 
index 7fdae7b..f5d5b3a 100644 (file)
@@ -12,7 +12,18 @@ var circModEntryCache = {};
 var matchPoint;
 
 function load(){
+    cmGrid.overrideWidgetArgs.grp = {hrbefore : true};
     cmGrid.overrideWidgetArgs.is_renewal = {ternary : true};
+    cmGrid.overrideWidgetArgs.ref_flag = {ternary : true};
+    cmGrid.overrideWidgetArgs.juvenile_flag = {ternary : true};
+    cmGrid.overrideWidgetArgs.circulate = {inherits : true, hrbefore : true};
+    cmGrid.overrideWidgetArgs.duration_rule = {inherits : true};
+    cmGrid.overrideWidgetArgs.recurring_fine_rule = {inherits : true};
+    cmGrid.overrideWidgetArgs.max_fine_rule = {inherits : true};
+    cmGrid.overrideWidgetArgs.available_copy_hold_ratio = {inherits : true};
+    cmGrid.overrideWidgetArgs.total_copy_hold_ratio = {inherits : true};
+    cmGrid.overrideWidgetArgs.renewals = {inherits : true};
+    cmGrid.overrideWidgetArgs.hard_due_date = {inherits : true};
     cmGrid.loadAll({order_by:{ccmm:'circ_modifier'}});
     cmGrid.onEditPane = buildEditPaneAdditions;
     circModEditor = dojo.byId('circ-mod-editor').parentNode.removeChild(dojo.byId('circ-mod-editor'));
index e585137..dda4906 100644 (file)
@@ -555,7 +555,7 @@ function grabUser(ses, force) {
                        return G.user;
 
        /* first make sure the session is valid */
-       var request = new Request(FETCH_SESSION, ses, 1 );
+       var request = new Request(FETCH_SESSION, ses);
        request.request.alertEvent = false;
        request.send(true);
        var user = request.result();
@@ -569,7 +569,7 @@ function grabUser(ses, force) {
                 function(success, authtoken) { 
                     if(success) {
                         ses = authtoken;
-                        var request = new Request(FETCH_SESSION, ses, 1);
+                        var request = new Request(FETCH_SESSION, ses);
                         request.request.alertEvent = false;
                         request.send(true);
                         user = request.result();
index 41068c2..3325a26 100644 (file)
@@ -35,7 +35,7 @@
             <button onclick='dojo.cookie("noGCF", "true", {path:"/", expires: 365}); hideMe($("gcfPrompt"));'>&common.googlechromeframe.dontask;</button>
         </div>
     </center>
-    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/chrome-frame/1/CFInstall.min.js"></script>
+    <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/chrome-frame/1/CFInstall.min.js"></script>
     <script><![CDATA[ 
         CFInstall.check({
             preventPrompt: true,
index d2f031d..9a37c8b 100644 (file)
@@ -30,7 +30,7 @@
             <button onclick='dojo.cookie("noGCF", "true", {path:"/", expires: 365}); hideMe($("gcfPrompt"));'>&common.googlechromeframe.dontask;</button>
         </div>
     </center>
-    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/chrome-frame/1/CFInstall.min.js"></script>
+    <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/chrome-frame/1/CFInstall.min.js"></script>
     <script><![CDATA[ 
         CFInstall.check({
             preventPrompt: true,
index 6054078..c09012f 100644 (file)
@@ -9,7 +9,7 @@
     <table  jsId="cmGrid"
             style="height: 600px;"
             dojoType="openils.widget.AutoGrid"
-            fieldOrder="['org_unit', 'active', 'grp', 'circ_modifier', 'marc_type', 'marc_form', 'marc_vr_format']"
+            fieldOrder="['id', 'active', 'grp', 'org_unit', 'copy_circ_lib', 'copy_owning_lib', 'user_home_ou', 'is_renewal', 'juvenile_flag', 'circ_modifier', 'marc_type', 'marc_form', 'marc_vr_format', 'ref_flag', 'usr_age_lower_bound', 'usr_age_upper_bound', 'circulate', 'duration_rule', 'renewals', 'hard_due_date', 'recurring_fine_rule', 'max_fine_rule', 'available_copy_hold_ratio', 'total_copy_hold_ratio', 'script_test']"
             defaultCellWidth='"auto"'
             query="{id: '*'}"
             fmClass='ccmm'
 <div class='hidden'><div dojoType='openils.widget.ProgressDialog' jsId='progressDialog'/></div>
 
 <script type="text/javascript">
-    function format_hard_due_date(name) {
-        return "<a href='" + oilsBasePath +
-            "/conify/global/config/hard_due_date?name=" +
-            encodeURIComponent(name) + "'>" + name + "</a>";
+    function format_hard_due_date(name, id) {
+        var item=this.grid.getItem(id);
+        if(!item) return name;
+        switch (this.grid.store.getValue(this.grid.getItem(id), 'hard_due_date')) {
+            case null :
+            case undefined :
+            case 'unset' :
+                return name;
+            default:
+                return "<a href='" + oilsBasePath +
+                    "/conify/global/config/hard_due_date?name=" +
+                    encodeURIComponent(name) + "'>" + name + "</a>";
+        }
     }
 </script>
 [% END %]