From 126fb121fc908e2cd4e0ea7aea011b70467cf4cd Mon Sep 17 00:00:00 2001
From: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
Date: Tue, 23 May 2017 10:27:31 -0300
Subject: [PATCH] Bug 18651: Copy the row before modify the id

If the "max(issue_id) from old_issue + 1" already exists in issues, the
move fails.

For instance we have
1, 2, 3, 4 in issues

checkin 4
1, 2, 3 in issues (AI=5)
4 in old_issues

Restart mysql => AI is reset to MAX(issue_id) => 4

checkout a new one
1, 2, 3, 4 in issues (AI=5)
4 in old_issues

checkin 4 (will get id 5 in old_issues)
1, 2, 3 in issues (AI=5)
4, 5 in old_issues

=> This works with and without this patch

Now we have
1, 2, 3 in issues (AI=5)
4, 5 in old_issues

Restart mysql => AI is reset to MAX(issue_id) => 4

checkout 2 new ones
1, 2, 3, 4, 5 in issues (AI=7)
4, 5 in old_issues

checkin 4 (4 becomes 6 in old_issues)
1, 2, 3, 5 in issues (AI=6)
4, 5, 6 in old_issues

=> This did not work without with patch
The update of the issue_id was made before the move (so in the issues
table), the PK did not allow it
---
 C4/Circulation.pm | 31 ++++++++++++++++---------------
 1 file changed, 16 insertions(+), 15 deletions(-)

diff --git a/C4/Circulation.pm b/C4/Circulation.pm
index 7b6a83e09d..49827a86c9 100644
--- a/C4/Circulation.pm
+++ b/C4/Circulation.pm
@@ -2176,30 +2176,31 @@ sub MarkIssueReturned {
         $dbh->do( $query, undef, @bind );
 
         my $original_issue_id = $issue_id;
-        my $id_already_exists = $dbh->selectrow_array(
-            q|SELECT COUNT(*) FROM old_issues WHERE issue_id = ?|,
-            undef, $issue_id
-        );
+        my $issue = Koha::Checkouts->find( $issue_id ); # FIXME should be fetched earlier
 
-        if ( $id_already_exists ) {
-            my $new_issue_id = $dbh->selectrow_array(q|SELECT MAX(issue_id)+1 FROM old_issues|);
-            $dbh->do(
-                q|UPDATE issues SET issue_id = ? WHERE issue_id = ?|,
-                undef, $new_issue_id, $issue_id
-            );
+        # Create the old_issues entry
+        my $old_checkout_data = $issue->unblessed;
+
+        if ( Koha::Old::Checkouts->find( $issue_id ) ) {
+            my $new_issue_id = Koha::Old::Checkouts->search(
+                {},
+                { columns => [ { max_issue_id => { max => 'issue_id' } } ] }
+            )->get_column('max_issue_id') + 1;
             $issue_id = $new_issue_id;
         }
+        $old_checkout_data->{issue_id} = $issue_id;
+        my $old_checkout = Koha::Old::Checkout->new($old_checkout_data)->store;
 
-        $dbh->do(q|INSERT INTO old_issues SELECT * FROM issues WHERE issue_id = ?|, undef, $issue_id);
-
-        $dbh->do(q|UPDATE accountlines SET issue_id = ? WHERE issue_id = ?|, undef, $issue_id, $original_issue_id);
+        # Update the fines
+        $dbh->do(q|UPDATE accountlines SET issue_id = ? WHERE issue_id = ?|, undef, $old_checkout->issue_id, $issue->issue_id);
 
         # anonymise patron checkout immediately if $privacy set to 2 and AnonymousPatron is set to a valid borrowernumber
         if ( $privacy == 2) {
-            $dbh->do(q|UPDATE old_issues SET borrowernumber=? WHERE issue_id = ?|, undef, $anonymouspatron, $issue_id);
+            $dbh->do(q|UPDATE old_issues SET borrowernumber=? WHERE issue_id = ?|, undef, $anonymouspatron, $old_checkout->issue_id);
         }
 
-        $dbh->do(q|DELETE FROM issues WHERE issue_id = ?|, undef, $issue_id);
+        # Delete the issue
+        $issue->delete;
 
         ModItem( { 'onloan' => undef }, undef, $itemnumber );
 
-- 
2.11.0