View | Details | Raw Unified | Return to bug 41801
Collapse All | Expand All

(-)a/C4/Reserves.pm (-86 / +92 lines)
Lines 1662-1762 priority adjusted to ensure that they remain at the end of the line. Link Here
1662
=cut
1662
=cut
1663
1663
1664
sub FixPriority {
1664
sub FixPriority {
1665
    my ($params)     = @_;
1665
    my ($params) = @_;
1666
    my $reserve_id   = $params->{reserve_id};
1667
    my $rank         = $params->{rank} // '';
1668
    my $biblionumber = $params->{biblionumber};
1669
1670
    my $dbh = C4::Context->dbh;
1671
1666
1672
    my $hold;
1667
    Koha::Database->new->schema->txn_do(
1673
    if ($reserve_id) {
1668
        sub {
1674
        $hold = Koha::Holds->find($reserve_id);
1669
            my $reserve_id   = $params->{reserve_id};
1675
        if ( !defined $hold ) {
1670
            my $rank         = $params->{rank} // '';
1671
            my $biblionumber = $params->{biblionumber};
1676
1672
1677
            # may have already been checked out and hold fulfilled
1673
            my $dbh = C4::Context->dbh;
1678
            require Koha::Old::Holds;
1679
            $hold = Koha::Old::Holds->find($reserve_id);
1680
        }
1681
        return unless $hold;
1682
    }
1683
1674
1684
    unless ($biblionumber) {    # FIXME This is a very weird API
1675
            my $hold;
1685
        $biblionumber = $hold->biblionumber;
1676
            if ($reserve_id) {
1686
    }
1677
                $hold = Koha::Holds->find($reserve_id);
1678
                if ( !defined $hold ) {
1687
1679
1688
    if ( $rank eq "del" ) {     # FIXME will crash if called without $hold
1680
                    # may have already been checked out and hold fulfilled
1689
        $hold->cancel;
1681
                    require Koha::Old::Holds;
1690
    } elsif ( $reserve_id && ( $rank eq "W" || $rank eq "0" ) ) {
1682
                    $hold = Koha::Old::Holds->find($reserve_id);
1691
1683
                }
1692
        # make sure priority for waiting or in-transit items is 0
1684
                return unless $hold;
1693
        my $query = "
1685
            }
1694
            UPDATE reserves
1695
            SET    priority = 0
1696
            WHERE reserve_id = ?
1697
            AND found IN ('W', 'T', 'P')
1698
        ";
1699
        my $sth = $dbh->prepare($query);
1700
        $sth->execute($reserve_id);
1701
    }
1702
    my @priority;
1703
1686
1704
    # get what's left, sorting lowestPriority holds to the bottom
1687
            unless ($biblionumber) {    # FIXME This is a very weird API
1705
    my $query = "
1688
                $biblionumber = $hold->biblionumber;
1706
        SELECT reserve_id, borrowernumber, reservedate, lowestPriority
1689
            }
1707
        FROM   reserves
1708
        WHERE  biblionumber   = ?
1709
          AND  ((found <> 'W' AND found <> 'T' AND found <> 'P') OR found IS NULL)
1710
        ORDER BY lowestPriority ASC, priority ASC
1711
    ";
1712
    my $sth = $dbh->prepare($query);
1713
    $sth->execute($biblionumber);
1714
    while ( my $line = $sth->fetchrow_hashref ) {
1715
        push( @priority, $line );
1716
    }
1717
1690
1718
    # FIXME This whole sub must be rewritten, especially to highlight what is done when reserve_id is not given
1691
            if ( $rank eq "del" ) {     # FIXME will crash if called without $hold
1719
    # To find the matching index
1692
                $hold->cancel;
1720
    my $i;
1693
            } elsif ( $reserve_id && ( $rank eq "W" || $rank eq "0" ) ) {
1721
    my $key = -1;    # to allow for 0 to be a valid result
1694
1722
    for ( $i = 0 ; $i < @priority ; $i++ ) {
1695
                # make sure priority for waiting or in-transit items is 0
1723
        if ( $reserve_id && $reserve_id == $priority[$i]->{'reserve_id'} ) {
1696
                my $query = "
1724
            $key = $i;    # save the index
1697
                    UPDATE reserves
1725
            last;
1698
                    SET    priority = 0
1726
        }
1699
                    WHERE reserve_id = ?
1727
    }
1700
                    AND found IN ('W', 'T', 'P')
1701
                ";
1702
                my $sth = $dbh->prepare($query);
1703
                $sth->execute($reserve_id);
1704
            }
1705
            my @priority;
1706
1707
            # Lock all active holds for this bib so concurrent FixPriority calls
1708
            # for the same hold set cannot interleave their read-modify-write cycle.
1709
            # FOR UPDATE is effective inside the enclosing txn_do transaction.
1710
            my $query = "
1711
                SELECT reserve_id, borrowernumber, reservedate, lowestPriority
1712
                FROM   reserves
1713
                WHERE  biblionumber   = ?
1714
                  AND  ((found <> 'W' AND found <> 'T' AND found <> 'P') OR found IS NULL)
1715
                ORDER BY lowestPriority ASC, priority ASC
1716
                FOR UPDATE
1717
            ";
1718
            my $sth = $dbh->prepare($query);
1719
            $sth->execute($biblionumber);
1720
            while ( my $line = $sth->fetchrow_hashref ) {
1721
                push( @priority, $line );
1722
            }
1728
1723
1729
    # if this hold is marked lowest priority, we can only move it so far;
1724
            # FIXME This whole sub must be rewritten, especially to highlight what is done when reserve_id is not given
1730
    # cap rank to just after the last non-lowestPriority hold using the
1725
            # To find the matching index
1731
    # already-fetched @priority array (avoids a second DB query and stale data)
1726
            my $i;
1732
    if ( $hold && $hold->lowestPriority && $rank ne 'del' && $rank > 0 ) {
1727
            my $key = -1;    # to allow for 0 to be a valid result
1733
        my $non_lowest_count = scalar grep { !$_->{lowestPriority} } @priority;
1728
            for ( $i = 0 ; $i < @priority ; $i++ ) {
1734
        $rank = $non_lowest_count + 1 if $non_lowest_count && $rank <= $non_lowest_count;
1729
                if ( $reserve_id && $reserve_id == $priority[$i]->{'reserve_id'} ) {
1735
    }
1730
                    $key = $i;    # save the index
1731
                    last;
1732
                }
1733
            }
1736
1734
1737
    # if index exists in array then move it to new position
1735
            # if this hold is marked lowest priority, we can only move it so far;
1738
    if ( $key > -1 && $rank ne 'del' && $rank > 0 ) {
1736
            # cap rank to just after the last non-lowestPriority hold using the
1739
        my $new_rank    = $rank - 1;                      # $new_rank is what you want the new index to be in the array
1737
            # already-fetched @priority array (avoids a second DB query and stale data)
1740
        my $moving_item = splice( @priority, $key, 1 );
1738
            if ( $hold && $hold->lowestPriority && $rank ne 'del' && $rank > 0 ) {
1741
        $new_rank = scalar @priority if $new_rank > scalar @priority;
1739
                my $non_lowest_count = scalar grep { !$_->{lowestPriority} } @priority;
1742
        splice( @priority, $new_rank, 0, $moving_item );
1740
                $rank = $non_lowest_count + 1 if $non_lowest_count && $rank <= $non_lowest_count;
1743
    }
1741
            }
1744
1742
1745
    # now fix the priority on those that are left....
1743
            # if index exists in array then move it to new position
1746
    # only updating if changed
1744
            if ( $key > -1 && $rank ne 'del' && $rank > 0 ) {
1747
    $query = "
1745
                my $new_rank    = $rank - 1;    # $new_rank is what you want the new index to be in the array
1748
        UPDATE reserves
1746
                my $moving_item = splice( @priority, $key, 1 );
1749
        SET    priority = ?
1747
                $new_rank = scalar @priority if $new_rank > scalar @priority;
1750
        WHERE  reserve_id = ? AND priority != ?
1748
                splice( @priority, $new_rank, 0, $moving_item );
1751
    ";
1749
            }
1752
    $sth = $dbh->prepare($query);
1753
    for ( my $j = 0 ; $j < @priority ; $j++ ) {
1754
        $sth->execute(
1755
            $j + 1,
1756
            $priority[$j]->{'reserve_id'}, $j + 1
1757
        );
1758
    }
1759
1750
1751
            # now fix the priority on those that are left....
1752
            # only updating if changed
1753
            $query = "
1754
                UPDATE reserves
1755
                SET    priority = ?
1756
                WHERE  reserve_id = ? AND priority != ?
1757
            ";
1758
            $sth = $dbh->prepare($query);
1759
            for ( my $j = 0 ; $j < @priority ; $j++ ) {
1760
                $sth->execute(
1761
                    $j + 1,
1762
                    $priority[$j]->{'reserve_id'}, $j + 1
1763
                );
1764
            }
1765
        }
1766
    );
1760
}
1767
}
1761
1768
1762
=head2 _Findgroupreserve
1769
=head2 _Findgroupreserve
1763
- 

Return to bug 41801