Allow more granular overrides
authorThomas Berezansky <tsbere@mvlc.org>
Thu, 24 May 2012 15:45:36 +0000 (11:45 -0400)
committerMike Rylander <mrylander@gmail.com>
Fri, 25 May 2012 15:15:01 +0000 (11:15 -0400)
This adds a new parameter to backend override functions. In most cases the
system will act like a hash with all set to 1 was passed in when nothing was
passed in by the caller.

The new parameter should be a hash containing zero or more of the following
options:

all - If true (1) override all events
events - Should be an array of event textcodes to override

For hold placement the "all" option is ignored for possibility checks, but
is checked for other events like HOLD_EXISTS.

Also included for hold placement is to always run possibility checks for
the test and create batch method.

Overall, the default is to act like things did previously.

Signed-off-by: Thomas Berezansky <tsbere@mvlc.org>
Signed-off-by: Mike Rylander <mrylander@gmail.com>

Open-ILS/src/perlmods/lib/OpenILS/Application/Actor.pm
Open-ILS/src/perlmods/lib/OpenILS/Application/Cat.pm
Open-ILS/src/perlmods/lib/OpenILS/Application/Cat/AssetCommon.pm
Open-ILS/src/perlmods/lib/OpenILS/Application/Cat/BibCommon.pm
Open-ILS/src/perlmods/lib/OpenILS/Application/Circ.pm
Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/Circulate.pm
Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/Holds.pm
Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/Survey.pm

index 4ba9ad5..77277e4 100644 (file)
@@ -2396,16 +2396,17 @@ __PACKAGE__->register_method(
 );
 
 sub register_workstation {
-       my( $self, $conn, $authtoken, $name, $owner ) = @_;
+       my( $self, $conn, $authtoken, $name, $owner, $oargs ) = @_;
 
        my $e = new_editor(authtoken=>$authtoken, xact=>1);
        return $e->die_event unless $e->checkauth;
        return $e->die_event unless $e->allowed('REGISTER_WORKSTATION', $owner);
        my $existing = $e->search_actor_workstation({name => $name})->[0];
+    $oargs = { all => 1 } unless defined $oargs;
 
        if( $existing ) {
 
-               if( $self->api_name =~ /override/o ) {
+               if( $self->api_name =~ /override/o && ($oargs->{all} || grep { $_ eq 'WORKSTATION_NAME_EXISTS' } @{$oargs->{events}}) ) {
             # workstation with the given name exists.  
 
             if($owner ne $existing->owning_lib) {
@@ -3639,9 +3640,10 @@ __PACKAGE__->register_method (
 );
 
 sub really_delete_user {
-    my($self, $conn, $auth, $user_id, $dest_user_id) = @_;
+    my($self, $conn, $auth, $user_id, $dest_user_id, $oargs) = @_;
     my $e = new_editor(authtoken => $auth, xact => 1);
     return $e->die_event unless $e->checkauth;
+    $oargs = { all => 1 } unless defined $oargs;
 
     # Find all unclosed billings for for user $user_id, thereby, also checking for open circs
     my $open_bills = $e->json_query({
@@ -3658,7 +3660,7 @@ sub really_delete_user {
     # No deleting patrons with open billings or checked out copies, unless perm-enabled override
     if (@$open_bills) {
         return $e->die_event(OpenILS::Event->new('ACTOR_USER_DELETE_OPEN_XACTS'))
-        unless $self->api_name =~ /override/o
+        unless $self->api_name =~ /override/o && ($oargs->{all} || grep { $_ eq 'ACTOR_USER_DELETE_OPEN_XACTS' } @{$oargs->{events}})
         && $e->allowed('ACTOR_USER_DELETE_OPEN_XACTS.override', $user->home_ou);
     }
     # No deleting yourself - UI is supposed to stop you first, though.
index e1d2c82..a442aff 100644 (file)
@@ -106,9 +106,10 @@ __PACKAGE__->register_method(
 );
 
 sub create_record_xml {
-    my( $self, $client, $login, $xml, $source ) = @_;
+    my( $self, $client, $login, $xml, $source, $oargs ) = @_;
 
     my $override = 1 if $self->api_name =~ /override/;
+    $oargs = { all => 1 } unless defined $oargs;
 
     my( $user_obj, $evt ) = $U->checksesperm($login, 'CREATE_MARC');
     return $evt if $evt;
@@ -120,7 +121,7 @@ sub create_record_xml {
     $meth = $self->method_lookup(
         "open-ils.cat.biblio.record.xml.import.override") if $override;
 
-    my ($s) = $meth->run($login, $xml, $source);
+    my ($s) = $meth->run($login, $xml, $source, $oargs);
     return $s;
 }
 
@@ -155,16 +156,20 @@ __PACKAGE__->register_method(
 );
 
 sub biblio_record_replace_marc  {
-    my( $self, $conn, $auth, $recid, $newxml, $source ) = @_;
+    my( $self, $conn, $auth, $recid, $newxml, $source, $oargs ) = @_;
     my $e = new_editor(authtoken=>$auth, xact=>1);
     return $e->die_event unless $e->checkauth;
     return $e->die_event unless $e->allowed('CREATE_MARC', $e->requestor->ws_ou);
 
     my $fix_tcn = $self->api_name =~ /replace/o;
-    my $override = $self->api_name =~ /override/o;
+    if($self->api_name =~ /override/o) {
+        $oargs = { all => 1 } unless defined $oargs;
+    } else {
+        $oargs = {};
+    }
 
     my $res = OpenILS::Application::Cat::BibCommon->biblio_record_replace_marc(
-        $e, $recid, $newxml, $source, $fix_tcn, $override);
+        $e, $recid, $newxml, $source, $fix_tcn, $oargs);
 
     $e->commit unless $U->event_code($res);
 
@@ -404,14 +409,18 @@ __PACKAGE__->register_method(
 
 
 sub biblio_record_xml_import {
-    my( $self, $client, $authtoken, $xml, $source, $auto_tcn) = @_;
+    my( $self, $client, $authtoken, $xml, $source, $auto_tcn, $oargs) = @_;
     my $e = new_editor(xact=>1, authtoken=>$authtoken);
     return $e->die_event unless $e->checkauth;
     return $e->die_event unless $e->allowed('IMPORT_MARC', $e->requestor->ws_ou);
 
-    my $override = $self->api_name =~ /override/;
+    if ($self->api_name =~ /override/) {
+        $oargs = { all => 1 } unless defined $oargs;
+    } else {
+        $oargs = {};
+    }
     my $record = OpenILS::Application::Cat::BibCommon->biblio_record_xml_import(
-        $e, $xml, $source, $auto_tcn, $override);
+        $e, $xml, $source, $auto_tcn, $oargs);
 
     return $record if $U->event_code($record);
 
@@ -718,15 +727,19 @@ __PACKAGE__->register_method(
 
 
 sub fleshed_copy_update {
-    my( $self, $conn, $auth, $copies, $delete_stats ) = @_;
+    my( $self, $conn, $auth, $copies, $delete_stats, $oargs ) = @_;
     return 1 unless ref $copies;
     my( $reqr, $evt ) = $U->checkses($auth);
     return $evt if $evt;
     my $editor = new_editor(requestor => $reqr, xact => 1);
-    my $override = $self->api_name =~ /override/;
+    if ($self->api_name =~ /override/) {
+        $oargs = { all => 1 } unless defined $oargs;
+    } else {
+        $oargs = {};
+    }
     my $retarget_holds = [];
     $evt = OpenILS::Application::Cat::AssetCommon->update_fleshed_copies(
-        $editor, $override, undef, $copies, $delete_stats, $retarget_holds, undef);
+        $editor, $oargs, undef, $copies, $delete_stats, $retarget_holds, undef);
 
     if( $evt ) { 
         $logger->info("fleshed copy update failed with event: ".OpenSRF::Utils::JSON->perl2JSON($evt));
@@ -845,12 +858,16 @@ __PACKAGE__->register_method(
     api_name => "open-ils.cat.asset.volume.fleshed.batch.update.override",);
 
 sub fleshed_volume_update {
-    my( $self, $conn, $auth, $volumes, $delete_stats, $options ) = @_;
+    my( $self, $conn, $auth, $volumes, $delete_stats, $options, $oargs ) = @_;
     my( $reqr, $evt ) = $U->checkses($auth);
     return $evt if $evt;
     $options ||= {};
 
-    my $override = ($self->api_name =~ /override/);
+    if ($self->api_name =~ /override/) {
+        $oargs = { all => 1 } unless defined $oargs;
+    } else {
+        $oargs = {};
+    }
     my $editor = new_editor( requestor => $reqr, xact => 1 );
     my $retarget_holds = [];
     my $auto_merge_vols = $options->{auto_merge_vols};
@@ -873,7 +890,7 @@ sub fleshed_volume_update {
             return $editor->die_event unless
                 $editor->allowed('UPDATE_VOLUME', $vol->owning_lib);
 
-            if(my $evt = $assetcom->delete_volume($editor, $vol, $override, $$options{force_delete_copies})) {
+            if(my $evt = $assetcom->delete_volume($editor, $vol, $oargs, $$options{force_delete_copies})) {
                 $editor->rollback;
                 return $evt;
             }
@@ -883,12 +900,12 @@ sub fleshed_volume_update {
 
         } elsif( $vol->isnew ) {
             $logger->info("vol-update: creating volume");
-            $evt = $assetcom->create_volume( $override, $editor, $vol );
+            $evt = $assetcom->create_volume( $oargs, $editor, $vol );
             return $evt if $evt;
 
         } elsif( $vol->ischanged ) {
             $logger->info("vol-update: update volume");
-            my $resp = update_volume($vol, $editor, ($override or $auto_merge_vols));
+            my $resp = update_volume($vol, $editor, ($oargs->{all} or grep { $_ eq 'VOLUME_LABEL_EXISTS' } @{$oargs->{events}} or $auto_merge_vols));
             return $resp->{evt} if $resp->{evt};
             $vol = $resp->{merge_vol};
         }
@@ -897,7 +914,7 @@ sub fleshed_volume_update {
         if( $copies and @$copies and !$vol->isdeleted ) {
             $_->call_number($vol->id) for @$copies;
             $evt = $assetcom->update_fleshed_copies(
-                $editor, $override, $vol, $copies, $delete_stats, $retarget_holds, undef);
+                $editor, $oargs, $vol, $copies, $delete_stats, $retarget_holds, undef);
             return $evt if $evt;
         }
     }
@@ -982,7 +999,7 @@ __PACKAGE__->register_method (
 
 
 sub batch_volume_transfer {
-    my( $self, $conn, $auth, $args ) = @_;
+    my( $self, $conn, $auth, $args, $oargs ) = @_;
 
     my $evt;
     my $rec     = $$args{docid};
@@ -990,6 +1007,7 @@ sub batch_volume_transfer {
     my $vol_ids = $$args{volumes};
 
     my $override = 1 if $self->api_name =~ /override/;
+    $oargs = { all => 1 } unless defined $oargs;
 
     $logger->info("merge: transferring volumes to lib=$o_lib and record=$rec");
 
@@ -1026,7 +1044,7 @@ sub batch_volume_transfer {
         # for each volume, see if there are any copies that have a 
         # remote circ_lib (circ_lib != vol->owning_lib and != $o_lib ).  
         # if so, warn them
-        unless( $override ) {
+        unless( $override && ($oargs->{all} || grep { $_ eq 'COPY_REMOTE_CIRC_LIB' } @{$oargs->{events}}) ) {
             for my $v (@all) {
 
                 $logger->debug("merge: searching for copies with remote circ_lib for volume ".$v->id);
@@ -1157,9 +1175,10 @@ __PACKAGE__->register_method(
 );
 
 sub create_serial_record_xml {
-    my( $self, $client, $login, $source, $owning_lib, $record_id, $xml ) = @_;
+    my( $self, $client, $login, $source, $owning_lib, $record_id, $xml, $oargs ) = @_;
 
     my $override = 1 if $self->api_name =~ /override/; # not currently used
+    $oargs = { all => 1 } unless defined $oargs; # Not currently used, but here for consistency.
 
     my $e = new_editor(xact=>1, authtoken=>$login);
     return $e->die_event unless $e->checkauth;
index ff75099..c87eb28 100644 (file)
@@ -195,6 +195,9 @@ sub update_copy_parts {
 sub update_copy {
        my($class, $editor, $override, $vol, $copy, $retarget_holds, $force_delete_empty_bib) = @_;
 
+    $override = { all => 1 } if($override && !ref $override);
+    $override = { all => 0 } if(!ref $override);
+
        my $evt;
        my $org = (ref $copy->circ_lib) ? $copy->circ_lib->id : $copy->circ_lib;
        return $evt if ( $evt = $class->org_cannot_have_vols($editor, $org) );
@@ -255,6 +258,9 @@ sub check_hold_retarget {
 sub update_fleshed_copies {
        my($class, $editor, $override, $vol, $copies, $delete_stats, $retarget_holds, $force_delete_empty_bib) = @_;
 
+    $override = { all => 1 } if($override && !ref $override);
+    $override = { all => 0 } if(!ref $override);
+
        my $evt;
        my $fetchvol = ($vol) ? 0 : 1;
 
@@ -322,9 +328,12 @@ sub delete_copy {
        return $editor->event unless
                $editor->allowed('DELETE_COPY', $class->copy_perm_org($vol, $copy));
 
+    $override = { all => 1 } if($override && !ref $override);
+    $override = { all => 0 } if(!ref $override);
+
        my $stat = $U->copy_status($copy->status);
        if ($U->is_true($stat->restrict_copy_delete)) {
-               if ($override) {
+               if ($override->{all} || grep { $_ eq 'COPY_DELETE_WARNING' } @{$override->{events}}) {
                        return $editor->event unless $editor->allowed('COPY_DELETE_WARNING.override', $class->copy_perm_org($vol, $copy))
                } else {
                        return OpenILS::Event->new('COPY_DELETE_WARNING', payload => $copy->id )
@@ -421,6 +430,9 @@ sub create_volume {
 
        return $evt if ( $evt = $class->org_cannot_have_vols($editor, $vol->owning_lib) );
 
+    $override = { all => 1 } if($override && !ref $override);
+    $override = { all => 0 } if(!ref $override);
+
    # see if the record this volume references is marked as deleted
    my $rec = $editor->retrieve_biblio_record_entry($vol->record)
       or return $editor->die_event;
@@ -441,7 +453,7 @@ sub create_volume {
        my $label = undef;
        if(@$vols) {
       # we've found an exising volume
-               if($override) { 
+               if($override->{all} || grep { $_ eq 'VOLUME_LABEL_EXISTS' } @{$override->{events}}) {
                        $label = $vol->label;
                } else {
                        return OpenILS::Event->new(
@@ -534,6 +546,9 @@ sub create_copy_note {
 sub remove_empty_objects {
        my($class, $editor, $override, $vol, $force_delete_empty_bib) = @_; 
 
+    $override = { all => 1 } if($override && !ref $override);
+    $override = { all => 0 } if(!ref $override);
+
     my $koe = $U->ou_ancestor_setting_value(
         $editor->requestor->ws_ou, 'cat.bib.keep_on_empty', $editor);
     my $aoe =  $U->ou_ancestor_setting_value(
@@ -548,7 +563,7 @@ sub remove_empty_objects {
         }
 
         return OpenILS::Event->new('TITLE_LAST_COPY', payload => $vol->record ) 
-            if $aoe and not $override and not $force_delete_empty_bib;
+            if $aoe and not ($override->{all} || grep { $_ eq 'TITLE_LAST_COPY' } @{$override->{events}}) and not $force_delete_empty_bib;
 
         unless($koe and not $force_delete_empty_bib) {
             # delete the bib record if the keep-on-empty setting is not set (and we're not otherwise forcing things, say through acq settings)
index 6a776d8..65c3e0f 100644 (file)
@@ -38,6 +38,9 @@ sub fetch_bib_sources {
 sub biblio_record_replace_marc  {
        my($class, $e, $recid, $newxml, $source, $fixtcn, $override) = @_;
 
+    $override = { all => 1 } if($override && !ref $override);
+    $override = { all => 0 } if(!ref $override);
+
        my $rec = $e->retrieve_biblio_record_entry($recid)
                or return $e->die_event;
 
@@ -48,7 +51,7 @@ sub biblio_record_replace_marc  {
 
        my( $tcn, $tsource, $marcdoc, $evt);
 
-    if($fixtcn or $override) {
+    if($fixtcn or $override->{all} or $override->{events}) {
 
            ($tcn, $tsource, $marcdoc, $evt) = 
                    _find_tcn_info($e, $newxml, $override, $recid);
@@ -76,6 +79,9 @@ sub biblio_record_replace_marc  {
 sub biblio_record_xml_import {
        my($class, $e, $xml, $source, $auto_tcn, $override) = @_;
 
+    $override = { all => 1 } if($override && !ref $override);
+    $override = { all => 0 } if(!ref $override);
+
        my( $evt, $tcn, $tcn_source, $marcdoc );
 
     my $use_id = $e->retrieve_config_global_flag('cat.bib.use_id_for_tcn');
@@ -171,6 +177,9 @@ sub _find_tcn_info {
        my $override    = shift;
        my $existing_rec        = shift || 0;
 
+    $override = { all => 1 } if($override && !ref $override);
+    $override = { all => 0 } if(!ref $override);
+
        # parse the XML
        my $marcxml = __make_marc_doc($xml);
 
@@ -187,7 +196,7 @@ sub _find_tcn_info {
                $tcn = find_free_tcn( $marcxml, $editor, $existing_rec );
 
                # if we're overriding, try to find a different TCN to use
-               if( $override ) {
+               if( $override->{all} || grep { $_ eq 'TCN_EXISTS' } @{$override->{events}} ) {
 
          # XXX Create ALLOW_ALT_TCN permission check support 
 
index fba805a..5c2a754 100644 (file)
@@ -400,11 +400,13 @@ __PACKAGE__->register_method(
 );
 
 sub set_circ_claims_returned {
-    my( $self, $conn, $auth, $args ) = @_;
+    my( $self, $conn, $auth, $args, $oargs ) = @_;
 
     my $e = new_editor(authtoken=>$auth, xact=>1);
     return $e->die_event unless $e->checkauth;
 
+    $oargs = { all => 1 } unless defined $oargs;
+
     my $barcode = $$args{barcode};
     my $backdate = $$args{backdate};
 
@@ -429,7 +431,7 @@ sub set_circ_claims_returned {
     # 0 means all attempts require an override
     if(defined $max_count and $patron->claims_returned_count >= $max_count) {
 
-        if($self->api_name =~ /override/) {
+        if($self->api_name =~ /override/ && ($oargs->{all} || grep { $_ eq 'PATRON_EXCEEDS_CLAIMS_RETURN_COUNT' } @{$oargs->{events}})) {
 
             # see if we're allowed to override
             return $e->die_event unless 
@@ -1393,7 +1395,7 @@ sub mark_item_missing_pieces {
             }
         }
 
-        my ($res) = $self->method_lookup('open-ils.circ.checkout.full.override')->run($e->authtoken,$co_params);
+        my ($res) = $self->method_lookup('open-ils.circ.checkout.full.override')->run($e->authtoken,$co_params,{ all => 1 });
         if (ref $res ne 'ARRAY') { $res = [ $res ]; }
         if ( $res->[0]->{textcode} eq 'SUCCESS' ) {
             $logger->info('open-ils.circ.mark_item_missing_pieces: successful checkout');
index 5bdb1c3..88f7a73 100644 (file)
@@ -191,12 +191,13 @@ __PACKAGE__->register_method(
 
 
 sub run_method {
-    my( $self, $conn, $auth, $args ) = @_;
+    my( $self, $conn, $auth, $args, $oargs ) = @_;
     translate_legacy_args($args);
+    $oargs = { all => 1 } unless defined $oargs;
     my $api = $self->api_name;
 
     my $circulator = 
-        OpenILS::Application::Circ::Circulator->new($auth, %$args);
+        OpenILS::Application::Circ::Circulator->new($auth, %$args, $oargs);
 
     return circ_events($circulator) if $circulator->bail_out;
 
@@ -540,6 +541,7 @@ my @AUTOLOAD_FIELDS = qw/
     hold_as_transit
     fake_hold_dest
     limit_groups
+    override_args
 /;
 
 
@@ -569,12 +571,13 @@ sub AUTOLOAD {
 
 
 sub new {
-    my( $class, $auth, %args ) = @_;
+    my( $class, $auth, %args, $oargs ) = @_;
     $class = ref($class) || $class;
     my $self = bless( {}, $class );
 
     $self->events([]);
     $self->editor(new_editor(xact => 1, authtoken => $auth));
+    $self->override_args($oargs);
 
     unless( $self->editor->checkauth ) {
         $self->bail_on_events($self->editor->event);
@@ -1367,6 +1370,7 @@ sub override_events {
     my $self = shift;
     my @events = @{$self->events};
     return unless @events;
+    my $oargs = $self->override_args;
 
     if(!$self->override) {
         return $self->bail_out(1) 
@@ -1375,14 +1379,18 @@ sub override_events {
 
     $self->events([]);
     
-   for my $e (@events) {
-      my $tc = $e->{textcode};
-      next if $tc eq 'SUCCESS';
-      my $ov = "$tc.override";
-      $logger->info("circulator: attempting to override event: $ov");
+    for my $e (@events) {
+        my $tc = $e->{textcode};
+        next if $tc eq 'SUCCESS';
+        if($oargs->{all} || grep { $_ eq $tc } @{$oargs->{events}}) {
+            my $ov = "$tc.override";
+            $logger->info("circulator: attempting to override event: $ov");
 
-        return $self->bail_on_events($self->editor->event)
-            unless( $self->editor->allowed($ov) );
+            return $self->bail_on_events($self->editor->event)
+                unless( $self->editor->allowed($ov) );
+        } else {
+            return $self->bail_out(1);
+        }
    }
 }
     
@@ -1408,7 +1416,7 @@ sub handle_claims_returned {
     my $evt;
 
     # - If the caller has set the override flag, we will check the item in
-    if($self->override) {
+    if($self->override && ($self->override_args->{all} || grep { $_ eq 'CIRC_CLAIMS_RETURNED' } @{$self->override_args->{events}}) ) {
 
         $CR->checkin_time('now');   
         $CR->checkin_scan_time('now');   
index 9fddeeb..23f19a9 100644 (file)
@@ -67,9 +67,10 @@ __PACKAGE__->register_method(
 
 
 sub test_and_create_hold_batch {
-       my( $self, $conn, $auth, $params, $target_list ) = @_;
+       my( $self, $conn, $auth, $params, $target_list, $oargs ) = @_;
 
        my $override = 1 if $self->api_name =~ /override/;
+    $oargs = { all => 1 } unless defined $oargs;
 
        my $e = new_editor(authtoken=>$auth);
        return $e->die_event unless $e->checkauth;
@@ -89,17 +90,15 @@ sub test_and_create_hold_batch {
     foreach (@$target_list) {
         $$params{$target_field} = $_;
         my $res;
-        if (! $override) {        
-            ($res) = $self->method_lookup(
-                'open-ils.circ.title_hold.is_possible')->run($auth, $params);
-        }
-        if ($override || $res->{'success'} == 1) {
+        ($res) = $self->method_lookup(
+            'open-ils.circ.title_hold.is_possible')->run($auth, $params, $override ? $oargs : {});
+        if ($res->{'success'} == 1) {
             my $ahr = construct_hold_request_object($params);
             my ($res2) = $self->method_lookup(
                 $override
                 ? 'open-ils.circ.holds.create.override'
                 : 'open-ils.circ.holds.create'
-            )->run($auth, $ahr);
+            )->run($auth, $ahr, $oargs);
             $res2 = {
                 'target' => $$params{$target_field},
                 'result' => $res2
@@ -166,10 +165,10 @@ __PACKAGE__->register_method(
 
 
 sub create_hold_batch {
-       my( $self, $conn, $auth, $hold_list ) = @_;
+       my( $self, $conn, $auth, $hold_list, $oargs ) = @_;
     (my $method = $self->api_name) =~ s/\.batch//og;
     foreach (@$hold_list) {
-        my ($res) = $self->method_lookup($method)->run($auth, $_);
+        my ($res) = $self->method_lookup($method)->run($auth, $_, $oargs);
         $conn->respond($res);
     }
     return undef;
@@ -223,12 +222,13 @@ __PACKAGE__->register_method(
 );
 
 sub create_hold {
-       my( $self, $conn, $auth, $hold ) = @_;
+       my( $self, $conn, $auth, $hold, $oargs ) = @_;
     return -1 unless $hold;
        my $e = new_editor(authtoken=>$auth, xact=>1);
        return $e->die_event unless $e->checkauth;
 
        my $override = 1 if $self->api_name =~ /override/;
+    $oargs = { all => 1 } unless defined $oargs;
 
     my @events;
 
@@ -306,7 +306,12 @@ sub create_hold {
         for my $evt (@events) {
             next unless $evt;
             my $name = $evt->{textcode};
-            return $e->die_event unless $e->allowed("$name.override", $porg);
+            if($oargs->{all} || grep { $_ eq $name } @{$oargs->{events}}) {
+                return $e->die_event unless $e->allowed("$name.override", $porg);
+            } else {
+                $e->rollback;
+                return \@events;
+            }
         }
     }
 
@@ -2159,9 +2164,9 @@ __PACKAGE__->register_method(
 );
 
 sub check_title_hold_batch {
-    my($self, $client, $authtoken, $param_list) = @_;
+    my($self, $client, $authtoken, $param_list, $oargs) = @_;
     foreach (@$param_list) {
-        my ($res) = $self->method_lookup('open-ils.circ.title_hold.is_possible')->run($authtoken, $_);
+        my ($res) = $self->method_lookup('open-ils.circ.title_hold.is_possible')->run($authtoken, $_, $oargs);
         $client->respond($res);
     }
     return undef;
@@ -2215,9 +2220,14 @@ All key/value pairs are passed on to do_possibility_checks.
 # FIXME: specify proper usage/interaction of selection_ou and pickup_lib
 
 sub check_title_hold {
-    my( $self, $client, $authtoken, $params ) = @_;
+    my( $self, $client, $authtoken, $params, $oargs ) = @_;
     my $e = new_editor(authtoken=>$authtoken);
     return $e->event unless $e->checkauth;
+    $oargs = {} unless defined $oargs;
+
+    if($oargs->{events}) {
+        @{$oargs->{events}} = grep { $e->allowed($_ . '.override', $e->requestor->ws_ou); } @{$oargs->{events}};
+    }
 
     my %params       = %$params;
     my $depth        = $params{depth}        || 0;
@@ -2252,7 +2262,7 @@ sub check_title_hold {
         my $depth = $soft_boundary;
         while($depth >= $min_depth) {
             $logger->info("performing hold possibility check with soft boundary $depth");
-            @status = do_possibility_checks($e, $patron, $request_lib, $depth, %params);
+            @status = do_possibility_checks($e, $patron, $request_lib, $depth, %params, $oargs);
             if ($status[0]) {
                 $return_depth = $depth;
                 last;
@@ -2262,11 +2272,11 @@ sub check_title_hold {
     } elsif(defined $hard_boundary and $depth < $hard_boundary) {
         # there is no soft boundary, enforce the hard boundary if it exists
         $logger->info("performing hold possibility check with hard boundary $hard_boundary");
-        @status = do_possibility_checks($e, $patron, $request_lib, $hard_boundary, %params);
+        @status = do_possibility_checks($e, $patron, $request_lib, $hard_boundary, %params, $oargs);
     } else {
         # no boundaries defined, fall back to user specifed boundary or no boundary
         $logger->info("performing hold possibility check with no boundary");
-        @status = do_possibility_checks($e, $patron, $request_lib, $params{depth}, %params);
+        @status = do_possibility_checks($e, $patron, $request_lib, $params{depth}, %params, $oargs);
     }
 
     my $place_unfillable = 0;
@@ -2289,7 +2299,7 @@ sub check_title_hold {
 
 
 sub do_possibility_checks {
-    my($e, $patron, $request_lib, $depth, %params) = @_;
+    my($e, $patron, $request_lib, $depth, %params, $oargs) = @_;
 
     my $issuanceid   = $params{issuanceid}      || "";
     my $partid       = $params{partid}      || "";
@@ -2315,7 +2325,7 @@ sub do_possibility_checks {
 
         return (1, 1, []) if( $hold_type eq OILS_HOLD_TYPE_RECALL || $hold_type eq OILS_HOLD_TYPE_FORCE);
         return verify_copy_for_hold( 
-            $patron, $e->requestor, $title, $copy, $pickup_lib, $request_lib
+            $patron, $e->requestor, $title, $copy, $pickup_lib, $request_lib, $oargs
         );
 
        } elsif( $hold_type eq OILS_HOLD_TYPE_VOLUME ) {
@@ -2324,25 +2334,25 @@ sub do_possibility_checks {
                return $e->event unless $title  = $e->retrieve_biblio_record_entry($volume->record);
 
                return _check_volume_hold_is_possible(
-                       $volume, $title, $depth, $request_lib, $patron, $e->requestor, $pickup_lib, $selection_ou
+                       $volume, $title, $depth, $request_lib, $patron, $e->requestor, $pickup_lib, $selection_ou, $oargs
         );
 
        } elsif( $hold_type eq OILS_HOLD_TYPE_TITLE ) {
 
                return _check_title_hold_is_possible(
-                       $titleid, $depth, $request_lib, $patron, $e->requestor, $pickup_lib, $selection_ou
+                       $titleid, $depth, $request_lib, $patron, $e->requestor, $pickup_lib, $selection_ou, $oargs
         );
 
        } elsif( $hold_type eq OILS_HOLD_TYPE_ISSUANCE ) {
 
                return _check_issuance_hold_is_possible(
-                       $issuanceid, $depth, $request_lib, $patron, $e->requestor, $pickup_lib, $selection_ou
+                       $issuanceid, $depth, $request_lib, $patron, $e->requestor, $pickup_lib, $selection_ou, $oargs
         );
 
        } elsif( $hold_type eq OILS_HOLD_TYPE_MONOPART ) {
 
                return _check_monopart_hold_is_possible(
-                       $partid, $depth, $request_lib, $patron, $e->requestor, $pickup_lib, $selection_ou
+                       $partid, $depth, $request_lib, $patron, $e->requestor, $pickup_lib, $selection_ou, $oargs
         );
 
        } elsif( $hold_type eq OILS_HOLD_TYPE_METARECORD ) {
@@ -2352,7 +2362,7 @@ sub do_possibility_checks {
                my @status = ();
                for my $rec (@recs) {
                        @status = _check_title_hold_is_possible(
-                               $rec, $depth, $request_lib, $patron, $e->requestor, $pickup_lib, $selection_ou, $holdable_formats
+                               $rec, $depth, $request_lib, $patron, $e->requestor, $pickup_lib, $selection_ou, $holdable_formats, $oargs
                        );
                        last if $status[0];
                }
@@ -2387,7 +2397,7 @@ sub create_ranged_org_filter {
 
 
 sub _check_title_hold_is_possible {
-    my( $titleid, $depth, $request_lib, $patron, $requestor, $pickup_lib, $selection_ou, $holdable_formats ) = @_;
+    my( $titleid, $depth, $request_lib, $patron, $requestor, $pickup_lib, $selection_ou, $holdable_formats, $oargs ) = @_;
    
     my ($types, $formats, $lang);
     if (defined($holdable_formats)) {
@@ -2517,7 +2527,7 @@ sub _check_title_hold_is_possible {
          }
    
          @status = verify_copy_for_hold(
-            $patron, $requestor, $title, $copy, $pickup_lib, $request_lib);
+            $patron, $requestor, $title, $copy, $pickup_lib, $request_lib, $oargs);
 
          $age_protect_only ||= $status[3];
          last OUTER if $status[0];
@@ -2529,7 +2539,7 @@ sub _check_title_hold_is_possible {
 }
 
 sub _check_issuance_hold_is_possible {
-    my( $issuanceid, $depth, $request_lib, $patron, $requestor, $pickup_lib, $selection_ou ) = @_;
+    my( $issuanceid, $depth, $request_lib, $patron, $requestor, $pickup_lib, $selection_ou, $oargs ) = @_;
    
     my $e = new_editor();
     my %org_filter = create_ranged_org_filter($e, $selection_ou, $depth);
@@ -2646,7 +2656,7 @@ sub _check_issuance_hold_is_possible {
          }
    
          @status = verify_copy_for_hold(
-            $patron, $requestor, $title, $copy, $pickup_lib, $request_lib);
+            $patron, $requestor, $title, $copy, $pickup_lib, $request_lib, $oargs);
 
          $age_protect_only ||= $status[3];
          last OUTER if $status[0];
@@ -2666,7 +2676,7 @@ sub _check_issuance_hold_is_possible {
 }
 
 sub _check_monopart_hold_is_possible {
-    my( $partid, $depth, $request_lib, $patron, $requestor, $pickup_lib, $selection_ou ) = @_;
+    my( $partid, $depth, $request_lib, $patron, $requestor, $pickup_lib, $selection_ou, $oargs ) = @_;
    
     my $e = new_editor();
     my %org_filter = create_ranged_org_filter($e, $selection_ou, $depth);
@@ -2783,7 +2793,7 @@ sub _check_monopart_hold_is_possible {
          }
    
          @status = verify_copy_for_hold(
-            $patron, $requestor, $title, $copy, $pickup_lib, $request_lib);
+            $patron, $requestor, $title, $copy, $pickup_lib, $request_lib, $oargs);
 
          $age_protect_only ||= $status[3];
          last OUTER if $status[0];
@@ -2804,7 +2814,7 @@ sub _check_monopart_hold_is_possible {
 
 
 sub _check_volume_hold_is_possible {
-       my( $vol, $title, $depth, $request_lib, $patron, $requestor, $pickup_lib, $selection_ou ) = @_;
+       my( $vol, $title, $depth, $request_lib, $patron, $requestor, $pickup_lib, $selection_ou, $oargs ) = @_;
     my %org_filter = create_ranged_org_filter(new_editor(), $selection_ou, $depth);
        my $copies = new_editor->search_asset_copy({call_number => $vol->id, %org_filter});
        $logger->info("checking possibility of volume hold for volume ".$vol->id);
@@ -2830,7 +2840,7 @@ sub _check_volume_hold_is_possible {
     my $age_protect_only = 0;
        for my $copy ( @$copies ) {
         @status = verify_copy_for_hold(
-                       $patron, $requestor, $title, $copy, $pickup_lib, $request_lib );
+                       $patron, $requestor, $title, $copy, $pickup_lib, $request_lib, $oargs );
         $age_protect_only ||= $status[3];
         last if $status[0];
        }
@@ -2841,7 +2851,8 @@ sub _check_volume_hold_is_possible {
 
 
 sub verify_copy_for_hold {
-       my( $patron, $requestor, $title, $copy, $pickup_lib, $request_lib ) = @_;
+       my( $patron, $requestor, $title, $copy, $pickup_lib, $request_lib, $oargs ) = @_;
+    $oargs = {} unless defined $oargs;
        $logger->info("checking possibility of copy in hold request for copy ".$copy->id);
     my $permitted = OpenILS::Utils::PermitHold::permit_copy_hold(
                {       patron                          => $patron, 
@@ -2855,6 +2866,17 @@ sub verify_copy_for_hold {
             show_event_list     => 1
                } 
        );
+
+    # All overridden?
+    my $permit_anyway = 0;
+    foreach my $permit_event (@$permitted) {
+        if (grep { $_ eq $permit_event->{textcode} } @{$oargs->{events}}) {
+            $permit_anyway = 1;
+            last;
+        }
+    }
+    $permitted = [] if $permit_anyway;
+
     my $age_protect_only = 0;
     if (@$permitted == 1 && @$permitted[0]->{textcode} eq 'ITEM_AGE_PROTECTED') {
         $age_protect_only = 1;
index e09b9f6..9c4bfc6 100644 (file)
@@ -384,9 +384,10 @@ __PACKAGE__->register_method (
 );
 
 sub delete_survey {
-    my($self, $conn, $auth, $survey_id) = @_;
+    my($self, $conn, $auth, $survey_id, $oargs) = @_;
     my $e = new_editor(authtoken => $auth, xact => 1);
     return $e->die_event unless $e->checkauth;
+    $oargs = { all => 1 } unless defined $oargs;
 
     my $survey = $e->retrieve_action_survey($survey_id) 
         or return $e->die_event;
@@ -398,7 +399,7 @@ sub delete_survey {
     my $responses = $e->search_action_survey_response({survey => $survey_id});
 
     return OpenILS::Event->new('SURVEY_RESPONSES_EXIST')
-        if @$responses and $self->api_name =! /override/;
+        if @$responses and ($self->api_name =! /override/ || !($oargs->{all} || grep { $_ eq 'SURVEY_RESPONSES_EXIST' } @{$oargs->{events}}));
 
     for my $resp (@$responses) {
         $e->delete_action_survey_response($resp) or return $e->die_event;