#
# 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 <http://www.gnu.org/licenses>.
-use strict;
-use warnings;
+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 C4::Koha qw( subfield_is_koha_internal_p );
+
+use MARC::Field;
+use MARC::Record;
use Time::localtime;
use HTML::Entities;
&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
- &GetContracts &GetContract
+ &GetParcels
&GetInvoices
&GetInvoice
&AddClaim
&GetBiblioCountByBasketno
+
+ &GetOrderUsers
+ &ModOrderUsers
+ &NotifyOrderUsers
+
+ &FillWithDefaultValues
);
}
my ($basketno, $cgi) = @_;
my $basket = GetBasket($basketno);
my @orders = GetOrders($basketno);
- my $contract = GetContract($basket->{'contractnumber'});
+ my $contract = GetContract({
+ contractnumber => $basket->{'contractnumber'}
+ });
- my $template = C4::Templates::gettemplate("acqui/csv/basket.tmpl", "intranet", $cgi);
+ my $template = C4::Templates::gettemplate("acqui/csv/basket.tt", "intranet", $cgi);
my @rows;
foreach my $order (@orders) {
publicationyear => $bd->{'publicationyear'},
publishercode => $bd->{'publishercode'},
collectiontitle => $bd->{'collectiontitle'},
- notes => $order->{'notes'},
+ notes => $order->{'order_vendornote'},
quantity => $order->{'quantity'},
rrp => $order->{'rrp'},
deliveryplace => C4::Branch::GetBranchName( $basket->{'deliveryplace'} ),
=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 {
my ($basketgroupid, $cgi) = @_;
my $baskets = GetBasketsByBasketgroup($basketgroupid);
- my $template = C4::Templates::gettemplate('acqui/csv/basketgroup.tmpl', 'intranet', $cgi);
+ my $template = C4::Templates::gettemplate('acqui/csv/basketgroup.tt', 'intranet', $cgi);
my @rows;
for my $basket (@$baskets) {
- my @orders = GetOrders( $$basket{basketno} );
- my $contract = GetContract( $$basket{contractnumber} );
- my $bookseller = GetBookSellerFromId( $$basket{booksellerid} );
+ my @orders = GetOrders( $basket->{basketno} );
+ my $contract = GetContract({
+ contractnumber => $basket->{contractnumber}
+ });
+ my $bookseller = Koha::Acquisition::Bookseller->fetch({ id => $basket->{booksellerid} });
my $basketgroup = GetBasketgroup( $$basket{basketgroupid} );
foreach my $order (@orders) {
rrp => $order->{rrp},
discount => $bookseller->{discount},
ecost => $order->{ecost},
- notes => $order->{notes},
+ notes => $order->{order_vendornote},
entrydate => $order->{entrydate},
booksellername => $bookseller->{name},
bookselleraddress => $bookseller->{address1},
return unless $supplierid;
my $dbh = C4::Context->dbh;
- my $query = qq{
+ my $query = q{
SELECT aqbasket.*,
SUM(aqorders.quantity) AS total_items,
+ SUM(
+ IF ( aqorders.orderstatus = 'cancelled', aqorders.quantity, 0 )
+ ) AS total_items_cancelled,
COUNT(DISTINCT aqorders.biblionumber) AS total_biblios,
SUM(
IF(aqorders.datereceived IS NULL
FROM aqbasket
LEFT JOIN aqorders ON aqorders.basketno = aqbasket.basketno
WHERE booksellerid = ?};
- if(!$allbaskets) {
+
+ unless ( $allbaskets ) {
$query.=" AND (closedate IS NULL OR (aqorders.quantity > aqorders.quantityreceived AND datecancellationprinted IS NULL))";
}
$query.=" GROUP BY aqbasket.basketno";
my $sth = $dbh->prepare($query);
$sth->execute($supplierid);
- return $sth->fetchall_arrayref({});
+ my $baskets = $sth->fetchall_arrayref({});
+
+ # Retrieve the number of biblios cancelled
+ my $cancelled_biblios = $dbh->selectall_hashref( q|
+ SELECT COUNT(DISTINCT(biblionumber)) AS total_biblios_cancelled, aqbasket.basketno
+ FROM aqbasket
+ LEFT JOIN aqorders ON aqorders.basketno = aqbasket.basketno
+ WHERE booksellerid = ?
+ AND aqorders.orderstatus = 'cancelled'
+ GROUP BY aqbasket.basketno
+ |, 'basketno', {}, $supplierid );
+ map {
+ $_->{total_biblios_cancelled} = $cancelled_biblios->{$_->{basketno}}{total_biblios_cancelled} || 0
+ } @$baskets;
+
+ return $baskets;
}
=head3 GetBasketUsers
$basketgroup = &GetBasketgroup($basketgroupid);
-Returns a reference to the hash containing all infermation about the basketgroup.
+Returns a reference to the hash containing all information about the basketgroup.
=cut
=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.*,
- biblio.title,
+ |;
+ $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);
sub GetOrder {
my ($ordernumber) = @_;
+ return unless $ordernumber;
+
my $dbh = C4::Context->dbh;
my $query = qq{SELECT
aqorders.*,
LIMIT 1
|;
my $result_set =
- $dbh->selectall_arrayref( $query, { Slice => {} }, $subscriptionid );
+ $dbh->selectall_arrayref( $query, { Slice => {} }, $subscriptionid, $subscriptionid );
# result_set assumed to contain 1 match
return $result_set->[0];
}
-
-#------------------------------------------------------------#
-
-=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", "notes", "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
#------------------------------------------------------------#
-=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($biblionumber, $ordernumber, $quantityreceived, $user,
- $cost, $ecost, $invoiceid, rrp, budget_id, datereceived, \@received_itemnumbers);
+ &ModReceiveOrder({
+ biblionumber => $biblionumber,
+ ordernumber => $ordernumber,
+ quantityreceived => $quantityreceived,
+ user => $user,
+ cost => $cost,
+ ecost => $ecost,
+ invoiceid => $invoiceid,
+ rrp => $rrp,
+ budget_id => $budget_id,
+ datereceived => $datereceived,
+ received_itemnumbers => \@received_itemnumbers,
+ order_internalnote => $order_internalnote,
+ order_vendornote => $order_vendornote,
+ });
Updates an order, to reflect the fact that it was received, at least
in part. All arguments not mentioned below update the fields with the
sub ModReceiveOrder {
- my (
- $biblionumber, $ordernumber, $quantrec, $user, $cost, $ecost,
- $invoiceid, $rrp, $budget_id, $datereceived, $received_items
- )
- = @_;
+ my ( $params ) = @_;
+ my $biblionumber = $params->{biblionumber};
+ my $ordernumber = $params->{ordernumber};
+ my $quantrec = $params->{quantityreceived};
+ my $user = $params->{user};
+ my $cost = $params->{cost};
+ my $ecost = $params->{ecost};
+ my $invoiceid = $params->{invoiceid};
+ my $rrp = $params->{rrp};
+ my $budget_id = $params->{budget_id};
+ my $datereceived = $params->{datereceived};
+ my $received_items = $params->{received_items};
+ my $order_internalnote = $params->{order_internalnote};
+ 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,
# without received items (the quantity is decreased),
# the second part is a new order line with quantity=quantityrec
# (entirely received)
- my $sth=$dbh->prepare("
+ my $query = q|
UPDATE aqorders
SET quantity = ?,
- orderstatus = 'partial'
- WHERE ordernumber = ?
- ");
+ orderstatus = 'partial'|;
+ $query .= q|, order_internalnote = ?| if defined $order_internalnote;
+ $query .= q|, order_vendornote = ?| if defined $order_vendornote;
+ $query .= q| WHERE ordernumber = ?|;
+ my $sth = $dbh->prepare($query);
- $sth->execute($order->{quantity} - $quantrec, $ordernumber);
+ $sth->execute(
+ $order->{quantity} - $quantrec,
+ ( defined $order_internalnote ? $order_internalnote : () ),
+ ( defined $order_vendornote ? $order_vendornote : () ),
+ $ordernumber
+ );
delete $order->{'ordernumber'};
$order->{'budget_id'} = ( $budget_id || $order->{'budget_id'} );
$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) {
}
}
} else {
- my $sth=$dbh->prepare("update aqorders
- set quantityreceived=?,datereceived=?,invoiceid=?,
- unitprice=?,rrp=?,ecost=?,budget_id=?,orderstatus='complete'
- where biblionumber=? and ordernumber=?");
- $sth->execute($quantrec,$datereceived,$invoiceid,$cost,$rrp,$ecost,$budget_id,$biblionumber,$ordernumber);
+ my $query = q|
+ update aqorders
+ set quantityreceived=?,datereceived=?,invoiceid=?,
+ unitprice=?,rrp=?,ecost=?,budget_id=?,orderstatus='complete'|;
+ $query .= q|, order_internalnote = ?| if defined $order_internalnote;
+ $query .= q|, order_vendornote = ?| if defined $order_vendornote;
+ $query .= q| where biblionumber=? and ordernumber=?|;
+ my $sth = $dbh->prepare( $query );
+ $sth->execute(
+ $quantrec,
+ $datereceived,
+ $invoiceid,
+ $cost,
+ $rrp,
+ $ecost,
+ ( $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);
}
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{
};
$sth = $dbh->prepare($query);
$sth->execute(0, undef, undef, $ordernumber);
+ _cancel_items_receipt( $ordernumber );
} else {
# The order line has a parent, increase parent quantity and delete
# the order line.
" receipt";
return;
}
- if(C4::Context->preference('AcqCreateItem') eq 'receiving') {
- # Remove items that were created at receipt
- $query = qq{
- DELETE FROM items, aqorders_items
- USING items, aqorders_items
- WHERE items.itemnumber = ? AND aqorders_items.itemnumber = ?
- };
- $sth = $dbh->prepare($query);
- my @itemnumbers = GetItemnumbersFromOrder($ordernumber);
- foreach my $itemnumber (@itemnumbers) {
- $sth->execute($itemnumber, $itemnumber);
- }
- } else {
- # Update items
- my @itemnumbers = GetItemnumbersFromOrder($ordernumber);
- foreach my $itemnumber (@itemnumbers) {
- ModItemOrder($itemnumber, $parent_ordernumber);
- }
- }
+ _cancel_items_receipt( $ordernumber, $parent_ordernumber );
# Delete order line
$query = qq{
DELETE FROM aqorders
}
+ 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;
}
+sub _cancel_items_receipt {
+ my ( $ordernumber, $parent_ordernumber ) = @_;
+ $parent_ordernumber ||= $ordernumber;
+
+ my @itemnumbers = GetItemnumbersFromOrder($ordernumber);
+ if(C4::Context->preference('AcqCreateItem') eq 'receiving') {
+ # Remove items that were created at receipt
+ my $query = qq{
+ DELETE FROM items, aqorders_items
+ USING items, aqorders_items
+ WHERE items.itemnumber = ? AND aqorders_items.itemnumber = ?
+ };
+ my $dbh = C4::Context->dbh;
+ my $sth = $dbh->prepare($query);
+ foreach my $itemnumber (@itemnumbers) {
+ $sth->execute($itemnumber, $itemnumber);
+ }
+ } else {
+ # Update items
+ foreach my $itemnumber (@itemnumbers) {
+ ModItemOrder($itemnumber, $parent_ordernumber);
+ }
+ }
+}
+
#------------------------------------------------------------#
=head3 SearchOrders
basketno => $basketno,
owner => $owner,
pending => $pending
+ ordered => $ordered
});
Searches for orders.
C<$owner> Finds order for the logged in user.
C<$pending> Finds pending orders. Ignores completed and cancelled orders.
+C<$ordered> Finds orders to receive only (status 'ordered' or 'partial').
C<@results> is an array of references-to-hash with the keys are fields
my $basketgroupname = $params->{basketgroupname};
my $owner = $params->{owner};
my $pending = $params->{pending};
+ my $ordered = $params->{ordered};
+ my $biblionumber = $params->{biblionumber};
+ my $budget_id = $params->{budget_id};
my $dbh = C4::Context->dbh;
my @args = ();
biblio.*,
biblioitems.isbn,
biblioitems.biblioitemnumber,
+ aqbasket.authorisedby,
+ aqbasket.booksellerid,
aqbasket.closedate,
aqbasket.creationdate,
aqbasket.basketname,
LEFT JOIN borrowers ON aqbasket.authorisedby=borrowers.borrowernumber
LEFT JOIN biblio ON aqorders.biblionumber=biblio.biblionumber
LEFT JOIN biblioitems ON biblioitems.biblionumber=biblio.biblionumber
- WHERE (datecancellationprinted is NULL)
};
+ # If we search on ordernumber, we retrieve the transferred order if a transfer has been done.
$query .= q{
- AND (quantity > quantityreceived OR quantityreceived is NULL)
- } if $pending;
+ LEFT JOIN aqorders_transfers ON aqorders_transfers.ordernumber_to = aqorders.ordernumber
+ } if $ordernumber;
+
+ $query .= q{
+ WHERE (datecancellationprinted is NULL)
+ };
+
+ if ( $pending or $ordered ) {
+ $query .= q{ AND (quantity > quantityreceived OR quantityreceived is NULL)};
+ }
+ if ( $ordered ) {
+ $query .= q{ AND aqorders.orderstatus IN ( "ordered", "partial" )};
+ }
my $userenv = C4::Context->userenv;
if ( C4::Context->preference("IndependentBranches") ) {
}
if ( $ordernumber ) {
- $query .= ' AND (aqorders.ordernumber=?)';
- push @args, $ordernumber;
+ $query .= ' AND ( aqorders.ordernumber = ? OR aqorders_transfers.ordernumber_from = ? ) ';
+ push @args, ( $ordernumber, $ordernumber );
+ }
+ if ( $biblionumber ) {
+ $query .= 'AND aqorders.biblionumber = ?';
+ push @args, $biblionumber;
}
if( $search ) {
$query .= ' AND (biblio.title LIKE ? OR biblio.author LIKE ? OR biblioitems.isbn LIKE ?)';
push @args, $userenv->{'number'};
}
+ if ( $budget_id ) {
+ $query .= ' AND aqorders.budget_id = ?';
+ push @args, $budget_id;
+ }
+
$query .= ' ORDER BY aqbasket.basketno';
my $sth = $dbh->prepare($query);
=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( $dbh, $bibnum, $itemnumber );
+ my $delcheck = C4::Items::DelItemCheck( $dbh, $bibnum, $itemnumber );
+
+ if($delcheck != 1) {
+ $error->{'delitem'} = 1;
+ }
}
- return;
+
+ 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 $error;
}
=head3 TransferOrder
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
$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
=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);
SELECT aqbasket.basketno,
aqorders.ordernumber,
DATE(aqbasket.closedate) AS orderdate,
+ aqbasket.basketname AS basketname,
+ aqbasket.basketgroupid AS basketgroupid,
+ aqbasketgroups.name AS basketgroupname,
aqorders.rrp AS unitpricesupplier,
aqorders.ecost AS unitpricelib,
aqorders.claims_count AS claims_count,
LEFT JOIN aqbudgets ON aqorders.budget_id = aqbudgets.budget_id,
aqbasket LEFT JOIN borrowers ON aqbasket.authorisedby = borrowers.borrowernumber
LEFT JOIN aqbooksellers ON aqbasket.booksellerid = aqbooksellers.id
+ LEFT JOIN aqbasketgroups ON aqbasket.basketgroupid = aqbasketgroups.id
WHERE aqorders.basketno = aqbasket.basketno
AND ( datereceived = ''
OR datereceived IS NULL
$sth->execute(@query_params);
my @results;
while (my $data = $sth->fetchrow_hashref) {
- $data->{orderdate} = format_date($data->{orderdate});
- $data->{claimed_date} = format_date($data->{claimed_date});
push @results, $data;
}
return @results;
=head3 GetHistory
- (\@order_loop, $total_qty, $total_price, $total_qtyreceived) = GetHistory( %params );
+ \@order_loop = GetHistory( %params );
Retreives some acquisition history information
'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
my $orderstatus = $params{orderstatus};
my $biblionumber = $params{biblionumber};
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;
aqorders.basketno,
aqbasket.basketname,
aqbasket.basketgroupid,
+ aqbasket.authorisedby,
+ concat( borrowers.firstname,' ',borrowers.surname) AS authorisedbyname,
aqbasketgroups.name as groupname,
aqbooksellers.name,
aqbasket.creationdate,
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')) {
push @query_params, "%$basketgroupname%";
}
+ if ($ordernumber) {
+ $query .= " AND (aqorders.ordernumber = ? ";
+ push @query_params, $ordernumber;
+ if ($search_children_too) {
+ $query .= " OR aqorders.parent_ordernumber = ? ";
+ push @query_params, $ordernumber;
+ }
+ $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() ) {
$query .= " AND (borrowers.branchcode = ? OR borrowers.branchcode ='' ) ";
}
}
$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
return $results;
}
-=head3 GetContracts
-
- $contractlist = &GetContracts($booksellerid, $activeonly);
-
-Looks up the contracts that belong to a bookseller
-
-Returns a list of contracts
-
-=over
-
-=item C<$booksellerid> is the "id" field in the "aqbooksellers" table.
-
-=item C<$activeonly> if exists get only contracts that are still active.
-
-=back
-
-=cut
-
-sub GetContracts {
- my ( $booksellerid, $activeonly ) = @_;
- my $dbh = C4::Context->dbh;
- my $query;
- if (! $activeonly) {
- $query = "
- SELECT *
- FROM aqcontract
- WHERE booksellerid=?
- ";
- } else {
- $query = "SELECT *
- FROM aqcontract
- WHERE booksellerid=?
- AND contractenddate >= CURDATE( )";
- }
- my $result_set =
- $dbh->selectall_arrayref( $query, { Slice => {} }, $booksellerid );
- return @{$result_set};
-}
-
#------------------------------------------------------------#
-=head3 GetContract
-
- $contract = &GetContract($contractID);
-
-Looks up the contract that has PRIMKEY (contractnumber) value $contractID
-
-Returns a contract
-
-=cut
-
-sub GetContract {
- my ( $contractno ) = @_;
- my $dbh = C4::Context->dbh;
- my $query = "
- SELECT *
- FROM aqcontract
- WHERE contractnumber=?
- ";
-
- my $sth = $dbh->prepare($query);
- $sth->execute( $contractno );
- my $result = $sth->fetchrow_hashref;
- return $result;
-}
-
=head3 AddClaim
-=over
-
-&AddClaim($ordernumber);
+ &AddClaim($ordernumber);
Add a claim for an order
-=back
-
=cut
sub AddClaim {
NULL
)
) AS receivedbiblios,
+ COUNT(
+ DISTINCT IF(
+ aqorders.subscriptionid IS NOT NULL,
+ aqorders.subscriptionid,
+ NULL
+ )
+ ) AS is_linked_to_subscriptions,
SUM(aqorders.quantityreceived) AS receiveditems
FROM aqinvoices
LEFT JOIN aqbooksellers ON aqbooksellers.id = aqinvoices.booksellerid
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);
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
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 $branch = C4::Branch::GetBranchDetail( $borrower->{branchcode} );
+ my $biblio = C4::Biblio::GetBiblio( $order->{biblionumber} );
+ my $letter = C4::Letters::GetPreparedLetter(
+ module => 'acquisition',
+ letter_code => 'ACQ_NOTIF_ON_RECEIV',
+ branchcode => $branch->{branchcode},
+ tables => {
+ 'branches' => $branch,
+ '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 ( subfield_is_koha_internal_p($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__