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

(-)a/C4/Items.pm (-38 / +17 lines)
Lines 66-71 use Koha::AuthorisedValues; Link Here
66
use Koha::DateUtils qw(dt_from_string);
66
use Koha::DateUtils qw(dt_from_string);
67
use Koha::Database;
67
use Koha::Database;
68
68
69
use Koha::Biblios;
69
use Koha::Biblioitems;
70
use Koha::Biblioitems;
70
use Koha::Items;
71
use Koha::Items;
71
use Koha::ItemTypes;
72
use Koha::ItemTypes;
Lines 1084-1090 the inner workings of C<C4::Items>. Link Here
1084
1085
1085
=head2 MoveItemFromBiblio
1086
=head2 MoveItemFromBiblio
1086
1087
1087
  MoveItemFromBiblio($itenumber, $frombiblio, $tobiblio);
1088
  MoveItemFromBiblio($itemnumber, $frombiblio, $tobiblio);
1088
1089
1089
Moves an item from a biblio to another
1090
Moves an item from a biblio to another
1090
1091
Lines 1094-1136 Returns undef if the move failed or the biblionumber of the destination record o Link Here
1094
1095
1095
sub MoveItemFromBiblio {
1096
sub MoveItemFromBiblio {
1096
    my ($itemnumber, $frombiblio, $tobiblio) = @_;
1097
    my ($itemnumber, $frombiblio, $tobiblio) = @_;
1097
    my $dbh = C4::Context->dbh;
1098
1098
    my ( $tobiblioitem ) = $dbh->selectrow_array(q|
1099
    my $item = Koha::Items->find($itemnumber);
1099
        SELECT biblioitemnumber
1100
    return unless $item;
1100
        FROM biblioitems
1101
1101
        WHERE biblionumber = ?
1102
    my $biblio = Koha::Biblios->find($tobiblio);
1102
    |, undef, $tobiblio );
1103
    return unless $biblio;
1103
    my $return = $dbh->do(q|
1104
1104
        UPDATE items
1105
    return unless $item->biblionumber != $biblio->biblionumber;
1105
        SET biblioitemnumber = ?,
1106
1106
            biblionumber = ?
1107
    $item->move_to_biblio($biblio);
1107
        WHERE itemnumber = ?
1108
    my $indexer = Koha::SearchEngine::Indexer->new({ index => $Koha::SearchEngine::BIBLIOS_INDEX });
1108
            AND biblionumber = ?
1109
    $indexer->index_records( $tobiblio, "specialUpdate", "biblioserver" );
1109
    |, undef, $tobiblioitem, $tobiblio, $itemnumber, $frombiblio );
1110
    $indexer->index_records( $frombiblio, "specialUpdate", "biblioserver" );
1110
    if ($return == 1) {
1111
1111
        my $indexer = Koha::SearchEngine::Indexer->new({ index => $Koha::SearchEngine::BIBLIOS_INDEX });
1112
    return $tobiblio;
1112
        $indexer->index_records( $tobiblio, "specialUpdate", "biblioserver" );
1113
        $indexer->index_records( $frombiblio, "specialUpdate", "biblioserver" );
1114
	    # Checking if the item we want to move is in an order 
1115
        require C4::Acquisition;
1116
        my $order = C4::Acquisition::GetOrderFromItemnumber($itemnumber);
1117
	    if ($order) {
1118
		    # Replacing the biblionumber within the order if necessary
1119
		    $order->{'biblionumber'} = $tobiblio;
1120
	        C4::Acquisition::ModOrder($order);
1121
	    }
1122
1123
        # Update reserves, hold_fill_targets, tmp_holdsqueue and linktracker tables
1124
        for my $table_name ( qw( reserves hold_fill_targets tmp_holdsqueue linktracker ) ) {
1125
            $dbh->do( qq|
1126
                UPDATE $table_name
1127
                SET biblionumber = ?
1128
                WHERE itemnumber = ?
1129
            |, undef, $tobiblio, $itemnumber );
1130
        }
1131
        return $tobiblio;
1132
	}
1133
    return;
1134
}
1113
}
1135
1114
1136
=head2 _marc_from_item_hash
1115
=head2 _marc_from_item_hash
(-)a/Koha/Biblio.pm (+24 lines)
Lines 41-46 use Koha::CirculationRules; Link Here
41
use Koha::Item::Transfer::Limits;
41
use Koha::Item::Transfer::Limits;
42
use Koha::Items;
42
use Koha::Items;
43
use Koha::Libraries;
43
use Koha::Libraries;
44
use Koha::SearchEngine::Indexer;
44
use Koha::Suggestions;
45
use Koha::Suggestions;
45
use Koha::Subscriptions;
46
use Koha::Subscriptions;
46
47
Lines 816-821 sub to_api_mapping { Link Here
816
    };
817
    };
817
}
818
}
818
819
820
=head3 adopt_items_from_biblio
821
822
$biblio->adopt_items_from_biblio($from_biblio);
823
824
Move items from the given biblio to this one.
825
826
=cut
827
828
sub adopt_items_from_biblio {
829
    my ( $self, $from_biblio ) = @_;
830
831
    my $items = $from_biblio->items;
832
    if ($items) {
833
        while (my $item = $items->next()) {
834
            $item->move_to_biblio($self);
835
        }
836
        my $indexer = Koha::SearchEngine::Indexer->new({ index => $Koha::SearchEngine::BIBLIOS_INDEX });
837
        $indexer->index_records( $self->biblionumber, "specialUpdate", "biblioserver" );
838
        $indexer->index_records( $from_biblio->biblionumber, "specialUpdate", "biblioserver" );
839
    }
840
}
841
842
819
=head2 Internal methods
843
=head2 Internal methods
820
844
821
=head3 type
845
=head3 type
(-)a/Koha/Item.pm (+63 lines)
Lines 966-971 sub itemtype { Link Here
966
    return Koha::ItemTypes->find( $self->effective_itemtype );
966
    return Koha::ItemTypes->find( $self->effective_itemtype );
967
}
967
}
968
968
969
=head3 item_orders
970
971
my $orders = $item->item_orders();
972
973
Returns a Koha::Acquisition::Orders object
974
975
=cut
976
977
sub item_orders {
978
    my ( $self ) = @_;
979
980
    my $orders = $self->_result->item_orders;
981
    return Koha::Acquisition::Orders->_new_from_dbic($orders);
982
}
983
984
=head3 move_to_biblio
985
986
  $item->move_to_biblio($to_biblio);
987
988
Move the item to another biblio and update any references also in other tables.
989
990
=cut
991
992
sub move_to_biblio {
993
    my ( $self, $to_biblio ) = @_;
994
995
    my $biblionumber = $to_biblio->biblionumber;
996
997
    # Own biblionumber and biblioitemnumber
998
    $self->set({
999
        biblionumber => $biblionumber,
1000
        biblioitemnumber => $to_biblio->biblioitem->biblioitemnumber
1001
    })->store({ skip_record_index => 1 });
1002
1003
    # Acquisition orders
1004
    $self->item_orders->update({ biblionumber => $biblionumber }, { no_triggers => 1 });
1005
1006
    # Holds
1007
    $self->holds->update({ biblionumber => $biblionumber }, { no_triggers => 1 });
1008
1009
    # hold_fill_target (there's no Koha object available)
1010
    my $hold_fill_target = $self->_result->hold_fill_target;
1011
    if ($hold_fill_target) {
1012
        $hold_fill_target->update({ biblionumber => $biblionumber });
1013
    }
1014
1015
    # tmp_holdsqueues - Can't update with DBIx since the table is missing a primary key
1016
    # and can't even fake one since the significant columns are nullable.
1017
    my $storage = $self->_result->result_source->storage;
1018
    $storage->dbh_do(
1019
        sub {
1020
            my ($storage, $dbh, @cols) = @_;
1021
1022
            $dbh->do("UPDATE tmp_holdsqueue SET biblionumber=? WHERE itemnumber=?", undef, $biblionumber, $self->itemnumber);
1023
        }
1024
    );
1025
1026
    # linktrackers
1027
    my $schema = Koha::Database->new()->schema();
1028
    my $linktrackers = $schema->resultset('Linktracker')->search({ itemnumber => $self->itemnumber });
1029
    $linktrackers->update_all({ biblionumber => $biblionumber });
1030
}
1031
969
=head2 Internal methods
1032
=head2 Internal methods
970
1033
971
=head3 _after_item_action_hooks
1034
=head3 _after_item_action_hooks
(-)a/Koha/Schema/Result/Item.pm (+13 lines)
Lines 763-768 __PACKAGE__->add_columns( Link Here
763
    '+exclude_from_local_holds_priority' => { is_boolean => 1 },
763
    '+exclude_from_local_holds_priority' => { is_boolean => 1 },
764
);
764
);
765
765
766
# Relationship with orders via the aqorders_item table that not have foreign keys
767
__PACKAGE__->has_many(
768
  "aqorders_item",
769
  "Koha::Schema::Result::AqordersItem",
770
  { "foreign.itemnumber" => "self.itemnumber" },
771
  { cascade_copy => 0, cascade_delete => 0 },
772
);
773
__PACKAGE__->many_to_many(
774
  "item_orders",
775
  "aqorders_item",
776
  "ordernumber",
777
);
778
766
use C4::Context;
779
use C4::Context;
767
sub effective_itemtype {
780
sub effective_itemtype {
768
    my ( $self ) = @_;
781
    my ( $self ) = @_;
(-)a/cataloguing/merge.pl (-15 / +7 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 80-104 if ($merge) { Link Here
80
    $record->leader(GetMarcBiblio({ biblionumber => $ref_biblionumber })->leader());
81
    $record->leader(GetMarcBiblio({ biblionumber => $ref_biblionumber })->leader());
81
82
82
    my $frameworkcode = $input->param('frameworkcode');
83
    my $frameworkcode = $input->param('frameworkcode');
83
    my @notmoveditems;
84
84
85
    # Modifying the reference record
85
    # Modifying the reference record
86
    ModBiblio($record, $ref_biblionumber, $frameworkcode);
86
    ModBiblio($record, $ref_biblionumber, $frameworkcode);
87
87
88
    # Moving items from the other record to the reference record
88
    # Moving items and article requests from the other record to the reference record
89
    my $biblio = Koha::Biblios->find($ref_biblionumber);
89
    foreach my $biblionumber (@biblionumbers) {
90
    foreach my $biblionumber (@biblionumbers) {
90
        my $items = Koha::Items->search({ biblionumber => $biblionumber });
91
        my $from_biblio = Koha::Biblios->find($biblionumber);
91
        while ( my $item = $items->next) {
92
        $biblio->adopt_items_from_biblio($from_biblio);
92
            my $res = MoveItemFromBiblio( $item->itemnumber, $biblionumber, $ref_biblionumber );
93
        $from_biblio->article_requests->update({ biblionumber => $ref_biblionumber }, { no_triggers => 1 });
93
            if ( not defined $res ) {
94
                push @notmoveditems, $item->itemnumber;
95
            }
96
        }
97
    }
98
    # If some items could not be moved :
99
    if (scalar(@notmoveditems) > 0) {
100
        my $itemlist = join(' ',@notmoveditems);
101
        push @errors, { code => "CANNOT_MOVE", value => $itemlist };
102
    }
94
    }
103
95
104
    my $sth_subscription = $dbh->prepare("
96
    my $sth_subscription = $dbh->prepare("
Lines 162-168 if ($merge) { Link Here
162
    # Moving suggestions
154
    # Moving suggestions
163
    $sth_suggestions->execute($ref_biblionumber, $biblionumber);
155
    $sth_suggestions->execute($ref_biblionumber, $biblionumber);
164
156
165
    # Moving orders (orders linked to items of frombiblio have already been moved by MoveItemFromBiblio)
157
    # Moving orders (orders linked to items of frombiblio have already been moved by adopt_items_from_biblio)
166
    my @allorders = GetOrdersByBiblionumber($biblionumber);
158
    my @allorders = GetOrdersByBiblionumber($biblionumber);
167
    foreach my $myorder (@allorders) {
159
    foreach my $myorder (@allorders) {
168
        $myorder->{'biblionumber'} = $ref_biblionumber;
160
        $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
my $from_biblio = $builder->build_sample_biblio;
37
my $from_biblio = $builder->build_sample_biblio;
35
my $to_biblio = $builder->build_sample_biblio;
38
my $to_biblio = $builder->build_sample_biblio;
36
39
(-)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 => 7;
22
use Test::More tests => 8;
23
23
24
use C4::Biblio;
24
use C4::Biblio;
25
use C4::Circulation;
25
use C4::Circulation;
Lines 163-170 subtest 'pickup_locations' => sub { Link Here
163
    my $dbh = C4::Context->dbh;
163
    my $dbh = C4::Context->dbh;
164
164
165
    # Cleanup database
165
    # Cleanup database
166
    Koha::Holds->search->delete;
167
    $dbh->do('DELETE FROM issues');
166
    $dbh->do('DELETE FROM issues');
167
    Koha::Holds->search->delete;
168
    Koha::Patrons->search->delete;
168
    Koha::Patrons->search->delete;
169
    Koha::Items->search->delete;
169
    Koha::Items->search->delete;
170
    Koha::Libraries->search->delete;
170
    Koha::Libraries->search->delete;
Lines 516-518 subtest 'Tests for itemtype' => sub { Link Here
516
516
517
    $schema->storage->txn_rollback;
517
    $schema->storage->txn_rollback;
518
};
518
};
519
- 
519
520
subtest 'move_to_biblio() tests' => sub {
521
522
    plan tests => 12;
523
524
    $schema->storage->txn_begin;
525
526
    my $dbh = C4::Context->dbh;
527
528
    my $source_biblio = $builder->build_sample_biblio();
529
    my $target_biblio = $builder->build_sample_biblio();
530
531
    my $source_biblionumber = $source_biblio->biblionumber;
532
533
    my $item1 = $builder->build_sample_item({ biblionumber => $source_biblionumber });
534
    my $item2 = $builder->build_sample_item({ biblionumber => $source_biblionumber });
535
536
    my $itemnumber1 = $item1->itemnumber;
537
    my $itemnumber2 = $item2->itemnumber;
538
539
    my $library = $builder->build_object({ class => 'Koha::Libraries' });
540
541
    my $patron = $builder->build_object({
542
        class => 'Koha::Patrons',
543
        value => { branchcode => $library->branchcode, }
544
    });
545
    my $borrowernumber = $patron->borrowernumber;
546
547
    $dbh->do("INSERT INTO aqbudgets (budget_notes) VALUES ('test')");
548
    my $budget_id = $dbh->last_insert_id(undef, undef, 'aqbudgets', 'budget_id');
549
550
    $dbh->do('INSERT INTO aqorders (biblionumber, budget_id) VALUES (?, ?)', undef, $source_biblionumber, $budget_id);
551
    my $ordernumber1 = $dbh->last_insert_id(undef, undef, 'aqorders', 'ordernumber');
552
    $dbh->do('INSERT INTO aqorders_items (ordernumber, itemnumber) VALUES (?, ?)', undef, $ordernumber1, $itemnumber1);
553
554
    $dbh->do('INSERT INTO aqorders (biblionumber, budget_id) VALUES (?, ?)', undef, $source_biblionumber, $budget_id);
555
    my $ordernumber2 = $dbh->last_insert_id(undef, undef, 'aqorders', 'ordernumber');
556
    $dbh->do('INSERT INTO aqorders_items (ordernumber, itemnumber) VALUES (?, ?)', undef, $ordernumber2, $source_biblionumber);
557
558
    my $reserve_id1 = C4::Reserves::AddReserve({
559
        branch => $library->branchcode,
560
        borrowernumber => $borrowernumber,
561
        biblionumber => $source_biblionumber,
562
        itemnumber => $itemnumber1,
563
        title => 'title'
564
    });
565
566
    my $reserve_id2 = C4::Reserves::AddReserve({
567
        branch => $library->branchcode,
568
        borrowernumber => $patron->borrowernumber,
569
        biblionumber => $source_biblionumber,
570
        itemnumber => $itemnumber2,
571
        title => 'title'
572
    });
573
574
    $dbh->do("INSERT INTO tmp_holdsqueue (surname,borrowernumber,itemnumber,biblionumber) VALUES ('Clamp',?,?,?)", undef, $borrowernumber, $itemnumber1, $source_biblionumber);
575
    $dbh->do("INSERT INTO tmp_holdsqueue (surname,borrowernumber,itemnumber,biblionumber) VALUES ('Clamp',?,?,?)", undef, $borrowernumber, $itemnumber2, $source_biblionumber);
576
577
    $dbh->do('INSERT INTO hold_fill_targets (borrowernumber,itemnumber,biblionumber) VALUES (?,?,?)', undef, $borrowernumber, $itemnumber1, $source_biblionumber);
578
    $dbh->do('INSERT INTO hold_fill_targets (borrowernumber,itemnumber,biblionumber) VALUES (?,?,?)', undef, $borrowernumber, $itemnumber2, $source_biblionumber);
579
580
    $dbh->do('INSERT INTO linktracker (borrowernumber,itemnumber,biblionumber) VALUES (?,?,?)', undef, $borrowernumber, $itemnumber1, $source_biblionumber);
581
    $dbh->do('INSERT INTO linktracker (borrowernumber,itemnumber,biblionumber) VALUES (?,?,?)', undef, $borrowernumber, $itemnumber2, $source_biblionumber);
582
583
    $item1->move_to_biblio($target_biblio);
584
585
    my @result = $dbh->selectrow_array('SELECT biblionumber FROM items WHERE itemnumber = ?', undef, $itemnumber1);
586
    is($result[0], $target_biblio->biblionumber, 'Correct biblionumber in the moved item');
587
588
    @result = $dbh->selectrow_array('SELECT biblionumber FROM items WHERE itemnumber = ?', undef, $itemnumber2);
589
    is($result[0], $source_biblionumber, 'Correct biblionumber in the unmoved item');
590
591
    @result = $dbh->selectrow_array('SELECT biblionumber FROM aqorders WHERE ordernumber = ?', undef, $ordernumber1);
592
    is($result[0], $target_biblio->biblionumber, 'Correct biblionumber in aqorders for order with the moved item');
593
594
    @result = $dbh->selectrow_array('SELECT biblionumber FROM aqorders WHERE ordernumber = ?', undef, $ordernumber2);
595
    is($result[0], $source_biblionumber, 'Correct biblionumber in aqorders for order with the unmoved item');
596
597
    @result = $dbh->selectrow_array('SELECT biblionumber FROM reserves WHERE reserve_id = ?', undef, $reserve_id1);
598
    is($result[0], $target_biblio->biblionumber, 'Correct biblionumber in reserves for moved item');
599
600
    @result = $dbh->selectrow_array('SELECT biblionumber FROM reserves WHERE reserve_id = ?', undef, $reserve_id2);
601
    is($result[0], $source_biblionumber, 'Correct biblionumber in reserves for unmoved item');
602
603
    @result = $dbh->selectrow_array('SELECT biblionumber FROM tmp_holdsqueue WHERE itemnumber = ?', undef, $itemnumber1);
604
    is($result[0], $target_biblio->biblionumber, 'Correct biblionumber in tmp_holdsqueue for moved item');
605
606
    @result = $dbh->selectrow_array('SELECT biblionumber FROM tmp_holdsqueue WHERE itemnumber = ?', undef, $itemnumber2);
607
    is($result[0], $source_biblionumber, 'Correct biblionumber in tmp_holdsqueue for unmoved item');
608
609
    @result = $dbh->selectrow_array('SELECT biblionumber FROM hold_fill_targets WHERE itemnumber = ?', undef, $itemnumber1);
610
    is($result[0], $target_biblio->biblionumber, 'Correct biblionumber in hold_fill_targets for moved item');
611
612
    @result = $dbh->selectrow_array('SELECT biblionumber FROM hold_fill_targets WHERE itemnumber = ?', undef, $itemnumber2);
613
    is($result[0], $source_biblionumber, 'Correct biblionumber in hold_fill_targets for unmoved item');
614
615
    @result = $dbh->selectrow_array('SELECT biblionumber FROM linktracker WHERE itemnumber = ?', undef, $itemnumber1);
616
    is($result[0], $target_biblio->biblionumber, 'Correct biblionumber in linktracker for moved item');
617
618
    @result = $dbh->selectrow_array('SELECT biblionumber FROM linktracker WHERE itemnumber = ?', undef, $itemnumber2);
619
    is($result[0], $source_biblionumber, 'Correct biblionumber in linktracker for unmoved item');
620
621
    $schema->storage->txn_rollback;
622
};

Return to bug 22690