From: Lebbeous Fogle-Weekley Date: Tue, 11 Jun 2013 21:28:17 +0000 (-0400) Subject: UNFINISHED Acq: If deleting on-order copies, remove fund debits and (if confirmed... X-Git-Url: https://old-git.evergreen-ils.org/?a=commitdiff_plain;h=refs%2Fheads%2Facq-li-delete-debits-and-copies;p=evergreen%2Fequinox.git UNFINISHED Acq: If deleting on-order copies, remove fund debits and (if confirmed) copies 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 35d46485b8..cd5d0afc95 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Acq/Lineitem.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Acq/Lineitem.pm @@ -213,6 +213,53 @@ __PACKAGE__->register_method( } ); + +# Deletes one fund debit given its ID ($debit_id) *iff* it's an orphan +# (i.e., it's not related to any of the tables that can point to a fund_debit, +# not including the lineitem detail with ID $lid_id). +# +# Returns nothing on success, event on failure. +sub delete_orphan_fund_debit { + my ($e, $debit_id, $lid_id) = @_; + + # Make sure the debit is orphaned first. + my $rows = $e->json_query({ + select => {acqfdeb => ["id"]}, + from => { + acqfdeb => { + acqii => { + type => "left", field => "fund_debit", fkey => "id" + }, + acqpoi => { + type => "left", field => "fund_debit", fkey => "id" + }, + acqlid => { + type => "left", field => "fund_debit", fkey => "id" + }, + acqda => { + type => "left", field => "fund_debit", fkey => "id" + } + } + }, + where => { + "+acqfdeb" => {id => $debit_id}, + "+acqii" => {id => undef}, + "+acqpoi" => {id => undef}, + "+acqda" => {id => undef}, + "+acqlid" => {id => $lid_id}, + } + }) or return $e->die_event; + + if (@$rows) { + $e->delete_acq_fund_debit( + $e->retrieve_acq_fund_debit($rows->[0]->{id}) + ) or return $e->die_event; + } + + return; # success +} + + __PACKAGE__->register_method( method => 'delete_lineitem', api_name => 'open-ils.acq.picklist.lineitem.delete', @@ -221,13 +268,14 @@ __PACKAGE__->register_method( params => [ {desc => 'Authentication token', type => 'string'}, {desc => 'lineitem ID to delete', type => 'number'}, + {desc => 'Even delete associated copies', type => 'boolean'} ], return => {desc => '1 on success, Event on error'} } ); sub delete_lineitem { - my($self, $conn, $auth, $li_id) = @_; + my($self, $conn, $auth, $li_id, $even_copies) = @_; my $e = new_editor(xact=>1, authtoken=>$auth); return $e->die_event unless $e->checkauth; @@ -260,9 +308,43 @@ sub delete_lineitem { {lineitem => $li_id}, {idlist=>1}); for my $lid_id (@$lid_ids) { - $e->delete_acq_lineitem_detail( - $e->retrieve_acq_lineitem_detail($lid_id)) - or return $e->die_event; + # As of 2.4 (specifically as of commit 76d2e15b), it shouldn't be + # possible in normal workflows to delete lineitems attached to + # activated purchase orders. But it's probably possible through some + # side-door or other, and it's definitely possible if you go straight + # to the middle layer (with suitable authentication, of course). + # + # Until/unless we decide that should be tightened, we need to be + # careful not to leave orphaned fund debits hanging around when + # lineitems are deleted. + + my $lid = $e->retrieve_acq_lineitem_detail($lid_id); + + if ($lid->fund_debit) { + my $evt = delete_orphan_fund_debit($e, $lid->fund_debit, $lid->id); + return $evt if $evt; + } + + if ($lid->eg_copy_id) { + if ($even_copies) { + my $copy = $e->retrieve_asset_copy([ + $lid->eg_copy_id, + {flesh => 1, flesh_fields => {"acp" => ["call_number"]}} + ]) or return $e->die_event; + + $e->allowed("DELETE_COPY", $copy->call_number->owning_lib) or + return $e->die_event; + + $e->delete_asset_copy($copy) or return $e->die_event; + } else { + $e->rollback; + return new OpenILS::Event( + "NO_CHANGE", payload => $lid->eg_copy_id + ); + } + } + + $e->delete_acq_lineitem_detail($lid) or return $e->die_event; } $e->delete_acq_lineitem($li) or return $e->die_event; diff --git a/Open-ILS/web/js/dojo/openils/Util.js b/Open-ILS/web/js/dojo/openils/Util.js index 804d13c3c4..c8099b5241 100644 --- a/Open-ILS/web/js/dojo/openils/Util.js +++ b/Open-ILS/web/js/dojo/openils/Util.js @@ -163,23 +163,30 @@ if(!dojo._hasResource["openils.Util"]) { * false, the response content will be null when an event is encountered. * @param isList If true, assume the response will be a list of data and * check the 1st item in the list for event-ness instead of the list itself. + * @param eventDispatch optional dispatch table indexed by event textcode, + * with methods taking 1) event and 2) raw value as args. */ openils.Util.alertEvent = true; - openils.Util.readResponse = function(r, eventOk, isList) { + openils.Util.readResponse = function(r, eventOk, isList, eventDispatch) { var msg = r.recv(); - if(msg == null) return msg; + if (msg == null) return msg; var val = msg.content(); var testval = val; - if(isList && dojo.isArray(val)) + if (isList && dojo.isArray(val)) testval = val[0]; - if(e = openils.Event.parse(testval)) { - if(eventOk || e.textcode == 'SUCCESS') return e; - console.log(e.toString()); + if (e = openils.Event.parse(testval)) { + if (e.textcode != "NO_SESSION") { + if (eventOk || e.textcode == 'SUCCESS') { + return e; + } else if (eventDispatch && e.textcode in eventDispatch) { + return eventDispatch[e.textcode](e, val); + } + console.log(e.toString()); + } else { // session timed out. Stop propagation of requests queued by Util.onload // and launch the XUL login dialog if possible - var retryLogin = false; - if(e.textcode == 'NO_SESSION') { + var retryLogin = false; openils.User.authtoken = null; if(openils.XUL.isXUL()) { retryLogin = true; @@ -190,7 +197,7 @@ if(!dojo._hasResource["openils.Util"]) { } } - if(openils.Util.alertEvent && !retryLogin) + if (openils.Util.alertEvent && !retryLogin) alert(e); return null; } diff --git a/Open-ILS/web/js/ui/default/acq/common/li_table.js b/Open-ILS/web/js/ui/default/acq/common/li_table.js index 7a804da228..de56fa0cac 100644 --- a/Open-ILS/web/js/ui/default/acq/common/li_table.js +++ b/Open-ILS/web/js/ui/default/acq/common/li_table.js @@ -3179,7 +3179,7 @@ function AcqLiTable() { ); } - this._deleteLiList = function(list, idx) { + this._deleteLiList = function(list, idx, even_copies) { if(idx == null) idx = 0; if(idx >= list.length) return; @@ -3214,10 +3214,22 @@ function AcqLiTable() { ['open-ils.acq', this.isPO ? 'open-ils.acq.purchase_order.lineitem.delete' : 'open-ils.acq.picklist.lineitem.delete'], { async: true, - params: [openils.User.authtoken, liId], + params: [openils.User.authtoken, liId, even_copies], oncomplete: function(r) { - self.removeLineitem(liId); - self._deleteLiList(list, ++idx); + r = openils.Util.readResponse( + r, false, false, { + "NO_CHANGE": function(e, val) { + /* XXX replace with dijit.Dialog before publishing */ if (confirm(localeStrings.DELETE_LID_REAL_COPY)) { + self._deleteLiList(list, idx, true); + } + return 0; + } + } + ); + if (r) { /* worked fine, didn't get NO_CHANGE */ + self.removeLineitem(liId); + self._deleteLiList(list, ++idx, even_copies); + } } } );