From bf90fb810ecfda70583994b75ae53b32ac3d1b5d Mon Sep 17 00:00:00 2001 From: Andrew Isherwood Date: Wed, 16 Jun 2021 14:22:30 +0100 Subject: [PATCH] Bug 24190: Add acquisition logging Signed-off-by: Maura Stephens Signed-off-by: Nick Clemens Signed-off-by: Jonathan Druart --- C4/Budgets.pm | 44 +++++++++- acqui/addorder.pl | 43 ++++++++++ acqui/cancelorder.pl | 5 ++ acqui/finishreceive.pl | 18 ++++ acqui/invoice.pl | 85 ++++++++++++++++++- admin/aqbudgetperiods.pl | 37 ++++++-- .../prog/en/modules/tools/viewlog.tt | 13 ++- 7 files changed, 233 insertions(+), 12 deletions(-) diff --git a/C4/Budgets.pm b/C4/Budgets.pm index 888bd7bee4..439fcaf4b7 100644 --- a/C4/Budgets.pm +++ b/C4/Budgets.pm @@ -23,6 +23,7 @@ use Koha::Database; use Koha::Patrons; use Koha::Acquisition::Invoice::Adjustments; use C4::Acquisition; +use C4::Log qw(logaction); our (@ISA, @EXPORT_OK); BEGIN { @@ -640,7 +641,22 @@ sub AddBudget { undef $budget->{budget_encumb} if defined $budget->{budget_encumb} && $budget->{budget_encumb} eq ''; undef $budget->{budget_owner_id} if defined $budget->{budget_owner_id} && $budget->{budget_owner_id} eq ''; my $resultset = Koha::Database->new()->schema->resultset('Aqbudget'); - return $resultset->create($budget)->id; + my $id = $resultset->create($budget)->id; + + # Log the addition + if (C4::Context->preference("AcqLog")) { + my $infos = + sprintf("%010d", $budget->{budget_amount}) . + sprintf("%010d", $budget->{budget_encumb}) . + sprintf("%010d", $budget->{budget_expend}); + logaction( + 'ACQUISITIONS', + 'CREATE_FUND', + $id, + $infos + ); + } + return $id; } # ------------------------------------------------------------------- @@ -650,6 +666,24 @@ sub ModBudget { my $result = Koha::Database->new()->schema->resultset('Aqbudget')->find($budget); return unless($result); + # Log this modification + if (C4::Context->preference("AcqLog")) { + my $infos = + sprintf("%010d", $budget->{budget_amount}) . + sprintf("%010d", $budget->{budget_encumb}) . + sprintf("%010d", $budget->{budget_expend}) . + sprintf("%010d", $result->budget_amount) . + sprintf("%010d", $result->budget_encumb) . + sprintf("%010d", $result->budget_expend) . + sprintf("%010d", 0 - ($result->budget_amount - $budget->{budget_amount})); + logaction( + 'ACQUISITIONS', + 'MODIFY_FUND', + $budget->{budget_id}, + $infos + ); + } + undef $budget->{budget_encumb} if defined $budget->{budget_encumb} && $budget->{budget_encumb} eq ''; undef $budget->{budget_owner_id} if defined $budget->{budget_owner_id} && $budget->{budget_owner_id} eq ''; $result = $result->update($budget); @@ -663,6 +697,14 @@ sub DelBudget { my $dbh = C4::Context->dbh; my $sth = $dbh->prepare("delete from aqbudgets where budget_id=?"); my $rc = $sth->execute($budget_id); + # Log the deletion + if (C4::Context->preference("AcqLog")) { + logaction( + 'ACQUISITIONS', + 'DELETE_FUND', + $budget_id + ); + } return $rc; } diff --git a/acqui/addorder.pl b/acqui/addorder.pl index c0e68dade3..c7aa868968 100755 --- a/acqui/addorder.pl +++ b/acqui/addorder.pl @@ -237,6 +237,23 @@ my $user = $input->remote_user; my $basketno = $$orderinfo{basketno}; my $basket = Koha::Acquisition::Baskets->find($basketno); +# Order related fields we're going to log +my @log_order_fields = ( + 'quantity', + 'listprice', + 'unitprice', + 'unitprice_tax_excluded', + 'unitprice_tax_included', + 'rrp', + 'replacementprice', + 'rrp_tax_excluded', + 'rrp_tax_included', + 'ecost', + 'ecost_tax_excluded', + 'ecost_tax_included', + 'tax_rate_on_ordering' +); + # create, modify or delete biblio # create if $quantity>0 and $existing='no' # modify if $quantity>0 and $existing='yes' @@ -301,9 +318,35 @@ if ( $basket->{is_standing} || $orderinfo->{quantity} ne '0' ) { my $order = Koha::Acquisition::Order->new($orderinfo); if ( $orderinfo->{ordernumber} ) { ModOrder($orderinfo); + # Log the order modification + if (C4::Context->preference("AcqLog")) { + my $infos = ''; + foreach my $field(@log_order_fields) { + $infos .= sprintf("%010d", $orderinfo->{$field}); + } + logaction( + 'ACQUISITIONS', + 'MODIFY_ORDER', + $orderinfo->{ordernumber}, + $infos + ); + } } else { # else, it's a new line $order->store; + # Log the order creation + if (C4::Context->preference("AcqLog")) { + my $infos = ''; + foreach my $field(@log_order_fields) { + $infos .= sprintf("%010d", $orderinfo->{$field}); + } + logaction( + 'ACQUISITIONS', + 'CREATE_ORDER', + $order->ordernumber, + $infos + ); + } } my $order_users_ids = $input->param('users_ids'); my @order_users = split( /:/, $order_users_ids ); diff --git a/acqui/cancelorder.pl b/acqui/cancelorder.pl index 48e5b41423..6278202471 100755 --- a/acqui/cancelorder.pl +++ b/acqui/cancelorder.pl @@ -34,6 +34,7 @@ use Modern::Perl; use CGI; use C4::Auth qw( get_template_and_user ); use C4::Output qw( output_html_with_http_headers ); +use C4::Log qw(logaction); use Koha::Acquisition::Baskets; my $input = CGI->new; @@ -65,6 +66,10 @@ if( $action and $action eq "confirmcancel" ) { if $messages[0]->message eq 'error_delbiblio'; } else { $template->param(success_cancelorder => 1); + # Log the cancellation of the order + if (C4::Context->preference("AcqLog")) { + logaction('ACQUISITIONS', 'CANCEL_ORDER', $ordernumber); + } } $template->param(confirmcancel => 1); } diff --git a/acqui/finishreceive.pl b/acqui/finishreceive.pl index 95759c7917..e3305be479 100755 --- a/acqui/finishreceive.pl +++ b/acqui/finishreceive.pl @@ -28,6 +28,7 @@ use C4::Context; use C4::Acquisition qw( GetInvoice GetOrder populate_order_with_prices ModReceiveOrder ); use C4::Biblio qw( GetFrameworkCode GetMarcFromKohaField TransformHtmlToXml ); use C4::Items qw( GetMarcItem ModItemFromMarc AddItemFromMarc ); +use C4::Log qw(logaction); use C4::Search; use Koha::Number::Price; @@ -189,4 +190,21 @@ if ($suggestion_id) { $suggestion->update( { reason => $reason } ) if $suggestion; } +# Log the receipt +if (C4::Context->preference("AcqLog")) { + my $infos = + sprintf("%010d", $quantityrec) . + sprintf("%010d", $bookfund) . + sprintf("%010.2f", $input->param("tax_rate")) . + sprintf("%010.2f", $replacementprice) . + sprintf("%010.2f", $unitprice); + + logaction( + 'ACQUISITIONS', + 'RECEIVE_ORDER', + $ordernumber, + $infos + ); +} + print $input->redirect("/cgi-bin/koha/acqui/parcel.pl?invoiceid=$invoiceid"); diff --git a/acqui/invoice.pl b/acqui/invoice.pl index eaf804d51e..2e05c0dbe0 100755 --- a/acqui/invoice.pl +++ b/acqui/invoice.pl @@ -33,6 +33,7 @@ use C4::Auth qw( get_template_and_user ); use C4::Output qw( output_and_exit output_html_with_http_headers ); use C4::Acquisition qw( CloseInvoice ReopenInvoice ModInvoice MergeInvoices DelInvoice GetInvoice GetInvoiceDetails get_rounded_price ); use C4::Budgets qw( GetBudgetHierarchy GetBudget CanUserUseBudget ); +use C4::Log qw(logaction); use Koha::Acquisition::Booksellers; use Koha::Acquisition::Currencies qw( get_active ); @@ -145,7 +146,25 @@ elsif ( $op && $op eq 'del_adj' ) { my $adjustment_id = $input->param('adjustment_id'); my $del_adj = Koha::Acquisition::Invoice::Adjustments->find( $adjustment_id ); - $del_adj->delete() if ($del_adj); + if ($del_adj) { + if (C4::Context->preference("AcqLog")) { + my $reason_length = length $del_adj->reason; + my $reason_padded = ( ' ' x (80 - $reason_length) ) . $del_adj->reason; + my $infos = + sprintf("%010d", $del_adj->invoiceid) . + sprintf("%010d", $del_adj->budget_id) . + sprintf("%010d", $del_adj->encumber_open) . + sprintf("%010.2f", $del_adj->adjustment) . + $reason_padded; + logaction( + 'ACQUISITIONS', + 'DELETE_INVOICE_ADJUSTMENT', + $adjustment_id, + $infos + ); + } + $del_adj->delete(); + } } elsif ( $op && $op eq 'mod_adj' ) { @@ -160,10 +179,11 @@ elsif ( $op && $op eq 'mod_adj' ) { my @encumber_open = $input->multi_param('encumber_open'); my %e_open = map { $_ => 1 } @encumber_open; + my @keys = ('adjustment', 'reason', 'budget_id', 'encumber_open'); for( my $i=0; $i < scalar @adjustment; $i++ ){ if( $adjustment_id[$i] eq 'new' ){ next unless ( $adjustment[$i] || $reason[$i] ); - my $new_adj = Koha::Acquisition::Invoice::Adjustment->new({ + my $adj = { invoiceid => $invoiceid, adjustment => $adjustment[$i], reason => $reason[$i], @@ -171,11 +191,41 @@ elsif ( $op && $op eq 'mod_adj' ) { budget_id => $budget_id[$i] || undef, encumber_open => defined $e_open{ $adjustment_id[$i] } ? 1 : 0, }); + my $new_adj = Koha::Acquisition::Invoice::Adjustment->new($adj); $new_adj->store(); + # Log this addition + if (C4::Context->preference("AcqLog")) { + my $infos = get_log_string($adj); + logaction( + 'ACQUISITIONS', + 'CREATE_INVOICE_ADJUSTMENT', + $new_adj->adjustment_id, + $infos + ); + } } else { my $old_adj = Koha::Acquisition::Invoice::Adjustments->find( $adjustment_id[$i] ); unless ( $old_adj->adjustment == $adjustment[$i] && $old_adj->reason eq $reason[$i] && $old_adj->budget_id == $budget_id[$i] && $old_adj->encumber_open == $e_open{$adjustment_id[$i]} && $old_adj->note eq $note[$i] ){ + # Log this modification + if (C4::Context->preference("AcqLog")) { + my $infos = get_log_string({ + adjustment => $adjustment[$i], + reason => $reason[$i], + budget_id => $budget_id[$i], + encumber_open => $e_open{$adjustment_id[$i]}, + adjustment_old => $old_adj->adjustment, + reason_old => $old_adj->reason, + budget_id_old => $old_adj->budget_id, + encumber_open_old => $old_adj->encumber_open + }); + logaction( + 'ACQUISITIONS', + 'UPDATE_INVOICE_ADJUSTMENT', + $adjustment_id[$i], + $infos + ); + } $old_adj->timestamp(undef); $old_adj->adjustment( $adjustment[$i] ); $old_adj->reason( $reason[$i] ); @@ -300,4 +350,35 @@ sub get_infos { return \%line; } +sub get_log_string { + my ($data) = @_; + + # We specify the keys we're dealing for logging within an array in order + # to preserve order, if we just iterate the hash keys, we could get + # the values in any order + my @keys = ( + 'budget_id', + 'encumber_open', + 'budget_id_old', + 'encumber_open_old' + ); + # Adjustment amount + my $return = sprintf("%010.2f", $data->{adjustment}); + # Left pad "reason" to the maximum length of aqinvoice_adjustments.reason + # (80 characters) + my $reason_len = length $data->{reason}; + $return .= ( ' ' x (80 - $reason_len) ) . $data->{reason}; + # Append the remaining fields + foreach my $key(@keys) { + $return .= sprintf("%010d", $data->{$key}); + } + # Old adjustment amount + $return .= sprintf("%010.2f", $data->{adjustment_old}); + # Left pad "reason_old" to the maximum length of aqinvoice_adjustments.reason + # (80 characters) + my $reason_old_len = length $data->{reason_old}; + $return .= ( ' ' x (80 - $reason_old_len) ) . $data->{reason_old}; + return $return; +} + output_html_with_http_headers $input, $cookie, $template->output; diff --git a/admin/aqbudgetperiods.pl b/admin/aqbudgetperiods.pl index b5932725b5..d6192c2d7c 100755 --- a/admin/aqbudgetperiods.pl +++ b/admin/aqbudgetperiods.pl @@ -55,6 +55,7 @@ use C4::Auth qw( get_template_and_user ); use C4::Output qw( output_html_with_http_headers ); use C4::Acquisition; use C4::Budgets qw( GetBudgetPeriod GetBudgetPeriods ModBudgetPeriod AddBudgetPeriod GetBudgets DelBudgetPeriod CloneBudgetPeriod MoveOrders ); +use C4::Log qw(logaction); use Koha::Acquisition::Currencies; my $dbh = C4::Context->dbh; @@ -112,14 +113,34 @@ elsif ( $op eq 'add_validate' ) { ## add or modify a budget period (confirmation) ## update budget period data - if ( $budget_period_id ne '' ) { - $$budget_period_hashref{$_}||=0 for qw(budget_period_active budget_period_locked); - my $status=ModBudgetPeriod($budget_period_hashref); - } - else { # ELSE ITS AN ADD - my $budget_period_id=AddBudgetPeriod($budget_period_hashref); - } - $op='else'; + if ( $budget_period_id ne '' ) { + # Grab the previous values so we can log them + my $budgetperiod_old=GetBudgetPeriod($budget_period_id); + $$budget_period_hashref{$_}||=0 for qw(budget_period_active budget_period_locked); + my $status=ModBudgetPeriod($budget_period_hashref); + # Log the budget modification + if (C4::Context->preference("AcqLog")) { + my $diff = 0 - ($budgetperiod_old->{budget_period_total} - $budget_period_hashref->{budget_period_total}); + my $infos = + eval { output_pref({ dt => dt_from_string( $input->param('budget_period_startdate') ), dateformat => 'iso', dateonly => 1 } ); } . + eval { output_pref({ dt => dt_from_string( $input->param('budget_period_enddate') ), dateformat => 'iso', dateonly => 1 } ); } . + sprintf("%010d", $budget_period_hashref->{budget_period_total}) . + eval { output_pref({ dt => dt_from_string( $budgetperiod_old->{budget_period_startdate} ), dateformat => 'iso', dateonly => 1 } ); } . + eval { output_pref({ dt => dt_from_string( $budgetperiod_old->{budget_period_enddate} ), dateformat => 'iso', dateonly => 1 } ); } . + sprintf("%010d", $budgetperiod_old->{budget_period_total}) . + sprintf("%010d", $diff); + logaction( + 'ACQUISITIONS', + 'MODIFY_BUDGET', + $budget_period_id, + $infos + ); + } + } + else { # ELSE ITS AN ADD + my $budget_period_id=AddBudgetPeriod($budget_period_hashref); + } + $op='else'; } #-------------------------------------------------- diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/viewlog.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/viewlog.tt index 3b0886d369..0eba6b1611 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/viewlog.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/viewlog.tt @@ -125,6 +125,17 @@ [% CASE 'CLOSE_BASKET' %]Close an acquisitions basket [% CASE 'APPROVE_BASKET' %]Approve an acquisitions basket [% CASE 'REOPEN_BASKET' %]Reopen an acquisitions basket +[% CASE 'CANCEL_ORDER' %]Cancel an order +[% CASE 'CREATE_ORDER' %]Create an order +[% CASE 'MODIFY_ORDER' %]Modify an order +[% CASE 'CREATE_INVOICE_ADJUSTMENT' %]Create an invoice adjustment +[% CASE 'UPDATE_INVOICE_ADJUSTMENT' %]Modify an invoice adjustment +[% CASE 'DELETE_INVOICE_ADJUSTMENT' %]Delete an invoice adjustment +[% CASE 'RECEIVE_ORDER' %]Receive an order +[% CASE 'MODIFY_BUDGET' %]Modify a budget +[% CASE 'CREATE_FUND' %]Create a fund +[% CASE 'MODIFY_FUND' %]Modify a fund +[% CASE 'DELETE_FUND' %]Delete a fund [% CASE 'Run' %]Run [% CASE 'EDIT_MAPPINGS' %]Edit mappings [% CASE 'RESET_MAPPINGS' %]Reset mappings @@ -223,7 +234,7 @@ [% END %] - [% FOREACH actx IN [ 'ADD' 'DELETE' 'MODIFY' 'ISSUE' 'RETURN' 'RENEW' 'CREATE' 'CANCEL' 'SUSPEND' 'RESUME' 'ADDCIRCMESSAGE' 'DELCIRCMESSAGE' 'STATUS_CHANGE' 'PATRON_NOTICE' 'CHANGE PASS' 'Run' 'EDIT_MAPPINGS' 'RESET_MAPPINGS' 'ADD_BASKET' 'MODIFY_BASKET' 'MODIFY_BASKET_HEADER' 'MODIFY_BASKET_USERS' 'CLOSE_BASKET' 'APPROVE_BASKET' 'REOPEN_BASKET' ] %] + [% FOREACH actx IN [ 'ADD' 'DELETE' 'MODIFY' 'ISSUE' 'RETURN' 'RENEW' 'CREATE' 'CANCEL' 'SUSPEND' 'RESUME' 'ADDCIRCMESSAGE' 'DELCIRCMESSAGE' 'STATUS_CHANGE' 'PATRON_NOTICE' 'CHANGE PASS' 'Run' 'EDIT_MAPPINGS' 'RESET_MAPPINGS' 'ADD_BASKET' 'MODIFY_BASKET' 'MODIFY_BASKET_HEADER' 'MODIFY_BASKET_USERS' 'CLOSE_BASKET' 'APPROVE_BASKET' 'REOPEN_BASKET' 'CANCEL_ORDER' 'CREATE_ORDER' 'MODIFY_ORDER' 'CREATE_INVOICE_ADJUSTMENT' 'UPDATE_INVOICE_ADJUSTMENT' 'DELETE_INVOICE_ADJUSTMENT' 'RECEIVE_ORDER' 'MODIFY_BUDGET' 'MODIFY_FUND' 'CREATE_FUND' 'DELETE_FUND' ] %] [% IF actions.grep(actx).size %] [% ELSE %] -- 2.39.5