X-Git-Url: http://koha-dev.rot13.org:8081/gitweb/?a=blobdiff_plain;f=C4%2FAcquisition.pm;h=c091f898a0b4c08ebd3031a5076f7949557a5b72;hb=b27da7e0ce25c806612743100609255ace48257c;hp=0cff23543105c33cf3c31f0ce1a4f9818c24f06f;hpb=3ed1d0bf7ed48a207a021e171882b5f30c257f2e;p=srvgit diff --git a/C4/Acquisition.pm b/C4/Acquisition.pm index 0cff235431..c091f898a0 100644 --- a/C4/Acquisition.pm +++ b/C4/Acquisition.pm @@ -4,42 +4,46 @@ package C4::Acquisition; # # 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 2 of the License, or (at your option) any later -# version. +# 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. +# 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, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# You should have received a copy of the GNU General Public License +# along with Koha; if not, see . use Modern::Perl; use Carp; use C4::Context; use C4::Debug; -use C4::Dates qw(format_date format_date_in_iso); -use MARC::Record; use C4::Suggestions; use C4::Biblio; use C4::Contract; use C4::Debug; -use C4::SQLHelper qw(InsertInTable UpdateInTable); -use C4::Bookseller qw(GetBookSellerFromId); use C4::Templates qw(gettemplate); +use Koha::DateUtils qw( dt_from_string output_pref ); +use Koha::Acquisition::Order; +use Koha::Acquisition::Bookseller; +use Koha::Number::Price; +use Koha::Libraries; + +use C4::Koha; + +use MARC::Field; +use MARC::Record; use Time::localtime; use HTML::Entities; -use vars qw($VERSION @ISA @EXPORT); +use vars qw(@ISA @EXPORT); BEGIN { - # set the version for version checking - $VERSION = 3.07.00.049; require Exporter; @ISA = qw(Exporter); @EXPORT = qw( @@ -56,15 +60,15 @@ BEGIN { &ModBasketgroup &NewBasketgroup &DelBasketgroup &GetBasketgroup &CloseBasketgroup &GetBasketgroups &ReOpenBasketgroup - &NewOrder &DelOrder &ModOrder &GetOrder &GetOrders &GetOrdersByBiblionumber + &DelOrder &ModOrder &GetOrder &GetOrders &GetOrdersByBiblionumber &GetLateOrders &GetOrderFromItemnumber &SearchOrders &GetHistory &GetRecentAcqui &ModReceiveOrder &CancelReceipt - &GetCancelledOrders &TransferOrder + &TransferOrder &GetLastOrderNotReceivedFromSubscriptionid &GetLastOrderReceivedFromSubscriptionid - &NewOrderItem &ModItemOrder + &ModItemOrder - &GetParcels &GetParcel + &GetParcels &GetInvoices &GetInvoice @@ -80,6 +84,12 @@ BEGIN { &AddClaim &GetBiblioCountByBasketno + + &GetOrderUsers + &ModOrderUsers + &NotifyOrderUsers + + &FillWithDefaultValues ); } @@ -176,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 @@ -196,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) ' @@ -208,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; } @@ -225,24 +235,11 @@ close a basket (becomes unmodifiable, except for receives) sub CloseBasket { my ($basketno) = @_; my $dbh = C4::Context->dbh; - my $query = " - UPDATE aqbasket - SET closedate=now() - WHERE basketno=? - "; - my $sth = $dbh->prepare($query); - $sth->execute($basketno); + $dbh->do('UPDATE aqbasket SET closedate=now() WHERE basketno=?', {}, $basketno ); - my @orders = GetOrders($basketno); - foreach my $order (@orders) { - $query = qq{ - UPDATE aqorders - SET orderstatus = 'ordered' - WHERE ordernumber = ?; - }; - $sth = $dbh->prepare($query); - $sth->execute($order->{'ordernumber'}); - } + $dbh->do( q{UPDATE aqorders SET orderstatus = 'ordered' WHERE basketno = ? AND orderstatus != 'complete'}, + {}, $basketno); + return; } =head3 ReopenBasket @@ -256,24 +253,15 @@ reopen a basket sub ReopenBasket { my ($basketno) = @_; my $dbh = C4::Context->dbh; - my $query = " - UPDATE aqbasket - SET closedate=NULL - WHERE basketno=? - "; - my $sth = $dbh->prepare($query); - $sth->execute($basketno); + $dbh->do( q{UPDATE aqbasket SET closedate=NULL WHERE basketno=?}, {}, $basketno ); - my @orders = GetOrders($basketno); - foreach my $order (@orders) { - $query = qq{ - UPDATE aqorders - SET orderstatus = 'new' - WHERE ordernumber = ?; - }; - $sth = $dbh->prepare($query); - $sth->execute($order->{'ordernumber'}); - } + $dbh->do( q{ + UPDATE aqorders + SET orderstatus = 'new' + WHERE basketno = ? + AND orderstatus != 'complete' + }, {}, $basketno); + return; } #------------------------------------------------------------# @@ -341,16 +329,12 @@ sub GetBasketAsCSV { =head3 GetBasketGroupAsCSV -=over - -&GetBasketGroupAsCSV($basketgroupid); + &GetBasketGroupAsCSV($basketgroupid); Export a basket group as CSV $cgi parameter is needed for column name translation -=back - =cut sub GetBasketGroupAsCSV { @@ -365,7 +349,7 @@ sub GetBasketGroupAsCSV { my $contract = GetContract({ contractnumber => $basket->{contractnumber} }); - my $bookseller = GetBookSellerFromId( $$basket{booksellerid} ); + my $bookseller = Koha::Acquisition::Bookseller->fetch({ id => $basket->{booksellerid} }); my $basketgroup = GetBasketgroup( $$basket{basketgroupid} ); foreach my $order (@orders) { @@ -547,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=?"; @@ -1034,47 +1020,80 @@ sub GetBasketgroups { =head3 GetOrders - @orders = &GetOrders($basketnumber, $orderby); + @orders = &GetOrders( $basketno, { orderby => 'biblio.title', cancelled => 0|1 } ); Looks up the pending (non-cancelled) orders with the given basket -number. If C<$booksellerID> is non-empty, only orders from that seller -are returned. +number. -return : -C<&basket> returns a two-element array. C<@orders> is an array of -references-to-hash, whose keys are the fields from the aqorders, -biblio, and biblioitems tables in the Koha database. +If cancelled is set, only cancelled orders will be returned. =cut sub GetOrders { - my ( $basketno, $orderby ) = @_; + my ( $basketno, $params ) = @_; + return () unless $basketno; + + my $orderby = $params->{orderby}; + my $cancelled = $params->{cancelled} || 0; + my $dbh = C4::Context->dbh; - my $query =" + my $query = q| SELECT biblio.*,biblioitems.*, aqorders.*, aqbudgets.*, + |; + $query .= $cancelled + ? q| + aqorders_transfers.ordernumber_to AS transferred_to, + aqorders_transfers.timestamp AS transferred_to_timestamp + | + : q| aqorders_transfers.ordernumber_from AS transferred_from, aqorders_transfers.timestamp AS transferred_from_timestamp + |; + $query .= q| FROM aqorders LEFT JOIN aqbudgets ON aqbudgets.budget_id = aqorders.budget_id LEFT JOIN biblio ON biblio.biblionumber = aqorders.biblionumber LEFT JOIN biblioitems ON biblioitems.biblionumber =biblio.biblionumber + |; + $query .= $cancelled + ? q| + LEFT JOIN aqorders_transfers ON aqorders_transfers.ordernumber_from = aqorders.ordernumber + | + : q| LEFT JOIN aqorders_transfers ON aqorders_transfers.ordernumber_to = aqorders.ordernumber + + |; + $query .= q| WHERE basketno=? + |; + + if ($cancelled) { + $orderby ||= q|biblioitems.publishercode, biblio.title|; + $query .= q| + AND (datecancellationprinted IS NOT NULL + AND datecancellationprinted <> '0000-00-00') + |; + } + else { + $orderby ||= + q|aqorders.datecancellationprinted desc, aqorders.timestamp desc|; + $query .= q| AND (datecancellationprinted IS NULL OR datecancellationprinted='0000-00-00') - "; + |; + } - $orderby = "biblioitems.publishercode,biblio.title" unless $orderby; $query .= " ORDER BY $orderby"; - my $result_set = + my $orders = $dbh->selectall_arrayref( $query, { Slice => {} }, $basketno ); - return @{$result_set}; + return @{$orders}; } #------------------------------------------------------------# + =head3 GetOrdersByBiblionumber @orders = &GetOrdersByBiblionumber($biblionumber); @@ -1228,95 +1247,6 @@ sub GetLastOrderReceivedFromSubscriptionid { } - -#------------------------------------------------------------# - -=head3 NewOrder - - &NewOrder(\%hashref); - -Adds a new order to the database. Any argument that isn't described -below is the new value of the field with the same name in the aqorders -table of the Koha database. - -=over - -=item $hashref->{'basketno'} is the basketno foreign key in aqorders, it is mandatory - -=item $hashref->{'ordernumber'} is a "minimum order number." - -=item $hashref->{'budgetdate'} is effectively ignored. -If it's undef (anything false) or the string 'now', the current day is used. -Else, the upcoming July 1st is used. - -=item $hashref->{'subscription'} may be either "yes", or anything else for "no". - -=item $hashref->{'uncertainprice'} may be 0 for "the price is known" or 1 for "the price is uncertain" - -=item defaults entrydate to Now - -The following keys are used: "biblionumber", "title", "basketno", "quantity", "order_vendornote", "order_internalnote", "rrp", "ecost", "gstrate", "unitprice", "subscription", "sort1", "sort2", "booksellerinvoicenumber", "listprice", "budgetdate", "purchaseordernumber", "branchcode", "booksellerinvoicenumber", "budget_id". - -=back - -=cut - -sub NewOrder { - my $orderinfo = shift; - - my $dbh = C4::Context->dbh; - my @params; - - - # if these parameters are missing, we can't continue - for my $key (qw/basketno quantity biblionumber budget_id/) { - croak "Mandatory parameter $key missing" unless $orderinfo->{$key}; - } - - if ( defined $orderinfo->{subscription} && $orderinfo->{'subscription'} eq 'yes' ) { - $orderinfo->{'subscription'} = 1; - } else { - $orderinfo->{'subscription'} = 0; - } - $orderinfo->{'entrydate'} ||= C4::Dates->new()->output("iso"); - if (!$orderinfo->{quantityreceived}) { - $orderinfo->{quantityreceived} = 0; - } - - my $ordernumber=InsertInTable("aqorders",$orderinfo); - if (not $orderinfo->{parent_ordernumber}) { - my $sth = $dbh->prepare(" - UPDATE aqorders - SET parent_ordernumber = ordernumber - WHERE ordernumber = ? - "); - $sth->execute($ordernumber); - } - return ( $orderinfo->{'basketno'}, $ordernumber ); -} - - - -#------------------------------------------------------------# - -=head3 NewOrderItem - - &NewOrderItem(); - -=cut - -sub NewOrderItem { - my ($itemnumber, $ordernumber) = @_; - my $dbh = C4::Context->dbh; - my $query = qq| - INSERT INTO aqorders_items - (itemnumber, ordernumber) - VALUES (?,?) |; - - my $sth = $dbh->prepare($query); - $sth->execute( $itemnumber, $ordernumber); -} - #------------------------------------------------------------# =head3 ModOrder @@ -1394,51 +1324,6 @@ sub ModItemOrder { #------------------------------------------------------------# -=head3 GetCancelledOrders - - my @orders = GetCancelledOrders($basketno, $orderby); - -Returns cancelled orders for a basket - -=cut - -sub GetCancelledOrders { - my ( $basketno, $orderby ) = @_; - - return () unless $basketno; - - my $dbh = C4::Context->dbh; - my $query = " - SELECT - biblio.*, - biblioitems.*, - aqorders.*, - aqbudgets.*, - aqorders_transfers.ordernumber_to AS transferred_to, - aqorders_transfers.timestamp AS transferred_to_timestamp - FROM aqorders - LEFT JOIN aqbudgets ON aqbudgets.budget_id = aqorders.budget_id - LEFT JOIN biblio ON biblio.biblionumber = aqorders.biblionumber - LEFT JOIN biblioitems ON biblioitems.biblionumber = biblio.biblionumber - LEFT JOIN aqorders_transfers ON aqorders_transfers.ordernumber_from = aqorders.ordernumber - WHERE basketno = ? - AND (datecancellationprinted IS NOT NULL - AND datecancellationprinted <> '0000-00-00') - "; - - $orderby = "aqorders.datecancellationprinted desc, aqorders.timestamp desc" - unless $orderby; - $query .= " ORDER BY $orderby"; - my $sth = $dbh->prepare($query); - $sth->execute($basketno); - my $results = $sth->fetchall_arrayref( {} ); - - return @$results; -} - - -#------------------------------------------------------------# - =head3 ModReceiveOrder &ModReceiveOrder({ @@ -1486,7 +1371,13 @@ sub ModReceiveOrder { my $order_vendornote = $params->{order_vendornote}; my $dbh = C4::Context->dbh; - $datereceived = C4::Dates->output('iso') unless $datereceived; + $datereceived = output_pref( + { + dt => ( $datereceived ? dt_from_string( $datereceived ) : dt_from_string ), + dateformat => 'iso', + dateonly => 1, + } + ); my $suggestionid = GetSuggestionFromBiblionumber( $biblionumber ); if ($suggestionid) { ModSuggestion( {suggestionid=>$suggestionid, @@ -1496,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 ); @@ -1504,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 @@ -1519,7 +1410,7 @@ q{SELECT * FROM aqorders WHERE biblionumber=? AND aqorders.ordernumber=?}, my $sth = $dbh->prepare($query); $sth->execute( - $order->{quantity} - $quantrec, + ( $order->{is_standing} ? 1 : ( $order->{quantity} - $quantrec ) ), ( defined $order_internalnote ? $order_internalnote : () ), ( defined $order_vendornote ? $order_vendornote : () ), $ordernumber @@ -1535,8 +1426,7 @@ q{SELECT * FROM aqorders WHERE biblionumber=? AND aqorders.ordernumber=?}, $order->{'rrp'} = $rrp; $order->{ecost} = $ecost; $order->{'orderstatus'} = 'complete'; - my $basketno; - ( $basketno, $new_ordernumber ) = NewOrder($order); + $new_ordernumber = Koha::Acquisition::Order->new($order)->insert->{ordernumber}; if ($received_items) { foreach my $itemnumber (@$received_items) { @@ -1559,12 +1449,16 @@ q{SELECT * FROM aqorders WHERE biblionumber=? AND aqorders.ordernumber=?}, $cost, $rrp, $ecost, - $budget_id, + ( $budget_id ? $budget_id : $order->{budget_id} ), ( defined $order_internalnote ? $order_internalnote : () ), ( defined $order_vendornote ? $order_vendornote : () ), $biblionumber, $ordernumber ); + + # All items have been received, sent a notification to users + NotifyOrderUsers( $ordernumber ); + } return ($datereceived, $new_ordernumber); } @@ -1605,6 +1499,8 @@ sub CancelReceipt { my $parent_ordernumber = $order->{'parent_ordernumber'}; + my @itemnumbers = GetItemnumbersFromOrder( $ordernumber ); + if($parent_ordernumber == $ordernumber || not $parent_ordernumber) { # The order line has no parent, just mark it as not received $query = qq{ @@ -1665,6 +1561,25 @@ sub CancelReceipt { } + if(C4::Context->preference('AcqCreateItem') eq 'ordering') { + my @affects = split q{\|}, C4::Context->preference("AcqItemSetSubfieldsWhenReceiptIsCancelled"); + if ( @affects ) { + for my $in ( @itemnumbers ) { + my $biblionumber = C4::Biblio::GetBiblionumberFromItemnumber( $in ); + my $frameworkcode = GetFrameworkCode($biblionumber); + my ( $itemfield ) = GetMarcFromKohaField( 'items.itemnumber', $frameworkcode ); + my $item = C4::Items::GetMarcItem( $biblionumber, $in ); + for my $affect ( @affects ) { + my ( $sf, $v ) = split q{=}, $affect, 2; + foreach ( $item->field($itemfield) ) { + $_->update( $sf => $v ); + } + } + C4::Items::ModItemFromMarc( $item, $biblionumber, $in ); + } + } + } + return $parent_ordernumber; } @@ -1761,7 +1676,7 @@ sub SearchOrders { LEFT JOIN biblioitems ON biblioitems.biblionumber=biblio.biblionumber }; - # If we search on ordernumber, we retrieve the transfered order if a transfer has been done. + # If we search on ordernumber, we retrieve the transferred order if a transfer has been done. $query .= q{ LEFT JOIN aqorders_transfers ON aqorders_transfers.ordernumber_to = aqorders.ordernumber } if $ordernumber; @@ -1771,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; @@ -1853,25 +1778,53 @@ cancelled. =cut sub DelOrder { - my ( $bibnum, $ordernumber ) = @_; + my ( $bibnum, $ordernumber, $delete_biblio, $reason ) = @_; + + my $error; my $dbh = C4::Context->dbh; my $query = " UPDATE aqorders SET datecancellationprinted=now(), orderstatus='cancelled' - WHERE biblionumber=? AND ordernumber=? + "; + if($reason) { + $query .= ", cancellationreason = ? "; + } + $query .= " + WHERE biblionumber=? AND ordernumber=? "; my $sth = $dbh->prepare($query); - $sth->execute( $bibnum, $ordernumber ); + if($reason) { + $sth->execute($reason, $bibnum, $ordernumber); + } else { + $sth->execute( $bibnum, $ordernumber ); + } + $sth->finish; + my @itemnumbers = GetItemnumbersFromOrder( $ordernumber ); foreach my $itemnumber (@itemnumbers){ - C4::Items::DelItem( - { - biblionumber => $bibnum, - itemnumber => $itemnumber + my $delcheck = C4::Items::DelItemCheck( $dbh, $bibnum, $itemnumber ); + + if($delcheck != 1) { + $error->{'delitem'} = 1; + } + } + + if($delete_biblio) { + # We get the number of remaining items + my $itemcount = C4::Items::GetItemsCount($bibnum); + + # If there are no items left, + if ( $itemcount == 0 ) { + # We delete the record + my $delcheck = DelBiblio($bibnum); + + if($delcheck) { + $error->{'delbiblio'} = 1; } - ); + } } - return; + + return $error; } =head3 TransferOrder @@ -1879,11 +1832,11 @@ sub DelOrder { my $newordernumber = TransferOrder($ordernumber, $basketno); Transfer an order line to a basket. -Mark $ordernumber as cancelled with an internal note 'Cancelled and transfered +Mark $ordernumber as cancelled with an internal note 'Cancelled and transferred to BOOKSELLER on DATE' and create new order with internal note -'Transfered from BOOKSELLER on DATE'. +'Transferred from BOOKSELLER on DATE'. Move all attached items to the new order. -Received orders cannot be transfered. +Received orders cannot be transferred. Return the ordernumber of created order. =cut @@ -1903,17 +1856,17 @@ sub TransferOrder { $query = q{ UPDATE aqorders - SET datecancellationprinted = CAST(NOW() AS date) + SET datecancellationprinted = CAST(NOW() AS date), orderstatus = ? WHERE ordernumber = ? }; $sth = $dbh->prepare($query); - $rv = $sth->execute($ordernumber); + $rv = $sth->execute('cancelled', $ordernumber); delete $order->{'ordernumber'}; delete $order->{parent_ordernumber}; $order->{'basketno'} = $basketno; - my $newordernumber; - (undef, $newordernumber) = NewOrder($order); + + my $newordernumber = Koha::Acquisition::Order->new($order)->insert->{ordernumber}; $query = q{ UPDATE aqorders_items @@ -1935,77 +1888,6 @@ sub TransferOrder { =head2 FUNCTIONS ABOUT PARCELS -=cut - -#------------------------------------------------------------# - -=head3 GetParcel - - @results = &GetParcel($booksellerid, $code, $date); - -Looks up all of the received items from the supplier with the given -bookseller ID at the given date, for the given code (bookseller Invoice number). Ignores cancelled and completed orders. - -C<@results> is an array of references-to-hash. The keys of each element are fields from -the aqorders, biblio, and biblioitems tables of the Koha database. - -C<@results> is sorted alphabetically by book title. - -=cut - -sub GetParcel { - #gets all orders from a certain supplier, orders them alphabetically - my ( $supplierid, $code, $datereceived ) = @_; - my $dbh = C4::Context->dbh; - my @results = (); - $code .= '%' - if $code; # add % if we search on a given code (otherwise, let him empty) - my $strsth =" - SELECT authorisedby, - creationdate, - aqbasket.basketno, - closedate,surname, - firstname, - aqorders.biblionumber, - aqorders.ordernumber, - aqorders.parent_ordernumber, - aqorders.quantity, - aqorders.quantityreceived, - aqorders.unitprice, - aqorders.listprice, - aqorders.rrp, - aqorders.ecost, - aqorders.gstrate, - biblio.title - FROM aqorders - LEFT JOIN aqbasket ON aqbasket.basketno=aqorders.basketno - LEFT JOIN borrowers ON aqbasket.authorisedby=borrowers.borrowernumber - LEFT JOIN biblio ON aqorders.biblionumber=biblio.biblionumber - LEFT JOIN aqinvoices ON aqorders.invoiceid = aqinvoices.invoiceid - WHERE - aqbasket.booksellerid = ? - AND aqinvoices.invoicenumber LIKE ? - AND aqorders.datereceived = ? "; - - my @query_params = ( $supplierid, $code, $datereceived ); - if ( C4::Context->preference("IndependentBranches") ) { - unless ( C4::Context->IsSuperLibrarian() ) { - $strsth .= " and (borrowers.branchcode = ? - or borrowers.branchcode = '')"; - push @query_params, C4::Context->userenv->{branch}; - } - } - $strsth .= " ORDER BY aqbasket.basketno"; - my $result_set = $dbh->selectall_arrayref( - $strsth, - { Slice => {} }, - @query_params); - - return @{$result_set}; -} - -#------------------------------------------------------------# - =head3 GetParcels $results = &GetParcels($bookseller, $order, $code, $datefrom, $dateto); @@ -2226,7 +2108,7 @@ sub GetLateOrders { =head3 GetHistory - (\@order_loop, $total_qty, $total_price, $total_qtyreceived) = GetHistory( %params ); + \@order_loop = GetHistory( %params ); Retreives some acquisition history information @@ -2266,9 +2148,6 @@ returns: 'quantityreceived' => undef, 'title' => 'The Adventures of Huckleberry Finn' } - $total_qty is the sum of all of the quantities in $order_loop - $total_price is the cost of each in $order_loop times the quantity - $total_qtyreceived is the sum of all of the quantityreceived entries in $order_loop =cut @@ -2292,6 +2171,7 @@ sub GetHistory { my $get_canceled_order = $params{get_canceled_order} || 0; my $ordernumber = $params{ordernumber}; my $search_children_too = $params{search_children_too} || 0; + my $created_by = $params{created_by} || []; my @order_loop; my $total_qty = 0; @@ -2308,6 +2188,8 @@ sub GetHistory { aqorders.basketno, aqbasket.basketname, aqbasket.basketgroupid, + aqbasket.authorisedby, + concat( borrowers.firstname,' ',borrowers.surname) AS authorisedbyname, aqbasketgroups.name as groupname, aqbooksellers.name, aqbasket.creationdate, @@ -2336,12 +2218,9 @@ sub GetHistory { LEFT JOIN aqinvoices ON aqorders.invoiceid = aqinvoices.invoiceid LEFT JOIN deletedbiblio ON deletedbiblio.biblionumber=aqorders.biblionumber LEFT JOIN deletedbiblioitems ON deletedbiblioitems.biblionumber=aqorders.biblionumber + LEFT JOIN borrowers ON aqbasket.authorisedby=borrowers.borrowernumber "; - if ( C4::Context->preference("IndependentBranches") ) { - $query .= " LEFT JOIN borrowers ON aqbasket.authorisedby=borrowers.borrowernumber"; - } - $query .= " WHERE 1 "; unless ($get_canceled_order or (defined $orderstatus and $orderstatus eq 'cancelled')) { @@ -2429,6 +2308,11 @@ sub GetHistory { $query .= ") "; } + if ( @$created_by ) { + $query .= ' AND aqbasket.authorisedby IN ( ' . join( ',', ('?') x @$created_by ) . ')'; + push @query_params, @$created_by; + } + if ( C4::Context->preference("IndependentBranches") ) { unless ( C4::Context->IsSuperLibrarian() ) { @@ -2437,18 +2321,8 @@ sub GetHistory { } } $query .= " ORDER BY id"; - my $sth = $dbh->prepare($query); - $sth->execute( @query_params ); - my $cnt = 1; - while ( my $line = $sth->fetchrow_hashref ) { - $line->{count} = $cnt++; - $line->{toggle} = 1 if $cnt % 2; - push @order_loop, $line; - $total_qty += ( $line->{quantity} ) ? $line->{quantity} : 0; - $total_qtyreceived += ( $line->{quantityreceived} ) ? $line->{quantityreceived} : 0; - $total_price += ( $line->{quantity} and $line->{ecost} ) ? $line->{quantity} * $line->{ecost} : 0; - } - return \@order_loop, $total_qty, $total_price, $total_qtyreceived; + + return $dbh->selectall_arrayref( $query, { Slice => {} }, @query_params ); } =head2 GetRecentAcqui @@ -2478,14 +2352,10 @@ sub GetRecentAcqui { =head3 AddClaim -=over - -&AddClaim($ordernumber); + &AddClaim($ordernumber); Add a claim for an order -=back - =cut sub AddClaim { @@ -2618,6 +2488,10 @@ sub GetInvoices { push @bind_strs, " borrowers.branchcode = ? "; push @bind_args, $args{branchcode}; } + if($args{message_id}) { + push @bind_strs, " aqinvoices.message_id = ? "; + push @bind_args, $args{message_id}; + } $query .= " WHERE " . join(" AND ", @bind_strs) if @bind_strs; $query .= " GROUP BY aqinvoices.invoiceid "; @@ -2697,10 +2571,19 @@ sub GetInvoiceDetails { my $invoice = $sth->fetchrow_hashref; $query = q{ - SELECT aqorders.*, biblio.*, aqbasket.basketname + SELECT aqorders.*, + biblio.*, + biblio.copyrightdate, + biblioitems.publishercode, + biblioitems.publicationyear, + aqbasket.basketname, + aqbasketgroups.id AS basketgroupid, + aqbasketgroups.name AS basketgroupname FROM aqorders LEFT JOIN aqbasket ON aqorders.basketno = aqbasket.basketno + LEFT JOIN aqbasketgroups ON aqbasket.basketgroupid = aqbasketgroups.id LEFT JOIN biblio ON aqorders.biblionumber = biblio.biblionumber + LEFT JOIN biblioitems ON aqorders.biblionumber = biblioitems.biblionumber WHERE invoiceid = ? }; $sth = $dbh->prepare($query); @@ -2733,7 +2616,7 @@ sub AddInvoice { return unless(%invoice and $invoice{invoicenumber}); my @columns = qw(invoicenumber booksellerid shipmentdate billingdate - closedate shipmentcost shipmentcost_budgetid); + closedate shipmentcost shipmentcost_budgetid message_id); my @set_strs; my @set_args; @@ -2834,7 +2717,7 @@ sub CloseInvoice { Reopen an invoice -Equivalent to ModInvoice(invoiceid => $invoiceid, closedate => C4::Dates->new()->output('iso')) +Equivalent to ModInvoice(invoiceid => $invoiceid, closedate => output_pref({ dt=>dt_from_string, dateonly=>1, otputpref=>'iso' })) =cut @@ -2936,6 +2819,222 @@ sub GetBiblioCountByBasketno { return $sth->fetchrow; } +# This is *not* the good way to calcul prices +# But it's how it works at the moment into Koha +# This will be fixed later. +# Note this subroutine should be moved to Koha::Acquisition::Order +# Will do when a DBIC decision will be taken. +sub populate_order_with_prices { + my ($params) = @_; + + my $order = $params->{order}; + my $booksellerid = $params->{booksellerid}; + return unless $booksellerid; + + my $bookseller = Koha::Acquisition::Bookseller->fetch({ id => $booksellerid }); + + my $receiving = $params->{receiving}; + my $ordering = $params->{ordering}; + my $discount = $order->{discount}; + $discount /= 100 if $discount > 1; + + $order->{rrp} = Koha::Number::Price->new( $order->{rrp} )->round; + $order->{ecost} = Koha::Number::Price->new( $order->{ecost} )->round; + if ($ordering) { + if ( $bookseller->{listincgst} ) { + $order->{rrpgsti} = $order->{rrp}; + $order->{rrpgste} = Koha::Number::Price->new( + $order->{rrpgsti} / ( 1 + $order->{gstrate} ) )->round; + $order->{ecostgsti} = $order->{ecost}; + $order->{ecostgste} = Koha::Number::Price->new( + $order->{ecost} / ( 1 + $order->{gstrate} ) )->round; + $order->{gstvalue} = Koha::Number::Price->new( + ( $order->{ecostgsti} - $order->{ecostgste} ) * + $order->{quantity} )->round; + $order->{totalgste} = $order->{ecostgste} * $order->{quantity}; + $order->{totalgsti} = $order->{ecostgsti} * $order->{quantity}; + } + else { + $order->{rrpgste} = $order->{rrp}; + $order->{rrpgsti} = Koha::Number::Price->new( + $order->{rrp} * ( 1 + $order->{gstrate} ) )->round; + $order->{ecostgste} = $order->{ecost}; + $order->{ecostgsti} = Koha::Number::Price->new( + $order->{ecost} * ( 1 + $order->{gstrate} ) )->round; + $order->{gstvalue} = Koha::Number::Price->new( + ( $order->{ecostgsti} - $order->{ecostgste} ) * + $order->{quantity} )->round; + $order->{totalgste} = $order->{ecostgste} * $order->{quantity}; + $order->{totalgsti} = $order->{ecostgsti} * $order->{quantity}; + } + } + + if ($receiving) { + if ( $bookseller->{listincgst} ) { + $order->{unitpricegsti} = Koha::Number::Price->new( $order->{unitprice} )->round; + $order->{unitpricegste} = Koha::Number::Price->new( + $order->{unitpricegsti} / ( 1 + $order->{gstrate} ) )->round; + } + else { + $order->{unitpricegste} = Koha::Number::Price->new( $order->{unitprice} )->round; + $order->{unitpricegsti} = Koha::Number::Price->new( + $order->{unitpricegste} * ( 1 + $order->{gstrate} ) )->round; + } + $order->{gstvalue} = Koha::Number::Price->new( + ( $order->{unitpricegsti} - $order->{unitpricegste} ) + * $order->{quantityreceived} )->round; + + $order->{totalgste} = $order->{unitpricegste} * $order->{quantity}; + $order->{totalgsti} = $order->{unitpricegsti} * $order->{quantity}; + } + + return $order; +} + +=head3 GetOrderUsers + + $order_users_ids = &GetOrderUsers($ordernumber); + +Returns a list of all borrowernumbers that are in order users list + +=cut + +sub GetOrderUsers { + my ($ordernumber) = @_; + + return unless $ordernumber; + + my $query = q| + SELECT borrowernumber + FROM aqorder_users + WHERE ordernumber = ? + |; + my $dbh = C4::Context->dbh; + my $sth = $dbh->prepare($query); + $sth->execute($ordernumber); + my $results = $sth->fetchall_arrayref( {} ); + + my @borrowernumbers; + foreach (@$results) { + push @borrowernumbers, $_->{'borrowernumber'}; + } + + return @borrowernumbers; +} + +=head3 ModOrderUsers + + my @order_users_ids = (1, 2, 3); + &ModOrderUsers($ordernumber, @basketusers_ids); + +Delete all users from order users list, and add users in C<@order_users_ids> +to this users list. + +=cut + +sub ModOrderUsers { + my ( $ordernumber, @order_users_ids ) = @_; + + return unless $ordernumber; + + my $dbh = C4::Context->dbh; + my $query = q| + DELETE FROM aqorder_users + WHERE ordernumber = ? + |; + my $sth = $dbh->prepare($query); + $sth->execute($ordernumber); + + $query = q| + INSERT INTO aqorder_users (ordernumber, borrowernumber) + VALUES (?, ?) + |; + $sth = $dbh->prepare($query); + foreach my $order_user_id (@order_users_ids) { + $sth->execute( $ordernumber, $order_user_id ); + } +} + +sub NotifyOrderUsers { + my ($ordernumber) = @_; + + my @borrowernumbers = GetOrderUsers($ordernumber); + return unless @borrowernumbers; + + my $order = GetOrder( $ordernumber ); + for my $borrowernumber (@borrowernumbers) { + my $borrower = C4::Members::GetMember( borrowernumber => $borrowernumber ); + my $library = Koha::Libraries->find( $borrower->{branchcode} )->unblessed; + my $biblio = C4::Biblio::GetBiblio( $order->{biblionumber} ); + my $letter = C4::Letters::GetPreparedLetter( + module => 'acquisition', + letter_code => 'ACQ_NOTIF_ON_RECEIV', + branchcode => $library->{branchcode}, + tables => { + 'branches' => $library, + 'borrowers' => $borrower, + 'biblio' => $biblio, + 'aqorders' => $order, + }, + ); + if ( $letter ) { + C4::Letters::EnqueueLetter( + { + letter => $letter, + borrowernumber => $borrowernumber, + LibraryName => C4::Context->preference("LibraryName"), + message_transport_type => 'email', + } + ) or warn "can't enqueue letter $letter"; + } + } +} + +=head3 FillWithDefaultValues + +FillWithDefaultValues( $marc_record ); + +This will update the record with default value defined in the ACQ framework. +For all existing fields, if a default value exists and there are no subfield, it will be created. +If the field does not exist, it will be created too. + +=cut + +sub FillWithDefaultValues { + my ($record) = @_; + my $tagslib = C4::Biblio::GetMarcStructure( 1, 'ACQ' ); + if ($tagslib) { + my ($itemfield) = + C4::Biblio::GetMarcFromKohaField( 'items.itemnumber', '' ); + for my $tag ( sort keys %$tagslib ) { + next unless $tag; + next if $tag == $itemfield; + for my $subfield ( sort keys %{ $tagslib->{$tag} } ) { + next if IsMarcStructureInternal($tagslib->{$tag}{$subfield}); + my $defaultvalue = $tagslib->{$tag}{$subfield}{defaultvalue}; + if ( defined $defaultvalue and $defaultvalue ne '' ) { + my @fields = $record->field($tag); + if (@fields) { + for my $field (@fields) { + unless ( defined $field->subfield($subfield) ) { + $field->add_subfields( + $subfield => $defaultvalue ); + } + } + } + else { + $record->insert_fields_ordered( + MARC::Field->new( + $tag, '', '', $subfield => $defaultvalue + ) + ); + } + } + } + } + } +} + 1; __END__