X-Git-Url: http://git.rot13.org/?a=blobdiff_plain;f=C4%2FAcquisition.pm;h=1ad7a2361c894a2fe5bdc5f8b6cfb4d8a64564e2;hb=dbcd0511e7580cce996965d54982bfcce7c97b14;hp=346fb4546cb789f8ec70aa3712f68c65daba3565;hpb=94513d0739757f0c5db4b7d1040aaae40622a60e;p=koha.git diff --git a/C4/Acquisition.pm b/C4/Acquisition.pm index 346fb4546c..1ad7a2361c 100644 --- a/C4/Acquisition.pm +++ b/C4/Acquisition.pm @@ -28,9 +28,11 @@ use C4::Contract; use C4::Debug; use C4::Templates qw(gettemplate); use Koha::DateUtils qw( dt_from_string output_pref ); -use Koha::Acquisition::Order; +use Koha::Acquisition::Baskets; use Koha::Acquisition::Booksellers; +use Koha::Acquisition::Orders; use Koha::Biblios; +use Koha::Exceptions; use Koha::Items; use Koha::Number::Price; use Koha::Libraries; @@ -83,8 +85,6 @@ BEGIN { &DelInvoice &MergeInvoices - &GetItemnumbersFromOrder - &AddClaim &GetBiblioCountByBasketno @@ -120,28 +120,6 @@ sub GetOrderFromItemnumber { } -# Returns the itemnumber(s) associated with the ordernumber given in parameter -sub GetItemnumbersFromOrder { - my ($ordernumber) = @_; - my $dbh = C4::Context->dbh; - my $query = "SELECT itemnumber FROM aqorders_items WHERE ordernumber=?"; - my $sth = $dbh->prepare($query); - $sth->execute($ordernumber); - my @tab; - - while (my $order = $sth->fetchrow_hashref) { - push @tab, $order->{'itemnumber'}; - } - - return @tab; - -} - - - - - - =head1 NAME C4::Acquisition - Koha functions for dealing with orders and acquisitions @@ -190,7 +168,7 @@ sub GetBasket { =head3 NewBasket $basket = &NewBasket( $booksellerid, $authorizedby, $basketname, - $basketnote, $basketbooksellernote, $basketcontractnumber, $deliveryplace, $billingplace, $is_standing ); + $basketnote, $basketbooksellernote, $basketcontractnumber, $deliveryplace, $billingplace, $is_standing, $create_items ); Create a new basket in aqbasket table @@ -209,7 +187,7 @@ The other parameters are optional, see ModBasketHeader for more info on them. sub NewBasket { my ( $booksellerid, $authorisedby, $basketname, $basketnote, $basketbooksellernote, $basketcontractnumber, $deliveryplace, - $billingplace, $is_standing ) = @_; + $billingplace, $is_standing, $create_items ) = @_; my $dbh = C4::Context->dbh; my $query = 'INSERT INTO aqbasket (creationdate,booksellerid,authorisedby) ' @@ -221,7 +199,7 @@ sub NewBasket { $basketnote ||= q{}; $basketbooksellernote ||= q{}; ModBasketHeader( $basket, $basketname, $basketnote, $basketbooksellernote, - $basketcontractnumber, $booksellerid, $deliveryplace, $billingplace, $is_standing ); + $basketcontractnumber, $booksellerid, $deliveryplace, $billingplace, $is_standing, $create_items ); return $basket; } @@ -240,8 +218,10 @@ sub CloseBasket { my $dbh = C4::Context->dbh; $dbh->do('UPDATE aqbasket SET closedate=now() WHERE basketno=?', {}, $basketno ); - $dbh->do( q{UPDATE aqorders SET orderstatus = 'ordered' WHERE basketno = ? AND orderstatus != 'complete'}, - {}, $basketno); + $dbh->do( +q{UPDATE aqorders SET orderstatus = 'ordered' WHERE basketno = ? AND orderstatus NOT IN ( 'complete', 'cancelled')}, + {}, $basketno + ); return; } @@ -262,7 +242,7 @@ sub ReopenBasket { UPDATE aqorders SET orderstatus = 'new' WHERE basketno = ? - AND orderstatus != 'complete' + AND orderstatus NOT IN ( 'complete', 'cancelled' ) }, {}, $basketno); return; } @@ -291,7 +271,7 @@ sub GetBasketAsCSV { my @rows; if ($csv_profile_id) { my $csv_profile = Koha::CsvProfiles->find( $csv_profile_id ); - die "There is no valid csv profile given" unless $csv_profile; + Koha::Exceptions::ObjectNotFound->throw( 'There is no valid csv profile given') unless $csv_profile; my $csv = Text::CSV_XS->new({'quote_char'=>'"','escape_char'=>'"','sep_char'=>$csv_profile->csv_separator,'binary'=>1}); my $csv_profile_content = $csv_profile->content; @@ -314,20 +294,13 @@ sub GetBasketAsCSV { } for my $order (@orders) { my @row; - my $bd = GetBiblioData( $order->{'biblionumber'} ); - my @biblioitems = GetBiblioItemByBiblioNumber( $order->{'biblionumber'}); - for my $biblioitem (@biblioitems) { - if ( $biblioitem->{isbn} - and $order->{isbn} - and $biblioitem->{isbn} eq $order->{isbn} ) - { - $order = { %$order, %$biblioitem }; - } - } + my $biblio = Koha::Biblios->find( $order->{biblionumber} ); + my $biblioitem = $biblio->biblioitem; + $order = { %$order, %{ $biblioitem->unblessed } }; if ($contract) { $order = {%$order, %$contract}; } - $order = {%$order, %$basket, %$bd}; + $order = {%$order, %$basket, %{ $biblio->unblessed }}; for my $field (@fields) { push @row, $order->{$field}; } @@ -343,17 +316,18 @@ sub GetBasketAsCSV { } else { foreach my $order (@orders) { - my $bd = GetBiblioData( $order->{'biblionumber'} ); + my $biblio = Koha::Biblios->find( $order->{biblionumber} ); + my $biblioitem = $biblio->biblioitem; my $row = { contractname => $contract->{'contractname'}, ordernumber => $order->{'ordernumber'}, entrydate => $order->{'entrydate'}, isbn => $order->{'isbn'}, - author => $bd->{'author'}, - title => $bd->{'title'}, - publicationyear => $bd->{'publicationyear'}, - publishercode => $bd->{'publishercode'}, - collectiontitle => $bd->{'collectiontitle'}, + author => $biblio->author, + title => $biblio->title, + publicationyear => $biblioitem->publicationyear, + publishercode => $biblioitem->publishercode, + collectiontitle => $biblioitem->collectiontitle, notes => $order->{'order_vendornote'}, quantity => $order->{'quantity'}, rrp => $order->{'rrp'}, @@ -412,16 +386,17 @@ sub GetBasketGroupAsCSV { my $basketgroup = GetBasketgroup( $$basket{basketgroupid} ); foreach my $order (@orders) { - my $bd = GetBiblioData( $order->{'biblionumber'} ); + my $biblio = Koha::Biblios->find( $order->{biblionumber} ); + my $biblioitem = $biblio->biblioitem; my $row = { clientnumber => $bookseller->accountnumber, basketname => $basket->{basketname}, ordernumber => $order->{ordernumber}, - author => $bd->{author}, - title => $bd->{title}, - publishercode => $bd->{publishercode}, - publicationyear => $bd->{publicationyear}, - collectiontitle => $bd->{collectiontitle}, + author => $biblio->author, + title => $biblio->title, + publishercode => $biblioitem->publishercode, + publicationyear => $biblioitem->publicationyear, + collectiontitle => $biblioitem->collectiontitle, isbn => $order->{isbn}, quantity => $order->{quantity}, rrp_tax_included => $order->{rrp_tax_included}, @@ -601,21 +576,26 @@ Modifies a basket's header. =item C<$is_standing> is the "is_standing" field in the aqbasket table. +=item C<$create_items> should be set to 'ordering', 'receiving' or 'cataloguing' (or undef, in which +case the AcqCreateItem syspref takes precedence). + =back =cut sub ModBasketHeader { - my ($basketno, $basketname, $note, $booksellernote, $contractnumber, $booksellerid, $deliveryplace, $billingplace, $is_standing) = @_; + my ($basketno, $basketname, $note, $booksellernote, $contractnumber, $booksellerid, $deliveryplace, $billingplace, $is_standing, $create_items) = @_; + + $is_standing ||= 0; my $query = qq{ UPDATE aqbasket - SET basketname=?, note=?, booksellernote=?, booksellerid=?, deliveryplace=?, billingplace=?, is_standing=? + SET basketname=?, note=?, booksellernote=?, booksellerid=?, deliveryplace=?, billingplace=?, is_standing=?, create_items=? WHERE basketno=? }; my $dbh = C4::Context->dbh; my $sth = $dbh->prepare($query); - $sth->execute($basketname, $note, $booksellernote, $booksellerid, $deliveryplace, $billingplace, $is_standing, $basketno); + $sth->execute($basketname, $note, $booksellernote, $booksellerid, $deliveryplace, $billingplace, $is_standing, $create_items || undef, $basketno); if ( $contractnumber ) { my $query2 ="UPDATE aqbasket SET contractnumber=? WHERE basketno=?"; @@ -690,7 +670,7 @@ sub GetBasketsInfosByBookseller { my $dbh = C4::Context->dbh; my $query = q{ - SELECT aqbasket.*, + SELECT aqbasket.basketno, aqbasket.basketname, aqbasket.note, aqbasket.booksellernote, aqbasket.contractnumber, aqbasket.creationdate, aqbasket.closedate, aqbasket.booksellerid, aqbasket.authorisedby, aqbasket.booksellerinvoicenumber, aqbasket.basketgroupid, aqbasket.deliveryplace, aqbasket.billingplace, aqbasket.branch, aqbasket.is_standing, aqbasket.create_items, SUM(aqorders.quantity) AS total_items, SUM( IF ( aqorders.orderstatus = 'cancelled', aqorders.quantity, 0 ) @@ -698,7 +678,7 @@ sub GetBasketsInfosByBookseller { COUNT(DISTINCT aqorders.biblionumber) AS total_biblios, SUM( IF(aqorders.datereceived IS NULL - AND aqorders.datecancellationprinted IS NULL + AND (aqorders.datecancellationprinted IS NULL OR aqorders.datecancellationprinted='0000-00-00') , aqorders.quantity , 0) ) AS expected_items @@ -706,10 +686,18 @@ sub GetBasketsInfosByBookseller { LEFT JOIN aqorders ON aqorders.basketno = aqbasket.basketno WHERE booksellerid = ?}; + $query.=" GROUP BY aqbasket.basketno, aqbasket.basketname, aqbasket.note, aqbasket.booksellernote, aqbasket.contractnumber, aqbasket.creationdate, aqbasket.closedate, aqbasket.booksellerid, aqbasket.authorisedby, aqbasket.booksellerinvoicenumber, aqbasket.basketgroupid, aqbasket.deliveryplace, aqbasket.billingplace, aqbasket.branch, aqbasket.is_standing, aqbasket.create_items"; + unless ( $allbaskets ) { - $query.=" AND (closedate IS NULL OR (aqorders.quantity > aqorders.quantityreceived AND datecancellationprinted IS NULL))"; + # Don't show the basket if it's NOT CLOSED or is FULLY RECEIVED + $query.=" HAVING (closedate IS NULL OR ( + SUM( + IF(aqorders.datereceived IS NULL + AND (aqorders.datecancellationprinted IS NULL OR aqorders.datecancellationprinted='0000-00-00') + , aqorders.quantity + , 0) + ) > 0))" } - $query.=" GROUP BY aqbasket.basketno"; my $sth = $dbh->prepare($query); $sth->execute($supplierid); @@ -1456,16 +1444,19 @@ sub ModReceiveOrder { UPDATE aqorders SET quantity = ?, orderstatus = 'partial'|; - $query .= q|, order_internalnote = ?| if defined $order->{order_internalnote}; $query .= q| WHERE ordernumber = ?|; my $sth = $dbh->prepare($query); $sth->execute( ( $is_standing ? 1 : ($order->{quantity} - $quantrec) ), - ( defined $order->{order_internalnote} ? $order->{order_internalnote} : () ), $order->{ordernumber} ); + if ( not $order->{subscriptionid} && defined $order->{order_internalnote} ) { + $dbh->do(q|UPDATE aqorders + SET order_internalnote = ?|, {}, $order->{order_internalnote}); + } + # Recalculate tax_value $dbh->do(q| UPDATE aqorders @@ -1488,7 +1479,7 @@ sub ModReceiveOrder { $order->{datereceived} = $datereceived; $order->{invoiceid} = $invoice->{invoiceid}; $order->{orderstatus} = 'complete'; - $new_ordernumber = Koha::Acquisition::Order->new($order)->insert->{ordernumber}; + $new_ordernumber = Koha::Acquisition::Order->new($order)->store->ordernumber; # TODO What if the store fails? if ($received_items) { foreach my $itemnumber (@$received_items) { @@ -1505,6 +1496,10 @@ sub ModReceiveOrder { orderstatus = 'complete' |; + $query .= q| + , replacementprice = ? + | if defined $order->{replacementprice}; + $query .= q| , unitprice = ?, unitprice_tax_included = ?, unitprice_tax_excluded = ? | if defined $order->{unitprice}; @@ -1526,6 +1521,10 @@ sub ModReceiveOrder { my $sth = $dbh->prepare( $query ); my @params = ( $quantrec, $datereceived, $invoice->{invoiceid}, ( $budget_id ? $budget_id : $order->{budget_id} ) ); + if ( defined $order->{replacementprice} ) { + push @params, $order->{replacementprice}; + } + if ( defined $order->{unitprice} ) { push @params, $order->{unitprice}, $order->{unitprice_tax_included}, $order->{unitprice_tax_excluded}; } @@ -1589,7 +1588,8 @@ sub CancelReceipt { my $parent_ordernumber = $order->{'parent_ordernumber'}; - my @itemnumbers = GetItemnumbersFromOrder( $ordernumber ); + my $order_obj = Koha::Acquisition::Orders->find( $ordernumber ); # FIXME rewrite all this subroutine using this object + my @itemnumbers = $order_obj->items->get_column('itemnumber'); if($parent_ordernumber == $ordernumber || not $parent_ordernumber) { # The order line has no parent, just mark it as not received @@ -1603,7 +1603,7 @@ sub CancelReceipt { }; $sth = $dbh->prepare($query); $sth->execute(0, undef, undef, $ordernumber); - _cancel_items_receipt( $ordernumber ); + _cancel_items_receipt( $order_obj ); } else { # The order line has a parent, increase parent quantity and delete # the order line. @@ -1650,7 +1650,7 @@ sub CancelReceipt { WHERE ordernumber = ? |, undef, $parent_ordernumber); - _cancel_items_receipt( $ordernumber, $parent_ordernumber ); + _cancel_items_receipt( $order_obj, $parent_ordernumber ); # Delete order line $query = qq{ DELETE FROM aqorders @@ -1661,11 +1661,11 @@ sub CancelReceipt { } - if(C4::Context->preference('AcqCreateItem') eq 'ordering') { + if( $order_obj->basket->effective_create_items eq 'ordering' ) { my @affects = split q{\|}, C4::Context->preference("AcqItemSetSubfieldsWhenReceiptIsCancelled"); if ( @affects ) { for my $in ( @itemnumbers ) { - my $item = Koha::Items->find( $in ); + my $item = Koha::Items->find( $in ); # FIXME We do not need that, we already have Koha::Items from $order_obj->items my $biblio = $item->biblio; my ( $itemfield ) = GetMarcFromKohaField( 'items.itemnumber', $biblio->frameworkcode ); my $item_marc = C4::Items::GetMarcItem( $biblio->biblionumber, $in ); @@ -1684,11 +1684,11 @@ sub CancelReceipt { } sub _cancel_items_receipt { - my ( $ordernumber, $parent_ordernumber ) = @_; - $parent_ordernumber ||= $ordernumber; + my ( $order, $parent_ordernumber ) = @_; + $parent_ordernumber ||= $order->ordernumber; - my @itemnumbers = GetItemnumbersFromOrder($ordernumber); - if(C4::Context->preference('AcqCreateItem') eq 'receiving') { + my $items = $order->items; + if ( $order->basket->effective_create_items eq 'receiving' ) { # Remove items that were created at receipt my $query = qq{ DELETE FROM items, aqorders_items @@ -1697,13 +1697,13 @@ sub _cancel_items_receipt { }; my $dbh = C4::Context->dbh; my $sth = $dbh->prepare($query); - foreach my $itemnumber (@itemnumbers) { - $sth->execute($itemnumber, $itemnumber); + while ( my $item = $items->next ) { + $sth->execute($item->itemnumber, $item->itemnumber); } } else { # Update items - foreach my $itemnumber (@itemnumbers) { - ModItemOrder($itemnumber, $parent_ordernumber); + while ( my $item = $items->next ) { + ModItemOrder($item->itemnumber, $parent_ordernumber); } } } @@ -1907,9 +1907,10 @@ sub DelOrder { } $sth->finish; - my @itemnumbers = GetItemnumbersFromOrder( $ordernumber ); - foreach my $itemnumber (@itemnumbers){ - my $delcheck = C4::Items::DelItemCheck( $bibnum, $itemnumber ); + my $order = Koha::Acquisition::Orders->find($ordernumber); + my $items = $order->items; + while ( my $item = $items->next ) { # Should be moved to Koha::Acquisition::Order->delete + my $delcheck = C4::Items::DelItemCheck( $bibnum, $item->itemnumber ); if($delcheck != 1) { $error->{'delitem'} = 1; @@ -1954,8 +1955,11 @@ sub TransferOrder { return unless ($ordernumber and $basketno); - my $order = GetOrder( $ordernumber ); - return if $order->{datereceived}; + my $order = Koha::Acquisition::Orders->find( $ordernumber ) or return; + return if $order->datereceived; + + $order = $order->unblessed; + my $basket = GetBasket($basketno); return unless $basket; @@ -1974,7 +1978,7 @@ sub TransferOrder { delete $order->{parent_ordernumber}; $order->{'basketno'} = $basketno; - my $newordernumber = Koha::Acquisition::Order->new($order)->insert->{ordernumber}; + my $newordernumber = Koha::Acquisition::Order->new($order)->store->ordernumber; $query = q{ UPDATE aqorders_items @@ -2144,7 +2148,6 @@ sub GetLateOrders { AND aqbasket.closedate IS NOT NULL AND (aqorders.datecancellationprinted IS NULL OR aqorders.datecancellationprinted='0000-00-00') "; - my $having = ""; if ($dbdriver eq "mysql") { $select .= " aqorders.quantity - COALESCE(aqorders.quantityreceived,0) AS quantity, @@ -2155,7 +2158,7 @@ sub GetLateOrders { $from .= " AND (closedate <= DATE_SUB(CAST(now() AS date),INTERVAL ? DAY)) " ; push @query_params, $delay; } - $having = "HAVING quantity <> 0"; + $from .= " AND aqorders.quantity - COALESCE(aqorders.quantityreceived,0) <> 0"; } else { # FIXME: account for IFNULL as above $select .= " @@ -2167,6 +2170,7 @@ sub GetLateOrders { $from .= " AND (closedate <= (CAST(now() AS date) -(INTERVAL ? DAY)) "; push @query_params, $delay; } + $from .= " AND aqorders.quantity <> 0"; } if (defined $supplierid) { $from .= ' AND aqbasket.booksellerid = ? '; @@ -2197,7 +2201,7 @@ sub GetLateOrders { push @query_params, C4::Context->userenv->{branch}; } $from .= " AND orderstatus <> 'cancelled' "; - my $query = "$select $from $having\nORDER BY latesince, basketno, borrowers.branchcode, supplier"; + my $query = "$select $from \nORDER BY latesince, basketno, borrowers.branchcode, supplier"; $debug and print STDERR "GetLateOrders query: $query\nGetLateOrders args: " . join(" ",@query_params); my $sth = $dbh->prepare($query); $sth->execute(@query_params); @@ -2276,12 +2280,30 @@ sub GetHistory { my $ordernumber = $params{ordernumber}; my $search_children_too = $params{search_children_too} || 0; my $created_by = $params{created_by} || []; + my $ordernumbers = $params{ordernumbers} || []; + my $additional_fields = $params{additional_fields} // []; my @order_loop; my $total_qty = 0; my $total_qtyreceived = 0; my $total_price = 0; + #get variation of isbn + my @isbn_params; + my @isbns; + if ($isbn){ + if ( C4::Context->preference("SearchWithISBNVariations") ){ + @isbns = C4::Koha::GetVariationsOfISBN( $isbn ); + foreach my $isb (@isbns){ + push @isbn_params, '?'; + } + } + unless (@isbns){ + push @isbns, $isbn; + push @isbn_params, '?'; + } + } + my $dbh = C4::Context->dbh; my $query =" SELECT @@ -2349,10 +2371,13 @@ sub GetHistory { push @query_params, "%$author%"; } - if ( $isbn ) { - $query .= " AND biblioitems.isbn LIKE ? "; - push @query_params, "%$isbn%"; + if ( @isbns ) { + $query .= " AND ( biblioitems.isbn LIKE " . join (" OR biblioitems.isbn LIKE ", @isbn_params ) . ")"; + foreach my $isb (@isbns){ + push @query_params, "%$isb%"; + } } + if ( $ean ) { $query .= " AND biblioitems.ean = ? "; push @query_params, "$ean"; @@ -2417,6 +2442,18 @@ sub GetHistory { push @query_params, @$created_by; } + if ( @$ordernumbers ) { + $query .= ' AND (aqorders.ordernumber IN ( ' . join (',', ('?') x @$ordernumbers ) . '))'; + push @query_params, @$ordernumbers; + } + if ( @$additional_fields ) { + my @baskets = Koha::Acquisition::Baskets->filter_by_additional_fields($additional_fields); + + return [] unless @baskets; + + # No parameterization because record IDs come directly from DB + $query .= ' AND aqbasket.basketno IN ( ' . join( ',', map { $_->basketno } @baskets ) . ' )'; + } if ( C4::Context->preference("IndependentBranches") ) { unless ( C4::Context->IsSuperLibrarian() ) { @@ -2433,7 +2470,7 @@ sub GetHistory { $results = GetRecentAcqui($days); -C<$results> is a ref to a table which containts hashref +C<$results> is a ref to a table which contains hashref =cut @@ -2512,7 +2549,8 @@ sub GetInvoices { my $dbh = C4::Context->dbh; my $query = qq{ - SELECT aqinvoices.*, aqbooksellers.name AS suppliername, + SELECT aqinvoices.invoiceid, aqinvoices.invoicenumber, aqinvoices.booksellerid, aqinvoices.shipmentdate, aqinvoices.billingdate, aqinvoices.closedate, aqinvoices.shipmentcost, aqinvoices.shipmentcost_budgetid, aqinvoices.message_id, + aqbooksellers.name AS suppliername, COUNT( DISTINCT IF( aqorders.datereceived IS NOT NULL, @@ -2598,7 +2636,7 @@ sub GetInvoices { } $query .= " WHERE " . join(" AND ", @bind_strs) if @bind_strs; - $query .= " GROUP BY aqinvoices.invoiceid "; + $query .= " GROUP BY aqinvoices.invoiceid, aqinvoices.invoicenumber, aqinvoices.booksellerid, aqinvoices.shipmentdate, aqinvoices.billingdate, aqinvoices.closedate, aqinvoices.shipmentcost, aqinvoices.shipmentcost_budgetid, aqinvoices.message_id, aqbooksellers.name"; if($args{order_by}) { my ($column, $direction) = split / /, $args{order_by}; @@ -2965,7 +3003,7 @@ sub populate_order_with_prices { # ecost tax excluded = rrp tax excluded * ( 1 - discount ) $order->{ecost_tax_excluded} = $order->{rrp_tax_excluded} * ( 1 - $discount ); - # ecost tax included = rrp tax excluded * ( 1 - tax rate ) * ( 1 - discount ) + # ecost tax included = rrp tax excluded * ( 1 + tax rate ) * ( 1 - discount ) $order->{ecost_tax_included} = $order->{rrp_tax_excluded} * ( 1 + $order->{tax_rate_on_ordering} ) *