From 9e145d40e6ba9214a699dd6aefabd630038533d8 Mon Sep 17 00:00:00 2001 From: senator Date: Tue, 30 Mar 2010 17:50:25 +0000 Subject: [PATCH] Acq: PO interface now tells you if activating a PO would breach fund limits. git-svn-id: svn://svn.open-ils.org/ILS/trunk@16062 dcc99617-32d9-48b4-a31d-7c20da2025e4 --- Open-ILS/src/extras/ils_events.xml | 6 ++ .../perlmods/OpenILS/Application/Acq/Order.pm | 94 ++++++++++++++----- Open-ILS/web/js/dojo/openils/acq/nls/acq.js | 7 +- Open-ILS/web/js/ui/default/acq/po/view_po.js | 75 ++++++++++++++- .../web/templates/default/acq/po/view.tt2 | 8 +- 5 files changed, 158 insertions(+), 32 deletions(-) diff --git a/Open-ILS/src/extras/ils_events.xml b/Open-ILS/src/extras/ils_events.xml index 54682419f6..0a74a95b1b 100644 --- a/Open-ILS/src/extras/ils_events.xml +++ b/Open-ILS/src/extras/ils_events.xml @@ -651,6 +651,12 @@ The requested acq.purchase_order cannot be split because it has gone beyond the "pending" state + + The requested acq.purchase_order cannot be activated because it would over-encumber a fund. + + + Activating the requested acq.purchase_order would encumber it beyond its warning level. + The requested acq.lineitem_detail was not found diff --git a/Open-ILS/src/perlmods/OpenILS/Application/Acq/Order.pm b/Open-ILS/src/perlmods/OpenILS/Application/Acq/Order.pm index a08dc09a82..220c65ec9d 100644 --- a/Open-ILS/src/perlmods/OpenILS/Application/Acq/Order.pm +++ b/Open-ILS/src/perlmods/OpenILS/Application/Acq/Order.pm @@ -606,7 +606,7 @@ sub set_lineitem_attr { # Lineitem Debits # ---------------------------------------------------------------------------- sub create_lineitem_debits { - my($mgr, $li) = @_; + my ($mgr, $li, $dry_run) = @_; unless($li->estimated_unit_price) { $mgr->editor->event(OpenILS::Event->new('ACQ_LINEITEM_NO_PRICE', payload => $li->id)); @@ -634,7 +634,7 @@ sub create_lineitem_debits { } ]); - create_lineitem_detail_debit($mgr, $li, $lid) or return 0; + create_lineitem_detail_debit($mgr, $li, $lid, $dry_run) or return 0; } return 1; @@ -644,7 +644,7 @@ sub create_lineitem_debits { # flesh li->provider # flesh lid->fund sub create_lineitem_detail_debit { - my($mgr, $li, $lid) = @_; + my ($mgr, $li, $lid, $dry_run) = @_; my $li_id = ref($li) ? $li->id : $li; @@ -684,6 +684,7 @@ sub create_lineitem_detail_debit { my $debit = create_fund_debit( $mgr, + $dry_run, fund => $lid->fund->id, origin_amount => $li->estimated_unit_price, origin_currency_type => $li->provider->currency_type, @@ -697,33 +698,65 @@ sub create_lineitem_detail_debit { } -# ---------------------------------------------------------------------------- -# Fund Debit -# ---------------------------------------------------------------------------- -sub create_fund_debit { - my($mgr, %args) = @_; +sub fund_exceeds_balance_stop_percent { + return fund_exceeds_balance_percent( + @_, "balance_stop_percent", "ACQ_FUND_EXCEEDS_STOP_PERCENT" + ); +} - # Verify the fund is not being spent beyond the hard stop amount - my $fund = $mgr->editor->retrieve_acq_fund($args{fund}) or return 0; +sub fund_exceeds_balance_warning_percent { + return fund_exceeds_balance_percent( + @_, "balance_warning_percent", "ACQ_FUND_EXCEEDS_WARN_PERCENT" + ); +} + +sub fund_exceeds_balance_percent { + my ($fund, $debit_amount, $e, $method_name, $event_name) = @_; - if($fund->balance_stop_percent) { + if ($fund->$method_name) { + my $balance = + $e->search_acq_fund_combined_balance({"fund" => $fund->id})->[0]; + my $allocations = + $e->search_acq_fund_allocation_total({"fund" => $fund->id})->[0]; - my $balance = $mgr->editor->search_acq_fund_combined_balance({fund => $fund->id})->[0]; - my $allocations = $mgr->editor->search_acq_fund_allocation_total({fund => $fund->id})->[0]; $balance = ($balance) ? $balance->amount : 0; $allocations = ($allocations) ? $allocations->amount : 0; - if( + if ( $allocations == 0 || # if no allocations were ever made, assume we have hit the stop percent - ( ( ( ($balance - $args{amount}) / $allocations ) * 100 ) < $fund->balance_stop_percent)) - { - $mgr->editor->event(OpenILS::Event->new( - 'FUND_EXCEEDS_STOP_PERCENT', - payload => {fund => $fund->id, debit_amount => $args{amount}} - )); - return 0; + ((($balance - $debit_amount) / $allocations) * 100) < + $fund->$method_name + ) { + $e->event( + new OpenILS::Event( + $event_name, + "payload" => { + "fund" => $fund, + "debit_amount" => $debit_amount + } + ) + ); + return 1; } } + return 0; +} + +# ---------------------------------------------------------------------------- +# Fund Debit +# ---------------------------------------------------------------------------- +sub create_fund_debit { + my($mgr, $dry_run, %args) = @_; + + # Verify the fund is not being spent beyond the hard stop amount + my $fund = $mgr->editor->retrieve_acq_fund($args{fund}) or return 0; + + return 0 if + fund_exceeds_balance_stop_percent($fund, $args{"amount"}, $mgr->editor); + return 0 if + $dry_run and fund_exceeds_balance_warning_percent( + $fund, $args{"amount"}, $mgr->editor + ); my $debit = Fieldmapper::acq::fund_debit->new; $debit->debit_type('purchase'); @@ -1982,6 +2015,11 @@ sub delete_picklist_api { +__PACKAGE__->register_method( + method => 'activate_purchase_order', + api_name => 'open-ils.acq.purchase_order.activate.dry_run' +); + __PACKAGE__->register_method( method => 'activate_purchase_order', api_name => 'open-ils.acq.purchase_order.activate', @@ -1999,19 +2037,25 @@ __PACKAGE__->register_method( sub activate_purchase_order { my($self, $conn, $auth, $po_id) = @_; + + my $dry_run = ($self->api_name =~ /\.dry_run/) ? 1 : 0; my $e = new_editor(xact=>1, authtoken=>$auth); return $e->die_event unless $e->checkauth; my $mgr = OpenILS::Application::Acq::BatchManager->new(editor => $e, conn => $conn); - my $die_event = activate_purchase_order_impl($mgr, $po_id); + my $die_event = activate_purchase_order_impl($mgr, $po_id, $dry_run); return $die_event if $die_event; - $e->commit; + if ($dry_run) { + $e->rollback; + } else { + $e->commit; + } $conn->respond_complete(1); $mgr->run_post_response_hooks; return undef; } sub activate_purchase_order_impl { - my($mgr, $po_id) = @_; + my ($mgr, $po_id, $dry_run) = @_; my $e = $mgr->editor; my $po = $e->retrieve_acq_purchase_order($po_id) or return $e->die_event; @@ -2028,7 +2072,7 @@ sub activate_purchase_order_impl { while( my $li = $e->search_acq_lineitem($query)->[0] ) { $li->state('on-order'); - create_lineitem_debits($mgr, $li) or return $e->die_event; + create_lineitem_debits($mgr, $li, $dry_run) or return $e->die_event; update_lineitem($mgr, $li) or return $e->die_event; $mgr->post_process( sub { create_lineitem_status_events($mgr, $li->id, 'aur.ordered'); }); $mgr->respond; diff --git a/Open-ILS/web/js/dojo/openils/acq/nls/acq.js b/Open-ILS/web/js/dojo/openils/acq/nls/acq.js index af3c7774b9..56ba178a31 100644 --- a/Open-ILS/web/js/dojo/openils/acq/nls/acq.js +++ b/Open-ILS/web/js/dojo/openils/acq/nls/acq.js @@ -48,5 +48,10 @@ 'FUND_LIST_ROLLOVER_SUMMARY_FUNDS' : '${1} funds propagated for fiscal year ${0} for the selected locations', 'FUND_LIST_ROLLOVER_SUMMARY_ROLLOVER_AMOUNT' : '$${1} unspent money rolled over to fiscal year ${0} for the selected locations', 'FUND_XFER_SAME_SOURCE_AND_DEST': "Cannot transfer. The source and destination funds are the same.", - 'FUND_XFER_CONFIRM': "Are you sure you're ready to commit this transfer?" + 'FUND_XFER_CONFIRM': "Are you sure you're ready to commit this transfer?", + 'PO_CHECKING': "[One moment...]", + 'PO_COULD_ACTIVATE' : "Yes.", + 'PO_WARNING_NO_BLOCK_ACTIVATION': "Yes; fund ${0} (${1}) would be encumbered beyond its warning level.", + 'PO_STOP_BLOCKS_ACTIVATION': "No; fund ${0} (${1}) would be encumbered beyond its stop level.", + 'PO_FUND_WARNING_CONFIRM': "Are you sure? Did you see the warning about over-encumbering a fund?" } diff --git a/Open-ILS/web/js/ui/default/acq/po/view_po.js b/Open-ILS/web/js/ui/default/acq/po/view_po.js index d15185b596..f804a31a8d 100644 --- a/Open-ILS/web/js/ui/default/acq/po/view_po.js +++ b/Open-ILS/web/js/ui/default/acq/po/view_po.js @@ -1,3 +1,4 @@ +dojo.require("dojo.string"); dojo.require('dijit.layout.ContentPane'); dojo.require('openils.User'); dojo.require('openils.Util'); @@ -281,7 +282,8 @@ function renderPo() { dojo.byId("acq-po-view-notes").innerHTML = PO.notes().length; if(PO.state() == "pending") { - openils.Util.show("acq-po-activate"); + openils.Util.show("acq-po-activate", "table-row"); + checkCouldActivatePo(); if (PO.lineitem_count() > 1) openils.Util.show("acq-po-split"); } @@ -327,11 +329,74 @@ params: [openils.User.authtoken, {purchase_order:poId}, {flesh_attrs:true, flesh ); } +function checkCouldActivatePo() { + var d = dojo.byId("acq-po-activate-checking"); + var a = dojo.byId("acq-po-activate-link"); + d.innerHTML = localeStrings.PO_CHECKING; + var warnings = []; + var stops = []; + + fieldmapper.standardRequest( + ["open-ils.acq", "open-ils.acq.purchase_order.activate.dry_run"], { + "params": [openils.User.authtoken, PO.id()], + "async": true, + "onresponse": function(r) { + if ((r = openils.Util.readResponse(r, true /* eventOk */))) { + if (typeof(r.textcode) != "undefined") { + switch(r.textcode) { + case "ACQ_FUND_EXCEEDS_STOP_PERCENT": + stops.push(r); + break; + case "ACQ_FUND_EXCEEDS_WARN_PERCENT": + warnings.push(r); + break; + } + } + } + }, + "oncomplete": function() { + /* XXX in the future, this might be tweaked to display info + * about more than one stop or warning event from the ML. */ + if (!(warnings.length || stops.length)) { + d.innerHTML = localeStrings.PO_COULD_ACTIVATE; + openils.Util.show(a, "inline"); + } else { + if (stops.length) { + d.innerHTML = + dojo.string.substitute( + localeStrings.PO_STOP_BLOCKS_ACTIVATION, [ + stops[0].payload.fund.code(), + stops[0].payload.fund.year() + ] + ); + openils.Util.hide(a); + } else { + PO._warning_hack = true; + d.innerHTML = + dojo.string.substitute( + localeStrings.PO_WARNING_NO_BLOCK_ACTIVATION, [ + warnings[0].payload.fund.code(), + warnings[0].payload.fund.year() + ] + ); + openils.Util.show(a, "inline"); + } + } + } + } + ); +} + function activatePo() { - if ( - openils.Util.isTrue(PO.prepayment_required()) && - !confirm(localeStrings.PREPAYMENT_REQUIRED_REMINDER) - ) return false; + if (openils.Util.isTrue(PO.prepayment_required())) { + if (!confirm(localeStrings.PREPAYMENT_REQUIRED_REMINDER)) + return false; + } + + if (PO._warning_hack) { + if (!confirm(localeStrings.PO_FUND_WARNING_CONFIRM)) + return false; + } progressDialog.show(true); try { diff --git a/Open-ILS/web/templates/default/acq/po/view.tt2 b/Open-ILS/web/templates/default/acq/po/view.tt2 index b5c45aab35..c4054c6cb8 100644 --- a/Open-ILS/web/templates/default/acq/po/view.tt2 +++ b/Open-ILS/web/templates/default/acq/po/view.tt2 @@ -42,7 +42,13 @@ id="acq-po-view-notes"> - + + Activatable? + + + + + -- 2.43.2