@@ -, +, @@ - No. of ordered titles - No. of received titles - Date closed on the left (Edit, Close and export as PDF, View, Reopen, Export as CSV) --- Koha/Acquisition/Basket.pm | 37 +++ Koha/Acquisition/BasketGroup.pm | 92 +++++- acqui/basket.pl | 4 +- acqui/basketgroup.pl | 269 ++++++------------ acqui/basketgroups.pl | 52 ++++ .../prog/en/includes/acquisitions-menu.inc | 3 + .../prog/en/includes/datatables.inc | 2 + .../prog/en/includes/vendor-menu.inc | 2 +- .../prog/en/modules/acqui/basket.tt | 2 +- .../prog/en/modules/acqui/basketgroup.tt | 211 +++----------- .../prog/en/modules/acqui/basketgroups.tt | 168 +++++++++++ .../prog/en/modules/acqui/parcel.tt | 2 +- .../intranet-tmpl/prog/js/basketgroup.js | 8 - koha-tmpl/intranet-tmpl/prog/js/datatables.js | 101 +++++-- t/db_dependent/Koha/Acquisition/Basket.t | 46 ++- 15 files changed, 608 insertions(+), 391 deletions(-) create mode 100755 acqui/basketgroups.pl create mode 100644 koha-tmpl/intranet-tmpl/prog/en/modules/acqui/basketgroups.tt --- a/Koha/Acquisition/Basket.pm +++ a/Koha/Acquisition/Basket.pm @@ -21,6 +21,7 @@ use Modern::Perl; use Koha::Database; use Koha::Acquisition::BasketGroups; +use Koha::Acquisition::Orders; use base qw( Koha::Object Koha::Object::Mixin::AdditionalFields ); @@ -71,6 +72,42 @@ sub effective_create_items { return $self->create_items || C4::Context->preference('AcqCreateItem'); } +=head3 orders + +Returns basket's orders + + # As an arrayref + my $orders = $basket->orders; + + # As an array + my @orders = $basket->orders; + +=cut + +sub orders { + my ($self) = @_; + + $self->{_orders} ||= Koha::Acquisition::Orders->search({ basketno => $self->basketno }); + + return wantarray ? $self->{_orders}->as_list : $self->{_orders}; +} + +sub total { + my ($self) = @_; + + my $total = 0; + for my $order ($self->orders){ + # FIXME The following is wrong + if ( $self->bookseller->listincgst ) { + $total = $total + ( $order->ecost_tax_included * $order->quantity ); + } else { + $total = $total + ( $order->ecost_tax_excluded * $order->quantity ); + } + } + return $total; +} + + =head2 Internal methods =head3 _type --- a/Koha/Acquisition/BasketGroup.pm +++ a/Koha/Acquisition/BasketGroup.pm @@ -17,7 +17,10 @@ package Koha::Acquisition::BasketGroup; use Modern::Perl; +use List::MoreUtils qw/uniq/; + use Koha::Database; +use Koha::Acquisition::Baskets; use base qw( Koha::Object ); @@ -27,10 +30,97 @@ Koha::Acquisition::BasketGroup - Koha Basket group Object class =head1 API -=head2 Class Methods +=head2 Methods + +=head3 vendor + +Returns the basketgroup's vendor (Koha::Acquisition::Bookseller) + + my $vendor = $basketgroup->vendor; + +=cut + +sub vendor { + my ($self) = @_; + + return scalar Koha::Acquisition::Booksellers->find($self->booksellerid); +} + +=head3 baskets + +Returns the basketgroup's baskets + + my $baskets = $basketgroup->baskets; # Koha::Acquisition::Baskets + my @baskets = $basketgroup->baskets; # array of Koha::Acquisition::Basket + +=cut + +sub baskets { + my ($self) = @_; + + my $baskets = Koha::Acquisition::Baskets->search({ basketgroupid => $self->id }); + + return wantarray ? $baskets->as_list : $baskets; +} + +=head3 baskets_count + +Returns the number of baskets contained in a basket group + + my $count = $basketgroup->baskets_count; =cut +sub baskets_count { + my ($self) = @_; + + return $self->baskets->count; +} + +=head3 ordered_titles_count + +Returns the number of ordered titles contained in a basket group + + my $count = $basketgroup->ordered_titles_count; + +=cut + +sub ordered_titles_count { + my ($self) = @_; + + my @biblionumbers; + foreach my $basket ($self->baskets) { + foreach my $order ($basket->orders) { + push @biblionumbers, $order->biblionumber; + } + } + + return scalar uniq @biblionumbers; +} + +=head3 received_titles_count + +Returns the number of received titles contained in a basket group + + my $count = $basketgroup->ordered_titles_count; + +=cut + +sub received_titles_count { + my ($self) = @_; + + my @biblionumbers; + foreach my $basket ($self->baskets) { + foreach my $order ($basket->orders) { + if ($order->datereceived) { + push @biblionumbers, $order->biblionumber; + } + } + } + + return scalar uniq @biblionumbers; +} + =head2 Internal methods =head3 _type --- a/acqui/basket.pl +++ a/acqui/basket.pl @@ -211,7 +211,7 @@ if ( $op eq 'delete_confirm' ) { }); ModBasket( { basketno => $basketno, basketgroupid => $basketgroupid } ); - print $query->redirect('/cgi-bin/koha/acqui/basketgroup.pl?booksellerid='.$booksellerid.'&closed=1'); + print $query->redirect('/cgi-bin/koha/acqui/basketgroups.pl?booksellerid='.$booksellerid); } else { print $query->redirect('/cgi-bin/koha/acqui/booksellers.pl?booksellerid=' . $booksellerid); } @@ -563,7 +563,7 @@ sub edi_close_and_order { } ); print $query->redirect( -"/cgi-bin/koha/acqui/basketgroup.pl?booksellerid=$booksellerid&closed=1" + "/cgi-bin/koha/acqui/basketgroups.pl?booksellerid=$booksellerid" ); } else { --- a/acqui/basketgroup.pl +++ a/acqui/basketgroup.pl @@ -56,71 +56,20 @@ use Koha::EDI qw/create_edi_order get_edifact_ean/; use Koha::Biblioitems; use Koha::Acquisition::Booksellers; +use Koha::Acquisition::BasketGroups; use Koha::ItemTypes; use Koha::Patrons; -our $input=new CGI; - -our ($template, $loggedinuser, $cookie) - = get_template_and_user({template_name => "acqui/basketgroup.tt", - query => $input, - type => "intranet", - authnotrequired => 0, - flagsrequired => {acquisition => 'group_manage'}, - debug => 1, - }); - -sub BasketTotal { - my $basketno = shift; - my $bookseller = shift; - my $total = 0; - my @orders = GetOrders($basketno); - for my $order (@orders){ - # FIXME The following is wrong - if ( $bookseller->listincgst ) { - $total = $total + ( get_rounded_price($order->{ecost_tax_included}) * $order->{quantity} ); - } else { - $total = $total + ( get_rounded_price($order->{ecost_tax_excluded}) * $order->{quantity} ); - } - } - return $total; -} +my $input = new CGI; -#displays all basketgroups and all closed baskets (in their respective groups) -sub displaybasketgroups { - my $basketgroups = shift; - my $bookseller = shift; - my $baskets = shift; - if (scalar @$basketgroups != 0) { - foreach my $basketgroup (@$basketgroups){ - my $i = 0; - my $basketsqty = 0; - while($i < scalar(@$baskets)){ - my $basket = @$baskets[$i]; - if($basket->{'basketgroupid'} && $basket->{'basketgroupid'} == $basketgroup->{'id'}){ - $basket->{total} = BasketTotal($basket->{basketno}, $bookseller); - push(@{$basketgroup->{'baskets'}}, $basket); - splice(@$baskets, $i, 1); - ++$basketsqty; - --$i; - } - ++$i; - } - $basketgroup -> {'basketsqty'} = $basketsqty; - } - $template->param(basketgroups => $basketgroups); - } - for(my $i=0; $i < scalar @$baskets; ++$i) { - if( ! @$baskets[$i]->{'closedate'} ) { - splice(@$baskets, $i, 1); - --$i; - }else{ - @$baskets[$i]->{total} = BasketTotal(@$baskets[$i]->{basketno}, $bookseller); - } - } - $template->param(baskets => $baskets); - $template->param( booksellername => $bookseller->name); -} +our ($template, $loggedinuser, $cookie) = get_template_and_user({ + template_name => "acqui/basketgroup.tt", + query => $input, + type => "intranet", + authnotrequired => 0, + flagsrequired => {acquisition => 'group_manage'}, + debug => 1, +}); sub printbasketgrouppdf{ my ($basketgroupid) = @_; @@ -211,7 +160,6 @@ sub printbasketgrouppdf{ ); my $pdf = printpdf($basketgroup, $bookseller, $baskets, \%orders, $bookseller->tax_rate // C4::Context->preference("gist")) || die "pdf generation failed"; print $pdf; - } sub generate_edifact_orders { @@ -232,104 +180,60 @@ sub generate_edifact_orders { return; } -my $op = $input->param('op') || 'display'; # possible values of $op : -# - add : adds a new basketgroup, or edit an open basketgroup, or display a closed basketgroup # - mod_basket : modify an individual basket of the basketgroup -# - closeandprint : close and print an closed basketgroup in pdf. called by clicking on "Close and print" button in closed basketgroups list -# - print : print a closed basketgroup. called by clicking on "Print" button in closed basketgroups list +# - closeandprint : close and print an closed basketgroup in pdf. called by +# clicking on "Close and print" button in closed basketgroups list +# - print : print a closed basketgroup. called by clicking on "Print" button in +# closed basketgroups list # - ediprint : generate edi order messages for the baskets in the group -# - export : export in CSV a closed basketgroup. called by clicking on "Export" button in closed basketgroups list -# - delete : delete an open basketgroup. called by clicking on "Delete" button in open basketgroups list -# - reopen : reopen a closed basketgroup. called by clicking on "Reopen" button in closed basketgroup list -# - attachbasket : save a modified basketgroup, or creates a new basketgroup when a basket is closed. called from basket page -# - display : display the list of all basketgroups for a vendor +# - export : export in CSV a closed basketgroup. called by clicking on "Export" +# button in closed basketgroups list +# - delete : delete an open basketgroup. called by clicking on "Delete" button +# in open basketgroups list +# - reopen : reopen a closed basketgroup. called by clicking on "Reopen" button +# in closed basketgroup list +# - attachbasket : save a modified basketgroup, or creates a new basketgroup +# when a basket is closed. called from basket page +my $op = $input->param('op'); +my $basketgroupid = $input->param('basketgroupid'); my $booksellerid = $input->param('booksellerid'); -$template->param(booksellerid => $booksellerid); -my $bookseller = Koha::Acquisition::Booksellers->find( $booksellerid ); + +my $basketgroup; +my $bookseller; +if ($basketgroupid) { + $basketgroup = Koha::Acquisition::BasketGroups->find($basketgroupid); + $bookseller = $basketgroup->vendor; +} elsif ($booksellerid) { + $bookseller = Koha::Acquisition::Booksellers->find($booksellerid); +} my $schema = Koha::Database->new()->schema(); my $rs = $schema->resultset('VendorEdiAccount')->search( { vendor_id => $booksellerid, } ); $template->param( ediaccount => ($rs->count > 0)); -if ( $op eq "add" ) { -# -# if no param('basketgroupid') is not defined, adds a new basketgroup -# else, edit (if it is open) or display (if it is close) the basketgroup basketgroupid -# the template will know if basketgroup must be displayed or edited, depending on the value of closed key -# - my $bookseller = Koha::Acquisition::Booksellers->find( $booksellerid ); - my $basketgroupid = $input->param('basketgroupid'); - my $billingplace; - my $deliveryplace; - my $freedeliveryplace; - if ( $basketgroupid ) { - # Get the selected baskets in the basketgroup to display them - my $selecteds = GetBasketsByBasketgroup($basketgroupid); - foreach my $basket(@{$selecteds}){ - $basket->{total} = BasketTotal($basket->{basketno}, $bookseller); - } - $template->param(basketgroupid => $basketgroupid, - selectedbaskets => $selecteds); - - # Get general informations about the basket group to prefill the form - my $basketgroup = GetBasketgroup($basketgroupid); - $template->param( - name => $basketgroup->{name}, - deliverycomment => $basketgroup->{deliverycomment}, - freedeliveryplace => $basketgroup->{freedeliveryplace}, - ); - $billingplace = $basketgroup->{billingplace}; - $deliveryplace = $basketgroup->{deliveryplace}; - $freedeliveryplace = $basketgroup->{freedeliveryplace}; - $template->param( closedbg => ($basketgroup ->{'closed'}) ? 1 : 0); - } else { - $template->param( closedbg => 0); - } - # determine default billing and delivery places depending on librarian homebranch and existing basketgroup data - my $patron = Koha::Patrons->find( $loggedinuser ); # FIXME Not needed if billingplace and deliveryplace are set - $billingplace = $billingplace || $patron->branchcode; - $deliveryplace = $deliveryplace || $patron->branchcode; - - $template->param( billingplace => $billingplace ); - $template->param( deliveryplace => $deliveryplace ); - $template->param( booksellerid => $booksellerid ); - - # the template will display a unique basketgroup - $template->param(grouping => 1); - my $basketgroups = &GetBasketgroups($booksellerid); - my $baskets = &GetBasketsByBookseller($booksellerid); - displaybasketgroups($basketgroups, $bookseller, $baskets); -} elsif ($op eq 'mod_basket') { -# -# edit an individual basket contained in this basketgroup -# - my $basketno=$input->param('basketno'); - my $basketgroupid=$input->param('basketgroupid'); - ModBasket( { basketno => $basketno, - basketgroupid => $basketgroupid } ); - print $input->redirect("basket.pl?basketno=" . $basketno); +if ($op eq 'mod_basket') { + # edit an individual basket contained in this basketgroup + + my $basketno=$input->param('basketno'); + ModBasket( { basketno => $basketno, + basketgroupid => $basketgroupid } ); + print $input->redirect("basket.pl?basketno=" . $basketno); } elsif ( $op eq 'closeandprint') { -# -# close an open basketgroup and generates a pdf -# - my $basketgroupid = $input->param('basketgroupid'); + # close an open basketgroup and generates a pdf + CloseBasketgroup($basketgroupid); printbasketgrouppdf($basketgroupid); exit; }elsif ($op eq 'print'){ -# -# print a closed basketgroup -# - my $basketgroupid = $input->param('basketgroupid'); + # print a closed basketgroup + printbasketgrouppdf($basketgroupid); exit; }elsif ( $op eq "export" ) { -# -# export a closed basketgroup in csv -# - my $basketgroupid = $input->param('basketgroupid'); + # export a closed basketgroup in csv + print $input->header( -type => 'text/csv', -attachment => 'basketgroup' . $basketgroupid . '.csv', @@ -337,29 +241,29 @@ if ( $op eq "add" ) { print GetBasketGroupAsCSV( $basketgroupid, $input ); exit; }elsif( $op eq "delete"){ -# -# delete an closed basketgroup -# - my $basketgroupid = $input->param('basketgroupid'); + # delete an closed basketgroup + DelBasketgroup($basketgroupid); - print $input->redirect('/cgi-bin/koha/acqui/basketgroup.pl?booksellerid=' . $booksellerid.'&listclosed=1'); + print $input->redirect('/cgi-bin/koha/acqui/basketgroups.pl?booksellerid=' . $bookseller->id); + exit; }elsif ( $op eq 'reopen'){ -# -# reopen a closed basketgroup -# - my $basketgroupid = $input->param('basketgroupid'); - my $booksellerid = $input->param('booksellerid'); + # reopen a closed basketgroup + ReOpenBasketgroup($basketgroupid); - my $redirectpath = ((defined $input->param('mode'))&& ($input->param('mode') eq 'singlebg')) ?'/cgi-bin/koha/acqui/basketgroup.pl?op=add&basketgroupid='.$basketgroupid.'&booksellerid='.$booksellerid : '/cgi-bin/koha/acqui/basketgroup.pl?booksellerid=' .$booksellerid.'&listclosed=1'; + my $redirectpath; + my $mode = $input->param('mode'); + if (defined $mode && $mode eq 'singlebg') { + $redirectpath = '/cgi-bin/koha/acqui/basketgroup.pl?op=add&basketgroupid='.$basketgroupid.'&booksellerid='.$bookseller->id; + } else { + $redirectpath = '/cgi-bin/koha/acqui/basketgroups.pl?booksellerid=' .$bookseller->id; + } print $input->redirect($redirectpath); + exit; } elsif ( $op eq 'attachbasket') { -# -# save a modified basketgroup, or creates a new basketgroup when a basket is closed. called from basket page -# - # Getting parameters + # save a modified basketgroup, or creates a new basketgroup when a basket is closed. called from basket page + my $basketgroup = {}; my @baskets = $input->multi_param('basket'); - my $basketgroupid = $input->param('basketgroupid'); my $basketgroupname = $input->param('basketgroupname'); my $booksellerid = $input->param('booksellerid'); my $billingplace = $input->param('billingplace'); @@ -368,7 +272,7 @@ if ( $op eq "add" ) { my $deliverycomment = $input->param('deliverycomment'); my $closedbg = $input->param('closedbg') ? 1 : 0; if ($basketgroupid) { - # If we have a basketgroupid we edit the basketgroup + # If we have a basketgroupid we edit the basketgroup $basketgroup = { name => $basketgroupname, id => $basketgroupid, @@ -380,14 +284,11 @@ if ( $op eq "add" ) { closed => $closedbg, }; ModBasketgroup($basketgroup); - if($closedbg){ -# FIXME - } - }else{ - # we create a new basketgroup (with a closed basket) + } else { + # we create a new basketgroup (with a closed basket) $basketgroup = { name => $basketgroupname, - booksellerid => $booksellerid, + booksellerid => $bookseller->id, basketlist => \@baskets, billingplace => $billingplace, deliveryplace => $deliveryplace, @@ -397,31 +298,31 @@ if ( $op eq "add" ) { }; $basketgroupid = NewBasketgroup($basketgroup); } - my $redirectpath = ((defined $input->param('mode')) && ($input->param('mode') eq 'singlebg')) ?'/cgi-bin/koha/acqui/basketgroup.pl?op=add&basketgroupid='.$basketgroupid.'&booksellerid='.$booksellerid : '/cgi-bin/koha/acqui/basketgroup.pl?booksellerid=' . $booksellerid; - $redirectpath .= "&listclosed=1" if $closedbg ; - print $input->redirect($redirectpath ); - + my $redirectpath; + my $mode = $input->param('mode'); + if (defined $mode && $mode eq 'singlebg') { + $redirectpath = '/cgi-bin/koha/acqui/basketgroup.pl?op=add&basketgroupid='.$basketgroupid.'&booksellerid='.$booksellerid; + } else { + $redirectpath = '/cgi-bin/koha/acqui/basketgroups.pl?booksellerid=' . $booksellerid; + } + print $input->redirect($redirectpath); + exit; } elsif ( $op eq 'ediprint') { - my $basketgroupid = $input->param('basketgroupid'); if ($template->param( 'ediaccount' )) { generate_edifact_orders( $basketgroupid ); exit; } else { $template->param('NoEDIMessage' => 1); - my $basketgroups = &GetBasketgroups($booksellerid); - my $bookseller = Koha::Acquisition::Booksellers->find( $booksellerid ); - my $baskets = &GetBasketsByBookseller($booksellerid); - - displaybasketgroups($basketgroups, $bookseller, $baskets); } -}else{ -# no param : display the list of all basketgroups for a given vendor - my $basketgroups = &GetBasketgroups($booksellerid); - my $bookseller = Koha::Acquisition::Booksellers->find( $booksellerid ); - my $baskets = &GetBasketsByBookseller($booksellerid); - - displaybasketgroups($basketgroups, $bookseller, $baskets); } -$template->param(listclosed => ((defined $input->param('listclosed')) && ($input->param('listclosed') eq '1'))? 1:0 ); -#prolly won't use all these, maybe just use print, the rest can be done inside validate + +my $borrower = Koha::Patrons->find( $loggedinuser ); +$template->param( + bookseller => $bookseller, + basketgroup => $basketgroup, + billingplace => $basketgroup ? $basketgroup->billingplace : $borrower->branchcode, + deliveryplace => $basketgroup ? $basketgroup->deliveryplace : $borrower->branchcode, + baskets => [ Koha::Acquisition::Baskets->search({booksellerid => $bookseller->id, basketgroupid => undef}) ], +); + output_html_with_http_headers $input, $cookie, $template->output; --- a/acqui/basketgroups.pl +++ a/acqui/basketgroups.pl @@ -0,0 +1,52 @@ +#!/usr/bin/perl + +# This file is part of Koha. +# +# Koha is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# Koha is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Koha; if not, see . + +use Modern::Perl; + +use CGI qw(-utf8); + +use C4::Auth; +use C4::Output; + +use Koha::Acquisition::BasketGroups; +use Koha::Acquisition::Booksellers; + +my $cgi = new CGI; + +my ($template, $loggedinuser, $cookie) = get_template_and_user({ + template_name => 'acqui/basketgroups.tt', + query => $cgi, + type => 'intranet', + flagsrequired => { acquisition => 'group_manage' }, +}); + +my $booksellerid = $cgi->param('booksellerid'); + +my $params = {}; +if ($booksellerid) { + $params->{booksellerid} = $booksellerid; + my $bookseller = Koha::Acquisition::Booksellers->find($booksellerid); + $template->param(bookseller => $bookseller); +} + +my @basketgroups = Koha::Acquisition::BasketGroups->search($params); + +$template->param( + basketgroups => \@basketgroups, +); + +output_html_with_http_headers $cgi, $cookie, $template->output; --- a/koha-tmpl/intranet-tmpl/prog/en/includes/acquisitions-menu.inc +++ a/koha-tmpl/intranet-tmpl/prog/en/includes/acquisitions-menu.inc @@ -3,6 +3,9 @@
Acquisitions