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.
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",
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;