Bug 10910: Add a warning when deleting a patron with pending suggestions
[koha-ffzg.git] / C4 / Acquisition.pm
index fcd590d..ca6058a 100644 (file)
@@ -20,6 +20,7 @@ package C4::Acquisition;
 
 use Modern::Perl;
 use Carp;
+use Text::CSV_XS;
 use C4::Context;
 use C4::Debug;
 use C4::Suggestions;
@@ -66,11 +67,10 @@ BEGIN {
         &GetBasketgroups &ReOpenBasketgroup
 
         &DelOrder &ModOrder &GetOrder &GetOrders &GetOrdersByBiblionumber
-        &GetLateOrders &GetOrderFromItemnumber
+        &GetOrderFromItemnumber
         &SearchOrders &GetHistory &GetRecentAcqui
         &ModReceiveOrder &CancelReceipt
         &TransferOrder
-        &GetLastOrderNotReceivedFromSubscriptionid &GetLastOrderReceivedFromSubscriptionid
         &ModItemOrder
 
         &GetParcels
@@ -1222,8 +1222,6 @@ sub GetOrder {
                 biblioitems.publishercode,
                 aqorders.rrp              AS unitpricesupplier,
                 aqorders.ecost            AS unitpricelib,
-                aqorders.claims_count     AS claims_count,
-                aqorders.claimed_date     AS claimed_date,
                 aqbudgets.budget_name     AS budget,
                 aqbooksellers.name        AS supplier,
                 aqbooksellers.id          AS supplierid,
@@ -1247,70 +1245,6 @@ sub GetOrder {
     return $result_set->[0];
 }
 
-=head3 GetLastOrderNotReceivedFromSubscriptionid
-
-  $order = &GetLastOrderNotReceivedFromSubscriptionid($subscriptionid);
-
-Returns a reference-to-hash describing the last order not received for a subscription.
-
-=cut
-
-sub GetLastOrderNotReceivedFromSubscriptionid {
-    my ( $subscriptionid ) = @_;
-    my $dbh                = C4::Context->dbh;
-    my $query              = qq|
-        SELECT * FROM aqorders
-        LEFT JOIN subscription
-            ON ( aqorders.subscriptionid = subscription.subscriptionid )
-        WHERE aqorders.subscriptionid = ?
-            AND aqorders.datereceived IS NULL
-        LIMIT 1
-    |;
-    my $result_set =
-      $dbh->selectall_arrayref( $query, { Slice => {} }, $subscriptionid );
-
-    # result_set assumed to contain 1 match
-    return $result_set->[0];
-}
-
-=head3 GetLastOrderReceivedFromSubscriptionid
-
-  $order = &GetLastOrderReceivedFromSubscriptionid($subscriptionid);
-
-Returns a reference-to-hash describing the last order received for a subscription.
-
-=cut
-
-sub GetLastOrderReceivedFromSubscriptionid {
-    my ( $subscriptionid ) = @_;
-    my $dbh                = C4::Context->dbh;
-    my $query              = qq|
-        SELECT * FROM aqorders
-        LEFT JOIN subscription
-            ON ( aqorders.subscriptionid = subscription.subscriptionid )
-        WHERE aqorders.subscriptionid = ?
-            AND aqorders.datereceived =
-                (
-                    SELECT MAX( aqorders.datereceived )
-                    FROM aqorders
-                    LEFT JOIN subscription
-                        ON ( aqorders.subscriptionid = subscription.subscriptionid )
-                        WHERE aqorders.subscriptionid = ?
-                            AND aqorders.datereceived IS NOT NULL
-                )
-        ORDER BY ordernumber DESC
-        LIMIT 1
-    |;
-    my $result_set =
-      $dbh->selectall_arrayref( $query, { Slice => {} }, $subscriptionid, $subscriptionid );
-
-    # result_set assumed to contain 1 match
-    return $result_set->[0];
-
-}
-
-#------------------------------------------------------------#
-
 =head3 ModOrder
 
   &ModOrder(\%hashref);
@@ -1346,7 +1280,7 @@ sub ModOrder {
     foreach my $orderinfokey (grep(!/ordernumber/, keys %$orderinfo)){
         # ... and skip hash entries that are not in the aqorders table
         # FIXME : probably not the best way to do it (would be better to have a correct hash)
-        next unless grep(/^$orderinfokey$/, @$colnames);
+        next unless grep { $_ eq $orderinfokey } @$colnames;
             $query .= "$orderinfokey=?, ";
             push(@params, $orderinfo->{$orderinfokey});
     }
@@ -1395,8 +1329,8 @@ sub ModItemOrder {
             user                 => $user,
             invoice              => $invoice,
             budget_id            => $budget_id,
+            datereceived         => $datereceived,
             received_itemnumbers => \@received_itemnumbers,
-            order_internalnote   => $order_internalnote,
         }
     );
 
@@ -1419,10 +1353,18 @@ sub ModReceiveOrder {
     my $quantrec       = $params->{quantityreceived};
     my $user           = $params->{user};
     my $budget_id      = $params->{budget_id};
+    my $datereceived   = $params->{datereceived};
     my $received_items = $params->{received_items};
 
     my $dbh = C4::Context->dbh;
-    my $datereceived = ( $invoice and $invoice->{datereceived} ) ? $invoice->{datereceived} : dt_from_string;
+    $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,
@@ -1614,48 +1556,50 @@ sub CancelReceipt {
     } else {
         # The order line has a parent, increase parent quantity and delete
         # the order line.
-        $query = qq{
-            SELECT quantity, datereceived
-            FROM aqorders
-            WHERE ordernumber = ?
-        };
-        $sth = $dbh->prepare($query);
-        $sth->execute($parent_ordernumber);
-        my $parent_order = $sth->fetchrow_hashref;
-        unless($parent_order) {
-            warn "Parent order $parent_ordernumber does not exist.";
-            return;
-        }
-        if($parent_order->{'datereceived'}) {
-            warn "CancelReceipt: parent order is received.".
-                " Can't cancel receipt.";
-            return;
-        }
-        $query = qq{
-            UPDATE aqorders
-            SET quantity = ?,
-                orderstatus = 'ordered'
-            WHERE ordernumber = ?
-        };
-        $sth = $dbh->prepare($query);
-        my $rv = $sth->execute(
-            $order->{'quantity'} + $parent_order->{'quantity'},
-            $parent_ordernumber
-        );
-        unless($rv) {
-            warn "Cannot update parent order line, so do not cancel".
-                " receipt";
-            return;
-        }
+        unless ( $order_obj->basket->is_standing ) {
+            $query = qq{
+                SELECT quantity, datereceived
+                FROM aqorders
+                WHERE ordernumber = ?
+            };
+            $sth = $dbh->prepare($query);
+            $sth->execute($parent_ordernumber);
+            my $parent_order = $sth->fetchrow_hashref;
+            unless($parent_order) {
+                warn "Parent order $parent_ordernumber does not exist.";
+                return;
+            }
+            if($parent_order->{'datereceived'}) {
+                warn "CancelReceipt: parent order is received.".
+                    " Can't cancel receipt.";
+                return;
+            }
+            $query = qq{
+                UPDATE aqorders
+                SET quantity = ?,
+                    orderstatus = 'ordered'
+                WHERE ordernumber = ?
+            };
+            $sth = $dbh->prepare($query);
+            my $rv = $sth->execute(
+                $order->{'quantity'} + $parent_order->{'quantity'},
+                $parent_ordernumber
+            );
+            unless($rv) {
+                warn "Cannot update parent order line, so do not cancel".
+                    " receipt";
+                return;
+            }
 
-        # Recalculate tax_value
-        $dbh->do(q|
-            UPDATE aqorders
-            SET
-                tax_value_on_ordering = quantity * | . get_rounding_sql(q|ecost_tax_excluded|) . q| * tax_rate_on_ordering,
-                tax_value_on_receiving = quantity * | . get_rounding_sql(q|unitprice_tax_excluded|) . q| * tax_rate_on_receiving
-            WHERE ordernumber = ?
-        |, undef, $parent_ordernumber);
+            # Recalculate tax_value
+            $dbh->do(q|
+                UPDATE aqorders
+                SET
+                    tax_value_on_ordering = quantity * | . get_rounding_sql(q|ecost_tax_excluded|) . q| * tax_rate_on_ordering,
+                    tax_value_on_receiving = quantity * | . get_rounding_sql(q|unitprice_tax_excluded|) . q| * tax_rate_on_receiving
+                WHERE ordernumber = ?
+            |, undef, $parent_ordernumber);
+        }
 
         _cancel_items_receipt( $order_obj, $parent_ordernumber );
         # Delete order line
@@ -1916,9 +1860,9 @@ sub DelOrder {
     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 );
+        my $delcheck = $item->safe_delete;
 
-        if($delcheck != 1) {
+        if($delcheck ne '1') {
             $error->{'delitem'} = 1;
         }
     }
@@ -2129,131 +2073,6 @@ sub GetParcels {
 
 #------------------------------------------------------------#
 
-=head3 GetLateOrders
-
-  @results = &GetLateOrders;
-
-Searches for bookseller with late orders.
-
-return:
-the table of supplier with late issues. This table is full of hashref.
-
-=cut
-
-sub GetLateOrders {
-    my $delay      = shift;
-    my $supplierid = shift;
-    my $branch     = shift;
-    my $estimateddeliverydatefrom = shift;
-    my $estimateddeliverydateto = shift;
-
-    my $dbh = C4::Context->dbh;
-
-    #BEWARE, order of parenthesis and LEFT JOIN is important for speed
-    my $dbdriver = C4::Context->config("db_scheme") || "mysql";
-
-    my @query_params = ();
-    my $select = "
-    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,
-        aqorders.claimed_date     AS claimed_date,
-        aqbudgets.budget_name     AS budget,
-        borrowers.branchcode      AS branch,
-        aqbooksellers.name        AS supplier,
-        aqbooksellers.id          AS supplierid,
-        biblio.author, biblio.title,
-        biblioitems.publishercode AS publisher,
-        biblioitems.publicationyear,
-        ADDDATE(aqbasket.closedate, INTERVAL aqbooksellers.deliverytime DAY) AS estimateddeliverydate,
-    ";
-    my $from = "
-    FROM
-        aqorders LEFT JOIN biblio     ON biblio.biblionumber         = aqorders.biblionumber
-        LEFT JOIN biblioitems         ON biblioitems.biblionumber    = biblio.biblionumber
-        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 IS NULL
-            OR aqorders.quantityreceived < aqorders.quantity
-        )
-        AND aqbasket.closedate IS NOT NULL
-        AND aqorders.datecancellationprinted IS NULL
-    ";
-    if ($dbdriver eq "mysql") {
-        $select .= "
-        aqorders.quantity - COALESCE(aqorders.quantityreceived,0)                 AS quantity,
-        (aqorders.quantity - COALESCE(aqorders.quantityreceived,0)) * aqorders.rrp AS subtotal,
-        DATEDIFF(CAST(now() AS date),closedate) AS latesince
-        ";
-        if ( defined $delay ) {
-            $from .= " AND (closedate <= DATE_SUB(CAST(now() AS date),INTERVAL ? DAY)) " ;
-            push @query_params, $delay;
-        }
-        $from .= " AND aqorders.quantity - COALESCE(aqorders.quantityreceived,0) <> 0";
-    } else {
-        # FIXME: account for IFNULL as above
-        $select .= "
-                aqorders.quantity                AS quantity,
-                aqorders.quantity * aqorders.rrp AS subtotal,
-                (CAST(now() AS date) - closedate)            AS latesince
-        ";
-        if ( defined $delay ) {
-            $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 = ? ';
-        push @query_params, $supplierid;
-    }
-    if (defined $branch) {
-        $from .= ' AND borrowers.branchcode LIKE ? ';
-        push @query_params, $branch;
-    }
-
-    if ( defined $estimateddeliverydatefrom or defined $estimateddeliverydateto ) {
-        $from .= ' AND aqbooksellers.deliverytime IS NOT NULL ';
-    }
-    if ( defined $estimateddeliverydatefrom ) {
-        $from .= ' AND ADDDATE(aqbasket.closedate, INTERVAL aqbooksellers.deliverytime DAY) >= ?';
-        push @query_params, $estimateddeliverydatefrom;
-    }
-    if ( defined $estimateddeliverydateto ) {
-        $from .= ' AND ADDDATE(aqbasket.closedate, INTERVAL aqbooksellers.deliverytime DAY) <= ?';
-        push @query_params, $estimateddeliverydateto;
-    }
-    if ( defined $estimateddeliverydatefrom and not defined $estimateddeliverydateto ) {
-        $from .= ' AND ADDDATE(aqbasket.closedate, INTERVAL aqbooksellers.deliverytime DAY) <= CAST(now() AS date)';
-    }
-    if (C4::Context->preference("IndependentBranches")
-            && !C4::Context->IsSuperLibrarian() ) {
-        $from .= ' AND borrowers.branchcode LIKE ? ';
-        push @query_params, C4::Context->userenv->{branch};
-    }
-    $from .= " AND orderstatus <> 'cancelled' ";
-    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);
-    my @results;
-    while (my $data = $sth->fetchrow_hashref) {
-        push @results, $data;
-    }
-    return @results;
-}
-
-#------------------------------------------------------------#
-
 =head3 GetHistory
 
   \@order_loop = GetHistory( %params );
@@ -2689,7 +2508,7 @@ sub GetInvoices {
 
     if($args{order_by}) {
         my ($column, $direction) = split / /, $args{order_by};
-        if(grep /^$column$/, @columns) {
+        if(grep  { $_ eq $column } @columns) {
             $direction ||= 'ASC';
             $query .= " ORDER BY $column $direction";
         }
@@ -2813,7 +2632,7 @@ sub AddInvoice {
     my @set_strs;
     my @set_args;
     foreach my $key (keys %invoice) {
-        if(0 < grep(/^$key$/, @columns)) {
+        if(0 < grep { $_ eq $key } @columns) {
             push @set_strs, "$key = ?";
             push @set_args, ($invoice{$key} || undef);
         }
@@ -2863,7 +2682,7 @@ sub ModInvoice {
     my @set_strs;
     my @set_args;
     foreach my $key (keys %invoice) {
-        if(0 < grep(/^$key$/, @columns)) {
+        if(0 < grep { $_ eq $key } @columns) {
             push @set_strs, "$key = ?";
             push @set_args, ($invoice{$key} || undef);
         }
@@ -3245,16 +3064,20 @@ sub NotifyOrderUsers {
 
 =head3 FillWithDefaultValues
 
-FillWithDefaultValues( $marc_record );
+FillWithDefaultValues( $marc_record, $params );
 
 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.
 
+If the parameter only_mandatory => 1 is passed via $params, only the mandatory
+defaults are being applied to the record.
+
 =cut
 
 sub FillWithDefaultValues {
-    my ($record) = @_;
+    my ( $record, $params ) = @_;
+    my $mandatory = $params->{only_mandatory};
     my $tagslib = C4::Biblio::GetMarcStructure( 1, 'ACQ', { unsafe => 1 } );
     if ($tagslib) {
         my ($itemfield) =
@@ -3264,23 +3087,36 @@ sub FillWithDefaultValues {
             next if $tag == $itemfield;
             for my $subfield ( sort keys %{ $tagslib->{$tag} } ) {
                 next if IsMarcStructureInternal($tagslib->{$tag}{$subfield});
+                next if $mandatory && !$tagslib->{$tag}{$subfield}{mandatory};
                 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) ) {
+                            if ( $field->is_control_field ) {
+                                $field->update($defaultvalue) if not defined $field->data;
+                            }
+                            elsif ( not defined $field->subfield($subfield) ) {
                                 $field->add_subfields(
                                     $subfield => $defaultvalue );
                             }
                         }
                     }
                     else {
-                        $record->insert_fields_ordered(
-                            MARC::Field->new(
-                                $tag, '', '', $subfield => $defaultvalue
-                            )
-                        );
+                        if ( $tag < 10 ) { # is_control_field
+                            $record->insert_fields_ordered(
+                                MARC::Field->new(
+                                    $tag, $defaultvalue
+                                )
+                            );
+                        }
+                        else {
+                            $record->insert_fields_ordered(
+                                MARC::Field->new(
+                                    $tag, '', '', $subfield => $defaultvalue
+                                )
+                            );
+                        }
                     }
                 }
             }