From: Lebbeous Fogle-Weekley Date: Tue, 12 Feb 2013 22:42:56 +0000 (-0500) Subject: Acq: lineitem batch updater - more perm checks, working on implementation X-Git-Url: https://old-git.evergreen-ils.org/?a=commitdiff_plain;h=076941a74b4eb24c9153a3eced732867b6494f75;p=evergreen%2Fequinox.git Acq: lineitem batch updater - more perm checks, working on implementation Signed-off-by: Lebbeous Fogle-Weekley --- diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Acq/Lineitem.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Acq/Lineitem.pm index e96f30e47c..4fdc0aa4fb 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Acq/Lineitem.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Acq/Lineitem.pm @@ -954,8 +954,9 @@ sub retrieve_lineitem_by_copy_id { return $li; } -# lineitem_batch_update_perm_test() +# lineitem_batch_update_perm_test(), helper for lineitem_batch_update_api() # +# Tests permissions on targeted lineitems, purchase orders, and picklists. # Returns undef on success, event on perm failure. # Responsible for calling $e->die_event. # Also sanitizes values in $target. @@ -1066,6 +1067,71 @@ sub lineitem_batch_update_perm_test { return; # perm check pass } +# lineitem_batch_update_impl() should be handed everything pre-perm-checked +# and ready-to-go. $e is in a transaction. +sub lineitem_batch_update_impl { + my ($e, $target, $changes, $dist_formula) = @_; + + # First, retrieve existing lineitem details. + + # The right ordering is important for adjusting lineitem detail counts. + my %order_by = (order_by => [ + {class => "acqlid", field => "lineitem"}, + {class => "acqlid", field => "id"} + ]); + + my $lineitem_details; + + if ($target->{lineitems}) { + $lineitem_details = $e->search_acq_lineitem_detail( + {lineitem => $target->{lineitems}}, \%order_by + ) or return $e->die_event; + } else { + my $where; + + if ($target->{purchase_order}) { + $where = {"+jub" => {purchase_order => $target->{purchase_order}}}; + } else { # picklist + $where = {"+jub" => {picklist => $target->{picklist}}}; + } + + $lineitem_details = $e->search_acq_lineitem_detail( + $where, {join => "jub", %order_by} + ) or return $e->die_event; + } + + # XXX Here, send one of those opensrf continue thingers in case (or substream on previous search_*()? ask berick + + # XXX TODO + # Count how many lineitem details we have per lineitem, and for each + # lineitem add or remove lineitems to match $changes->{count}, as needed. + + # Now, going through all our lineitem details, make the updates called for + # in $changes, other than the 'count' field (handled above). + + foreach my $lid (@$lineitem_details) { + foreach my $field (qw/owning_lib fund location collection_code circ_modifer/) { + # undef value in $changes should clear a field. + # Absence of value should do nothing to a field. + + if (exists $changes->{$field}) { + if (not defined $changes->{$field}) { + my $meth = "clear_$field"; + $lid->$meth; + } else { + $lid->$field($changes->{$field}); + } + } + } + + # XXX TODO cstore update, and send client a response per LI (not per + # LID I think...) + } + + $e->commit; +} + + __PACKAGE__->register_method( method => "lineitem_batch_update_api", api_name => "open-ils.acq.lineitem.batch_update", @@ -1086,16 +1152,53 @@ __PACKAGE__->register_method( sub lineitem_batch_update_api { my ($self, $conn, $auth, $target, $changes, $dist_formula) = @_; - my $e = new_editor("authtoken" => $auth, xact => 1); + # Make sure that $changes->{count}, if it exists, is a natural number. + # Other things in $change are safe to treat somewhat more casually, + # except fund, which is handled later. + $changes ||= {}; + if (exists $changes->{count}) { + $changes->{count} = int($changes->{count}); + return new OpenILS::Event("BAD_PARAMS", note => "changes (count)") + unless $changes->{count} >= 0; + } + + # We want to do our perm tests and everything within a transaction. + + my $e = new_editor(authtoken => $auth, xact => 1); return $e->die_event unless $e->checkauth; - # lineitem_batch_update_perm_test() will call die_event() for us if needed. + # If any distribution formula ID is given, fetch distribution formula + # (with entries fleshed) early so we can get a quick permission check + # out of the way. + if ($dist_formula) { + $dist_formula = $e->acq->retrieve_acq_dist_formula([ + int($dist_formula), {flesh=>1, flesh_fields=>["entries","fund"]} + ]) or return $e->die_event; + + return $e->die_event unless + $e->allowed("ADMIN_ACQ_DISTRIB_FORMULA", $dist_formula->owner); + + # If the distribution formula has a fund, there's an additional perm + # test to do before proceeding. + if ($dist_formula->fund) { + return $e->die_event unless $e->allowed( + ["ADMIN_FUND", "MANAGE_FUND"], + $dist_formula->fund->org, $dist_formula->fund + ); + } + } + + # Next, test permissions on fund to set, if any, from $changes. + # XXX TODO + + # Now test permissions on the targets. lineitem_batch_update_perm_test() + # calls die_event() for us if needed. Has side-effect of target + # sanitization. my $evt = lineitem_batch_update_perm_test($e, $target); return $evt if $U->event_code($evt); - $e->rollback; - - return 1; + # Now do the actual work. + return lineitem_batch_update_impl($e, $target, $changes, $dist_formula); } 1;