diff --git a/C4/Acquisition.pm b/C4/Acquisition.pm index db6c45acb6..19ecb6b51f 100644 --- a/C4/Acquisition.pm +++ b/C4/Acquisition.pm @@ -186,8 +186,8 @@ sub GetBasket { =head3 NewBasket - $basket = &NewBasket( $booksellerid, $authorizedby, $basketname, - $basketnote, $basketbooksellernote, $basketcontractnumber, $deliveryplace, $billingplace ); + $basket = &NewBasket( $booksellerid, $authorizedby, $basketname, + $basketnote, $basketbooksellernote, $basketcontractnumber, $deliveryplace, $billingplace, $is_standing ); Create a new basket in aqbasket table @@ -206,7 +206,7 @@ The other parameters are optional, see ModBasketHeader for more info on them. sub NewBasket { my ( $booksellerid, $authorisedby, $basketname, $basketnote, $basketbooksellernote, $basketcontractnumber, $deliveryplace, - $billingplace ) = @_; + $billingplace, $is_standing ) = @_; my $dbh = C4::Context->dbh; my $query = 'INSERT INTO aqbasket (creationdate,booksellerid,authorisedby) ' @@ -218,7 +218,7 @@ sub NewBasket { $basketnote ||= q{}; $basketbooksellernote ||= q{}; ModBasketHeader( $basket, $basketname, $basketnote, $basketbooksellernote, - $basketcontractnumber, $booksellerid, $deliveryplace, $billingplace ); + $basketcontractnumber, $booksellerid, $deliveryplace, $billingplace, $is_standing ); return $basket; } @@ -531,21 +531,23 @@ Modifies a basket's header. =item C<$billingplace> is the "billingplace" field in the aqbasket table. +=item C<$is_standing> is the "is_standing" field in the aqbasket table. + =back =cut sub ModBasketHeader { - my ($basketno, $basketname, $note, $booksellernote, $contractnumber, $booksellerid, $deliveryplace, $billingplace) = @_; + my ($basketno, $basketname, $note, $booksellernote, $contractnumber, $booksellerid, $deliveryplace, $billingplace, $is_standing) = @_; my $query = qq{ UPDATE aqbasket - SET basketname=?, note=?, booksellernote=?, booksellerid=?, deliveryplace=?, billingplace=? + SET basketname=?, note=?, booksellernote=?, booksellerid=?, deliveryplace=?, billingplace=?, is_standing=? WHERE basketno=? }; my $dbh = C4::Context->dbh; my $sth = $dbh->prepare($query); - $sth->execute($basketname, $note, $booksellernote, $booksellerid, $deliveryplace, $billingplace, $basketno); + $sth->execute($basketname, $note, $booksellernote, $booksellerid, $deliveryplace, $billingplace, $is_standing, $basketno); if ( $contractnumber ) { my $query2 ="UPDATE aqbasket SET contractnumber=? WHERE basketno=?"; @@ -1385,7 +1387,7 @@ sub ModReceiveOrder { } my $result_set = $dbh->selectall_arrayref( -q{SELECT * FROM aqorders WHERE biblionumber=? AND aqorders.ordernumber=?}, +q{SELECT *, aqbasket.is_standing FROM aqorders LEFT JOIN aqbasket USING (basketno) WHERE biblionumber=? AND aqorders.ordernumber=?}, { Slice => {} }, $biblionumber, $ordernumber ); @@ -1393,7 +1395,7 @@ q{SELECT * FROM aqorders WHERE biblionumber=? AND aqorders.ordernumber=?}, my $order = $result_set->[0]; my $new_ordernumber = $ordernumber; - if ( $order->{quantity} > $quantrec ) { + if ( $order->{is_standing} || $order->{quantity} > $quantrec ) { # Split order line in two parts: the first is the original order line # without received items (the quantity is decreased), # the second part is a new order line with quantity=quantityrec @@ -1408,7 +1410,7 @@ q{SELECT * FROM aqorders WHERE biblionumber=? AND aqorders.ordernumber=?}, my $sth = $dbh->prepare($query); $sth->execute( - $order->{quantity} - $quantrec, + ( $order->{quantity} < $quantrec ? 0 : ( $order->{quantity} - $quantrec ) ), ( defined $order_internalnote ? $order_internalnote : () ), ( defined $order_vendornote ? $order_vendornote : () ), $ordernumber @@ -1684,10 +1686,20 @@ sub SearchOrders { }; if ( $pending or $ordered ) { - $query .= q{ AND (quantity > quantityreceived OR quantityreceived is NULL)}; - } - if ( $ordered ) { - $query .= q{ AND aqorders.orderstatus IN ( "ordered", "partial" )}; + $query .= q{ + AND ( + ( aqbasket.is_standing AND aqorders.orderstatus IN ( "new", "ordered", "partial" ) ) + OR ( + ( quantity > quantityreceived OR quantityreceived is NULL ) + }; + + if ( $ordered ) { + $query .= q{ AND aqorders.orderstatus IN ( "ordered", "partial" )}; + } + $query .= q{ + ) + ) + }; } my $userenv = C4::Context->userenv; diff --git a/Koha/Acquisition/Order.pm b/Koha/Acquisition/Order.pm index 15b9867023..de0c49d904 100644 --- a/Koha/Acquisition/Order.pm +++ b/Koha/Acquisition/Order.pm @@ -27,16 +27,20 @@ sub insert { my ($self) = @_; # if these parameters are missing, we can't continue - for my $key (qw( basketno quantity biblionumber budget_id )) { + for my $key (qw( basketno biblionumber budget_id )) { croak "Cannot insert order: Mandatory parameter $key is missing" unless $self->{$key}; } + my $schema = Koha::Database->new->schema; + if ( !$self->{quantity} && !$schema->resultset('Aqbasket')->find( $self->{basketno} )->is_standing ) { + croak "Cannot insert order: Quantity is mandatory for non-standing orders"; + } + $self->{quantityreceived} ||= 0; $self->{entrydate} ||= output_pref( { dt => dt_from_string, dateformat => 'iso' } ); - my $schema = Koha::Database->new->schema; my @columns = $schema->source('Aqorder')->columns; $self->{ordernumber} ||= undef; diff --git a/Koha/Schema/Result/Aqbasket.pm b/Koha/Schema/Result/Aqbasket.pm index 52cc708041..e2fb8d7bf2 100644 --- a/Koha/Schema/Result/Aqbasket.pm +++ b/Koha/Schema/Result/Aqbasket.pm @@ -106,6 +106,12 @@ __PACKAGE__->table("aqbasket"); is_nullable: 1 size: 10 +=head2 is_standing + + data_type: 'tinyint' + default_value: 0 + is_nullable: 0 + =cut __PACKAGE__->add_columns( @@ -142,6 +148,8 @@ __PACKAGE__->add_columns( { data_type => "varchar", is_nullable => 1, size => 10 }, "branch", { data_type => "varchar", is_foreign_key => 1, is_nullable => 1, size => 10 }, + "is_standing", + { data_type => "tinyint", default_value => 0, is_nullable => 0 }, ); =head1 PRIMARY KEY @@ -289,8 +297,8 @@ Composing rels: L -> borrowernumber __PACKAGE__->many_to_many("borrowernumbers", "aqbasketusers", "borrowernumber"); -# Created by DBIx::Class::Schema::Loader v0.07033 @ 2014-09-02 11:37:47 -# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:tsMzwP7eofOR27sfZSTqFQ +# Created by DBIx::Class::Schema::Loader v0.07042 @ 2016-01-14 16:28:06 +# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:CuP/8SFJOD4h4XZf7AdeiA # You can replace this text with custom content, and it will be preserved on regeneration diff --git a/acqui/addorder.pl b/acqui/addorder.pl index 1e60f79d5a..70cb36c92d 100755 --- a/acqui/addorder.pl +++ b/acqui/addorder.pl @@ -228,12 +228,15 @@ $orderinfo->{'list_price'} ||= 0; $orderinfo->{'uncertainprice'} ||= 0; $orderinfo->{subscriptionid} ||= undef; +my $basketno=$$orderinfo{basketno}; +my $basket = GetBasket($basketno); + my $user = $input->remote_user; # create, modify or delete biblio # create if $quantity>0 and $existing='no' # modify if $quantity>0 and $existing='yes' -if ( $orderinfo->{quantity} ne '0' ) { +if ( $basket->{is_standing} || $orderinfo->{quantity} ne '0' ) { #TODO:check to see if biblio exists unless ( $$orderinfo{biblionumber} ) { #if it doesn't create it @@ -319,7 +322,6 @@ if ( $orderinfo->{quantity} ne '0' ) { } -my $basketno=$$orderinfo{basketno}; my $booksellerid=$$orderinfo{booksellerid}; if (my $import_batch_id=$$orderinfo{import_batch_id}) { print $input->redirect("/cgi-bin/koha/acqui/addorderiso2709.pl?import_batch_id=$import_batch_id&basketno=$basketno&booksellerid=$booksellerid"); diff --git a/acqui/basket.pl b/acqui/basket.pl index 0a0cbda6a3..d1f37e6c34 100755 --- a/acqui/basket.pl +++ b/acqui/basket.pl @@ -366,6 +366,7 @@ elsif ( $op eq 'ediorder' ) { $template->param( basketno => $basketno, + basket => $basket, basketname => $basket->{'basketname'}, basketbranchname => C4::Branch::GetBranchName($basket->{branch}), basketnote => $basket->{note}, @@ -380,6 +381,7 @@ elsif ( $op eq 'ediorder' ) { users => \@basketusers, closedate => $basket->{closedate}, estimateddeliverydate=> $estimateddeliverydate, + is_standing => $basket->{is_standing}, deliveryplace => C4::Branch::GetBranchName( $basket->{deliveryplace} ), billingplace => C4::Branch::GetBranchName( $basket->{billingplace} ), active => $bookseller->{'active'}, @@ -397,7 +399,12 @@ elsif ( $op eq 'ediorder' ) { basketgroups => $basketgroups, basketgroup => $basketgroup, grouped => $basket->{basketgroupid}, - unclosable => @orders ? 0 : 1, + # The double negatives and booleans here mean: + # "A basket cannot be closed if there are no orders in it or it's a standing order basket." + # + # (The template has another implicit restriction that the order cannot be closed if there + # are any orders with uncertain prices.) + unclosable => @orders ? $basket->{is_standing} : 1, has_budgets => $has_budgets, duplinbatch => $duplinbatch, ); @@ -410,10 +417,12 @@ sub get_order_infos { if ( !defined $order->{quantityreceived} ) { $order->{quantityreceived} = 0; } - my $budget = GetBudget( $order->{'budget_id'} ); + my $budget = GetBudget($order->{budget_id}); + my $basket = GetBasket($order->{basketno}); my %line = %{ $order }; - $line{order_received} = ( $qty == $order->{'quantityreceived'} ); + # Don't show unreceived standing orders as received + $line{order_received} = ( $qty == $order->{'quantityreceived'} && ( $basket->{is_standing} ? $qty : 1 ) ); $line{basketno} = $basketno; $line{budget_name} = $budget->{budget_name}; @@ -463,7 +472,6 @@ sub get_order_infos { foreach my $key (qw(transferred_from transferred_to)) { if ($line{$key}) { my $order = GetOrder($line{$key}); - my $basket = GetBasket($order->{basketno}); my $bookseller = Koha::Acquisition::Bookseller->fetch({ id => $basket->{booksellerid} }); $line{$key} = { order => $order, diff --git a/acqui/basketheader.pl b/acqui/basketheader.pl index a4ef0b9fea..051e148000 100755 --- a/acqui/basketheader.pl +++ b/acqui/basketheader.pl @@ -148,6 +148,7 @@ if ( $op eq 'add_form' ) { $input->param('basketbooksellerid'), $input->param('deliveryplace'), $input->param('billingplace'), + $input->param('is_standing') ? 1 : undef, ); } else { #New basket $basketno = NewBasket( @@ -159,6 +160,7 @@ if ( $op eq 'add_form' ) { $input->param('basketcontractnumber') || undef, $input->param('deliveryplace'), $input->param('billingplace'), + $input->param('is_standing') ? 1 : undef, ); } print $input->redirect('basket.pl?basketno='.$basketno); diff --git a/acqui/neworderempty.pl b/acqui/neworderempty.pl index 4fdf33fdc1..da5acd5cdd 100755 --- a/acqui/neworderempty.pl +++ b/acqui/neworderempty.pl @@ -324,6 +324,7 @@ $template->param( ordernumber => $ordernumber, # basket informations basketno => $basketno, + basket => $basket, basketname => $basket->{'basketname'}, basketnote => $basket->{'note'}, booksellerid => $basket->{'booksellerid'}, diff --git a/installer/data/mysql/atomicupdate/bug_15531-add_is_standing_to_aqbasket.sql b/installer/data/mysql/atomicupdate/bug_15531-add_is_standing_to_aqbasket.sql new file mode 100644 index 0000000000..69d8fabd41 --- /dev/null +++ b/installer/data/mysql/atomicupdate/bug_15531-add_is_standing_to_aqbasket.sql @@ -0,0 +1 @@ +ALTER TABLE aqbasket ADD COLUMN is_standing TINYINT(1) NOT NULL DEFAULT 0; diff --git a/installer/data/mysql/kohastructure.sql b/installer/data/mysql/kohastructure.sql index ca73390068..a4d6c39522 100644 --- a/installer/data/mysql/kohastructure.sql +++ b/installer/data/mysql/kohastructure.sql @@ -2935,6 +2935,7 @@ CREATE TABLE `aqbasket` ( -- stores data about baskets in acquisitions `deliveryplace` varchar(10) default NULL, -- basket delivery place `billingplace` varchar(10) default NULL, -- basket billing place branch varchar(10) default NULL, -- basket branch + is_standing TINYINT(1) NOT NULL DEFAULT 0, -- orders in this basket are standing PRIMARY KEY (`basketno`), KEY `booksellerid` (`booksellerid`), KEY `basketgroupid` (`basketgroupid`), diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/basket.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/basket.tt index 2a23ad6d63..12de1ed1f9 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/basket.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/basket.tt @@ -319,6 +319,9 @@ [% IF ( creationdate ) %]