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

(-)a/C4/Items.pm (-37 / +16 lines)
Lines 72-77 use Koha::AuthorisedValues; Link Here
72
use Koha::DateUtils qw(dt_from_string);
72
use Koha::DateUtils qw(dt_from_string);
73
use Koha::Database;
73
use Koha::Database;
74
74
75
use Koha::Biblios;
75
use Koha::Biblioitems;
76
use Koha::Biblioitems;
76
use Koha::Items;
77
use Koha::Items;
77
use Koha::ItemTypes;
78
use Koha::ItemTypes;
Lines 1652-1658 sub _koha_new_item { Link Here
1652
1653
1653
=head2 MoveItemFromBiblio
1654
=head2 MoveItemFromBiblio
1654
1655
1655
  MoveItemFromBiblio($itenumber, $frombiblio, $tobiblio);
1656
  MoveItemFromBiblio($itemnumber, $frombiblio, $tobiblio);
1656
1657
1657
Moves an item from a biblio to another
1658
Moves an item from a biblio to another
1658
1659
Lines 1662-1703 Returns undef if the move failed or the biblionumber of the destination record o Link Here
1662
1663
1663
sub MoveItemFromBiblio {
1664
sub MoveItemFromBiblio {
1664
    my ($itemnumber, $frombiblio, $tobiblio) = @_;
1665
    my ($itemnumber, $frombiblio, $tobiblio) = @_;
1665
    my $dbh = C4::Context->dbh;
1666
1666
    my ( $tobiblioitem ) = $dbh->selectrow_array(q|
1667
    my $item = Koha::Items->find($itemnumber);
1667
        SELECT biblioitemnumber
1668
    return unless $item;
1668
        FROM biblioitems
1669
1669
        WHERE biblionumber = ?
1670
    my $biblio = Koha::Biblios->find($tobiblio);
1670
    |, undef, $tobiblio );
1671
    return unless $biblio;
1671
    my $return = $dbh->do(q|
1672
1672
        UPDATE items
1673
    return unless $item->biblionumber != $biblio->biblionumber;
1673
        SET biblioitemnumber = ?,
1674
1674
            biblionumber = ?
1675
    $item->move_to_biblio($biblio);
1675
        WHERE itemnumber = ?
1676
    ModZebra($tobiblio, 'specialUpdate', 'biblioserver');
1676
            AND biblionumber = ?
1677
    ModZebra($frombiblio, 'specialUpdate', 'biblioserver');
1677
    |, undef, $tobiblioitem, $tobiblio, $itemnumber, $frombiblio );
1678
1678
    if ($return == 1) {
1679
    return $tobiblio;
1679
        ModZebra( $tobiblio, "specialUpdate", "biblioserver" );
1680
        ModZebra( $frombiblio, "specialUpdate", "biblioserver" );
1681
	    # Checking if the item we want to move is in an order 
1682
        require C4::Acquisition;
1683
        my $order = C4::Acquisition::GetOrderFromItemnumber($itemnumber);
1684
	    if ($order) {
1685
		    # Replacing the biblionumber within the order if necessary
1686
		    $order->{'biblionumber'} = $tobiblio;
1687
	        C4::Acquisition::ModOrder($order);
1688
	    }
1689
1690
        # Update reserves, hold_fill_targets, tmp_holdsqueue and linktracker tables
1691
        for my $table_name ( qw( reserves hold_fill_targets tmp_holdsqueue linktracker ) ) {
1692
            $dbh->do( qq|
1693
                UPDATE $table_name
1694
                SET biblionumber = ?
1695
                WHERE itemnumber = ?
1696
            |, undef, $tobiblio, $itemnumber );
1697
        }
1698
        return $tobiblio;
1699
	}
1700
    return;
1701
}
1680
}
1702
1681
1703
=head2 ItemSafeToDelete
1682
=head2 ItemSafeToDelete
(-)a/Koha/Biblio.pm (+22 lines)
Lines 815-820 sub to_api_mapping { Link Here
815
    };
815
    };
816
}
816
}
817
817
818
=head3 adopt_items_from_biblio
819
820
$biblio->adopt_items_from_biblio($from_biblio);
821
822
Move items from the given biblio to this one.
823
824
=cut
825
826
sub adopt_items_from_biblio {
827
    my ( $self, $from_biblio ) = @_;
828
829
    my $items = $from_biblio->items;
830
    if ($items) {
831
        while (my $item = $items->next()) {
832
            $item->move_to_biblio($self);
833
        }
834
        C4::Biblio::ModZebra( $self->biblionumber, "specialUpdate", "biblioserver" );
835
        C4::Biblio::ModZebra( $from_biblio->biblionumber, "specialUpdate", "biblioserver" );
836
    }
837
}
838
839
818
=head2 Internal methods
840
=head2 Internal methods
819
841
820
=head3 type
842
=head3 type
(-)a/Koha/Item.pm (+56 lines)
Lines 547-552 sub to_api_mapping { Link Here
547
    };
547
    };
548
}
548
}
549
549
550
=head3 move_to_biblio
551
552
  $item->move_to_biblio($to_biblio);
553
554
Move the item to another biblio and update any references also in other tables.
555
556
=cut
557
558
sub move_to_biblio {
559
    my ( $self, $to_biblio ) = @_;
560
561
    my $biblionumber = $to_biblio->biblionumber;
562
563
    # Own biblionumber and biblioitemnumber
564
    $self->set({
565
        biblionumber => $biblionumber,
566
        biblioitemnumber => $to_biblio->biblioitem->biblioitemnumber
567
    })->store();
568
569
    my $schema = Koha::Database->new()->schema();
570
571
    # Acquisition orders related to the item
572
    my $orders = $schema->resultset('Aqorder')->search(
573
        { itemnumber => $self->itemnumber },
574
        { join => 'aqorders_items'}
575
    );
576
    $orders->update_all({ biblionumber => $biblionumber });
577
578
    # reserves
579
    my $reserves = $self->_result->reserves;
580
    $reserves->update_all({ biblionumber => $biblionumber });
581
582
    # hold_fill_target
583
    my $hold_fill_target = $self->_result->hold_fill_target;
584
    if ($hold_fill_target) {
585
        $hold_fill_target->update({ biblionumber => $biblionumber });
586
    }
587
588
    # tmp_holdsqueues - Can't update with DBIx since the table is missing a primary key
589
    # and can't even fake one since the significant columns are nullable.
590
    my $storage = $self->_result->result_source->storage;
591
    $storage->dbh_do(
592
        sub {
593
            my ($storage, $dbh, @cols) = @_;
594
595
            $dbh->do("UPDATE tmp_holdsqueue SET biblionumber=? WHERE itemnumber=?", undef, $biblionumber, $self->itemnumber);
596
        }
597
    );
598
    #my $tmp_holdsqueues = $self->_result->tmp_holdsqueues;
599
    #$tmp_holdsqueues->update_all({ biblionumber => $biblionumber });
600
601
    # linktrackers
602
    my $linktrackers = $schema->resultset('Linktracker')->search({ itemnumber => $self->itemnumber });
603
    $linktrackers->update_all({ biblionumber => $biblionumber });
604
}
605
550
=head2 Internal methods
606
=head2 Internal methods
551
607
552
=head3 _type
608
=head3 _type
(-)a/cataloguing/merge.pl (-14 / +11 lines)
Lines 31-36 use C4::Reserves qw/MergeHolds/; Link Here
31
use C4::Acquisition qw/ModOrder GetOrdersByBiblionumber/;
31
use C4::Acquisition qw/ModOrder GetOrdersByBiblionumber/;
32
32
33
use Koha::BiblioFrameworks;
33
use Koha::BiblioFrameworks;
34
use Koha::Biblios;
34
use Koha::Items;
35
use Koha::Items;
35
use Koha::MetadataRecord;
36
use Koha::MetadataRecord;
36
37
Lines 81-105 if ($merge) { Link Here
81
    $record->leader(GetMarcBiblio({ biblionumber => $ref_biblionumber })->leader());
82
    $record->leader(GetMarcBiblio({ biblionumber => $ref_biblionumber })->leader());
82
83
83
    my $frameworkcode = $input->param('frameworkcode');
84
    my $frameworkcode = $input->param('frameworkcode');
84
    my @notmoveditems;
85
85
86
    # Modifying the reference record
86
    # Modifying the reference record
87
    ModBiblio($record, $ref_biblionumber, $frameworkcode);
87
    ModBiblio($record, $ref_biblionumber, $frameworkcode);
88
88
89
    # Moving items from the other record to the reference record
89
    # Moving items from the other record to the reference record
90
    my $biblio = Koha::Biblios->find($ref_biblionumber);
90
    foreach my $biblionumber (@biblionumbers) {
91
    foreach my $biblionumber (@biblionumbers) {
91
        my $items = Koha::Items->search({ biblionumber => $biblionumber });
92
        my $from_biblio = Koha::Biblios->find($biblionumber);
92
        while ( my $item = $items->next) {
93
        $biblio->adopt_items_from_biblio($from_biblio);
93
            my $res = MoveItemFromBiblio( $item->itemnumber, $biblionumber, $ref_biblionumber );
94
            if ( not defined $res ) {
95
                push @notmoveditems, $item->itemnumber;
96
            }
97
        }
98
    }
99
    # If some items could not be moved :
100
    if (scalar(@notmoveditems) > 0) {
101
        my $itemlist = join(' ',@notmoveditems);
102
        push @errors, { code => "CANNOT_MOVE", value => $itemlist };
103
    }
94
    }
104
95
105
    my $sth_subscription = $dbh->prepare("
96
    my $sth_subscription = $dbh->prepare("
Lines 114-119 if ($merge) { Link Here
114
    my $sth_suggestions = $dbh->prepare("
105
    my $sth_suggestions = $dbh->prepare("
115
        UPDATE suggestions SET biblionumber = ? WHERE biblionumber = ?
106
        UPDATE suggestions SET biblionumber = ? WHERE biblionumber = ?
116
    ");
107
    ");
108
    my $sth_articlerequests = $dbh->prepare("
109
        UPDATE article_requests SET biblionumber = ? WHERE biblionumber = ?
110
    ");
117
111
118
    my $report_header = {};
112
    my $report_header = {};
119
    foreach my $biblionumber ($ref_biblionumber, @biblionumbers) {
113
    foreach my $biblionumber ($ref_biblionumber, @biblionumbers) {
Lines 163-169 if ($merge) { Link Here
163
    # Moving suggestions
157
    # Moving suggestions
164
    $sth_suggestions->execute($ref_biblionumber, $biblionumber);
158
    $sth_suggestions->execute($ref_biblionumber, $biblionumber);
165
159
166
    # Moving orders (orders linked to items of frombiblio have already been moved by MoveItemFromBiblio)
160
    # Moving article requests
161
    $sth_articlerequests->execute($ref_biblionumber, $biblionumber);
162
163
    # Moving orders (orders linked to items of frombiblio have already been moved by adopt_items_from_biblio)
167
    my @allorders = GetOrdersByBiblionumber($biblionumber);
164
    my @allorders = GetOrdersByBiblionumber($biblionumber);
168
    foreach my $myorder (@allorders) {
165
    foreach my $myorder (@allorders) {
169
        $myorder->{'biblionumber'} = $ref_biblionumber;
166
        $myorder->{'biblionumber'} = $ref_biblionumber;
(-)a/t/db_dependent/Items/MoveItemFromBiblio.t (+3 lines)
Lines 25-36 use Koha::Holds; Link Here
25
use Koha::Items;
25
use Koha::Items;
26
26
27
use t::lib::TestBuilder;
27
use t::lib::TestBuilder;
28
use t::lib::Mocks;
28
use Data::Dumper qw|Dumper|;
29
use Data::Dumper qw|Dumper|;
29
30
30
my $schema  = Koha::Database->new->schema;
31
my $schema  = Koha::Database->new->schema;
31
$schema->storage->txn_begin;
32
$schema->storage->txn_begin;
32
my $builder = t::lib::TestBuilder->new;
33
my $builder = t::lib::TestBuilder->new;
33
34
35
t::lib::Mocks::mock_preference( 'SearchEngine', 'Zebra' );
36
34
# NOTE This is a trick, if we want to populate the biblioitems table, we should not create a Biblio but a Biblioitem
37
# NOTE This is a trick, if we want to populate the biblioitems table, we should not create a Biblio but a Biblioitem
35
my $param = { source => 'Biblioitem' };
38
my $param = { source => 'Biblioitem' };
36
my $from_biblio = {
39
my $from_biblio = {
(-)a/t/db_dependent/Koha/Item.t (-3 / +106 lines)
Lines 19-25 Link Here
19
19
20
use Modern::Perl;
20
use Modern::Perl;
21
21
22
use Test::More tests => 4;
22
use Test::More tests => 5;
23
23
24
use C4::Biblio;
24
use C4::Biblio;
25
25
Lines 152-162 subtest 'pickup_locations' => sub { Link Here
152
    my $dbh = C4::Context->dbh;
152
    my $dbh = C4::Context->dbh;
153
153
154
    # Cleanup database
154
    # Cleanup database
155
    $dbh->do('DELETE FROM issues');
155
    Koha::Holds->search->delete;
156
    Koha::Holds->search->delete;
156
    Koha::Patrons->search->delete;
157
    Koha::Patrons->search->delete;
157
    Koha::Items->search->delete;
158
    Koha::Items->search->delete;
158
    Koha::Libraries->search->delete;
159
    Koha::Libraries->search->delete;
159
    $dbh->do('DELETE FROM issues');
160
    Koha::CirculationRules->search->delete;
160
    Koha::CirculationRules->search->delete;
161
    Koha::CirculationRules->set_rules(
161
    Koha::CirculationRules->set_rules(
162
        {
162
        {
Lines 329-331 subtest 'pickup_locations' => sub { Link Here
329
329
330
    $schema->storage->txn_rollback;
330
    $schema->storage->txn_rollback;
331
};
331
};
332
- 
332
333
subtest 'move_to_biblio() tests' => sub {
334
335
    plan tests => 12;
336
337
    $schema->storage->txn_begin;
338
339
    my $dbh = C4::Context->dbh;
340
341
    my $source_biblio = $builder->build_sample_biblio();
342
    my $target_biblio = $builder->build_sample_biblio();
343
344
    my $source_biblionumber = $source_biblio->biblionumber;
345
346
    my $item1 = $builder->build_sample_item({ biblionumber => $source_biblionumber });
347
    my $item2 = $builder->build_sample_item({ biblionumber => $source_biblionumber });
348
349
    my $itemnumber1 = $item1->itemnumber;
350
    my $itemnumber2 = $item2->itemnumber;
351
352
    my $library = $builder->build_object({ class => 'Koha::Libraries' });
353
354
    my $patron = $builder->build_object({
355
        class => 'Koha::Patrons',
356
        value => { branchcode => $library->branchcode, }
357
    });
358
    my $borrowernumber = $patron->borrowernumber;
359
360
    $dbh->do("INSERT INTO aqbudgets (budget_notes) VALUES ('test')");
361
    my $budget_id = $dbh->last_insert_id(undef, undef, 'aqbudgets', 'budget_id');
362
363
    $dbh->do('INSERT INTO aqorders (biblionumber, budget_id) VALUES (?, ?)', undef, $source_biblionumber, $budget_id);
364
    my $ordernumber1 = $dbh->last_insert_id(undef, undef, 'aqorders', 'ordernumber');
365
    $dbh->do('INSERT INTO aqorders_items (ordernumber, itemnumber) VALUES (?, ?)', undef, $ordernumber1, $itemnumber1);
366
367
    $dbh->do('INSERT INTO aqorders (biblionumber, budget_id) VALUES (?, ?)', undef, $source_biblionumber, $budget_id);
368
    my $ordernumber2 = $dbh->last_insert_id(undef, undef, 'aqorders', 'ordernumber');
369
    $dbh->do('INSERT INTO aqorders_items (ordernumber, itemnumber) VALUES (?, ?)', undef, $ordernumber2, $source_biblionumber);
370
371
    my $reserve_id1 = C4::Reserves::AddReserve({
372
        branch => $library->branchcode, 
373
        borrowernumber => $borrowernumber,
374
        biblionumber => $source_biblionumber, 
375
        itemnumber => $itemnumber1,
376
        title => 'title'
377
    });
378
379
    my $reserve_id2 = C4::Reserves::AddReserve({
380
        branch => $library->branchcode, 
381
        borrowernumber => $patron->borrowernumber,
382
        biblionumber => $source_biblionumber, 
383
        itemnumber => $itemnumber2,
384
        title => 'title'
385
    });
386
387
    $dbh->do("INSERT INTO tmp_holdsqueue (surname,borrowernumber,itemnumber,biblionumber) VALUES ('Clamp',?,?,?)", undef, $borrowernumber, $itemnumber1, $source_biblionumber);
388
    $dbh->do("INSERT INTO tmp_holdsqueue (surname,borrowernumber,itemnumber,biblionumber) VALUES ('Clamp',?,?,?)", undef, $borrowernumber, $itemnumber2, $source_biblionumber);
389
390
    $dbh->do('INSERT INTO hold_fill_targets (borrowernumber,itemnumber,biblionumber) VALUES (?,?,?)', undef, $borrowernumber, $itemnumber1, $source_biblionumber);
391
    $dbh->do('INSERT INTO hold_fill_targets (borrowernumber,itemnumber,biblionumber) VALUES (?,?,?)', undef, $borrowernumber, $itemnumber2, $source_biblionumber);
392
393
    $dbh->do('INSERT INTO linktracker (borrowernumber,itemnumber,biblionumber) VALUES (?,?,?)', undef, $borrowernumber, $itemnumber1, $source_biblionumber);
394
    $dbh->do('INSERT INTO linktracker (borrowernumber,itemnumber,biblionumber) VALUES (?,?,?)', undef, $borrowernumber, $itemnumber2, $source_biblionumber);
395
396
    $item1->move_to_biblio($target_biblio);
397
398
    my @result = $dbh->selectrow_array('SELECT biblionumber FROM items WHERE itemnumber = ?', undef, $itemnumber1);
399
    is($result[0], $target_biblio->biblionumber, 'Correct biblionumber in the moved item');
400
401
    @result = $dbh->selectrow_array('SELECT biblionumber FROM items WHERE itemnumber = ?', undef, $itemnumber2);
402
    is($result[0], $source_biblionumber, 'Correct biblionumber in the unmoved item');
403
404
    @result = $dbh->selectrow_array('SELECT biblionumber FROM aqorders WHERE ordernumber = ?', undef, $ordernumber1);
405
    is($result[0], $target_biblio->biblionumber, 'Correct biblionumber in aqorders for order with the moved item');
406
407
    @result = $dbh->selectrow_array('SELECT biblionumber FROM aqorders WHERE ordernumber = ?', undef, $ordernumber2);
408
    is($result[0], $source_biblionumber, 'Correct biblionumber in aqorders for order with the unmoved item');
409
410
    @result = $dbh->selectrow_array('SELECT biblionumber FROM reserves WHERE reserve_id = ?', undef, $reserve_id1);
411
    is($result[0], $target_biblio->biblionumber, 'Correct biblionumber in reserves for moved item');
412
413
    @result = $dbh->selectrow_array('SELECT biblionumber FROM reserves WHERE reserve_id = ?', undef, $reserve_id2);
414
    is($result[0], $source_biblionumber, 'Correct biblionumber in reserves for unmoved item');
415
416
    @result = $dbh->selectrow_array('SELECT biblionumber FROM tmp_holdsqueue WHERE itemnumber = ?', undef, $itemnumber1);
417
    is($result[0], $target_biblio->biblionumber, 'Correct biblionumber in tmp_holdsqueue for moved item');
418
419
    @result = $dbh->selectrow_array('SELECT biblionumber FROM tmp_holdsqueue WHERE itemnumber = ?', undef, $itemnumber2);
420
    is($result[0], $source_biblionumber, 'Correct biblionumber in tmp_holdsqueue for unmoved item');
421
422
    @result = $dbh->selectrow_array('SELECT biblionumber FROM hold_fill_targets WHERE itemnumber = ?', undef, $itemnumber1);
423
    is($result[0], $target_biblio->biblionumber, 'Correct biblionumber in hold_fill_targets for moved item');
424
425
    @result = $dbh->selectrow_array('SELECT biblionumber FROM hold_fill_targets WHERE itemnumber = ?', undef, $itemnumber2);
426
    is($result[0], $source_biblionumber, 'Correct biblionumber in hold_fill_targets for unmoved item');
427
428
    @result = $dbh->selectrow_array('SELECT biblionumber FROM linktracker WHERE itemnumber = ?', undef, $itemnumber1);
429
    is($result[0], $target_biblio->biblionumber, 'Correct biblionumber in linktracker for moved item');
430
431
    @result = $dbh->selectrow_array('SELECT biblionumber FROM linktracker WHERE itemnumber = ?', undef, $itemnumber2);
432
    is($result[0], $source_biblionumber, 'Correct biblionumber in linktracker for unmoved item');
433
434
    $schema->storage->txn_rollback;
435
};

Return to bug 22690