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

(-)a/C4/Items.pm (-37 / +16 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 1058-1064 the inner workings of C<C4::Items>. Link Here
1058
1059
1059
=head2 MoveItemFromBiblio
1060
=head2 MoveItemFromBiblio
1060
1061
1061
  MoveItemFromBiblio($itenumber, $frombiblio, $tobiblio);
1062
  MoveItemFromBiblio($itemnumber, $frombiblio, $tobiblio);
1062
1063
1063
Moves an item from a biblio to another
1064
Moves an item from a biblio to another
1064
1065
Lines 1068-1109 Returns undef if the move failed or the biblionumber of the destination record o Link Here
1068
1069
1069
sub MoveItemFromBiblio {
1070
sub MoveItemFromBiblio {
1070
    my ($itemnumber, $frombiblio, $tobiblio) = @_;
1071
    my ($itemnumber, $frombiblio, $tobiblio) = @_;
1071
    my $dbh = C4::Context->dbh;
1072
1072
    my ( $tobiblioitem ) = $dbh->selectrow_array(q|
1073
    my $item = Koha::Items->find($itemnumber);
1073
        SELECT biblioitemnumber
1074
    return unless $item;
1074
        FROM biblioitems
1075
1075
        WHERE biblionumber = ?
1076
    my $biblio = Koha::Biblios->find($tobiblio);
1076
    |, undef, $tobiblio );
1077
    return unless $biblio;
1077
    my $return = $dbh->do(q|
1078
1078
        UPDATE items
1079
    return unless $item->biblionumber != $biblio->biblionumber;
1079
        SET biblioitemnumber = ?,
1080
1080
            biblionumber = ?
1081
    $item->move_to_biblio($biblio);
1081
        WHERE itemnumber = ?
1082
    ModZebra($tobiblio, 'specialUpdate', 'biblioserver');
1082
            AND biblionumber = ?
1083
    ModZebra($frombiblio, 'specialUpdate', 'biblioserver');
1083
    |, undef, $tobiblioitem, $tobiblio, $itemnumber, $frombiblio );
1084
1084
    if ($return == 1) {
1085
    return $tobiblio;
1085
        ModZebra( $tobiblio, "specialUpdate", "biblioserver" );
1086
        ModZebra( $frombiblio, "specialUpdate", "biblioserver" );
1087
	    # Checking if the item we want to move is in an order 
1088
        require C4::Acquisition;
1089
        my $order = C4::Acquisition::GetOrderFromItemnumber($itemnumber);
1090
	    if ($order) {
1091
		    # Replacing the biblionumber within the order if necessary
1092
		    $order->{'biblionumber'} = $tobiblio;
1093
	        C4::Acquisition::ModOrder($order);
1094
	    }
1095
1096
        # Update reserves, hold_fill_targets, tmp_holdsqueue and linktracker tables
1097
        for my $table_name ( qw( reserves hold_fill_targets tmp_holdsqueue linktracker ) ) {
1098
            $dbh->do( qq|
1099
                UPDATE $table_name
1100
                SET biblionumber = ?
1101
                WHERE itemnumber = ?
1102
            |, undef, $tobiblio, $itemnumber );
1103
        }
1104
        return $tobiblio;
1105
	}
1106
    return;
1107
}
1086
}
1108
1087
1109
=head2 _marc_from_item_hash
1088
=head2 _marc_from_item_hash
(-)a/Koha/Biblio.pm (+22 lines)
Lines 816-821 sub to_api_mapping { Link Here
816
    };
816
    };
817
}
817
}
818
818
819
=head3 adopt_items_from_biblio
820
821
$biblio->adopt_items_from_biblio($from_biblio);
822
823
Move items from the given biblio to this one.
824
825
=cut
826
827
sub adopt_items_from_biblio {
828
    my ( $self, $from_biblio ) = @_;
829
830
    my $items = $from_biblio->items;
831
    if ($items) {
832
        while (my $item = $items->next()) {
833
            $item->move_to_biblio($self);
834
        }
835
        C4::Biblio::ModZebra( $self->biblionumber, "specialUpdate", "biblioserver" );
836
        C4::Biblio::ModZebra( $from_biblio->biblionumber, "specialUpdate", "biblioserver" );
837
    }
838
}
839
840
819
=head2 Internal methods
841
=head2 Internal methods
820
842
821
=head3 type
843
=head3 type
(-)a/Koha/Item.pm (+63 lines)
Lines 819-824 sub to_api_mapping { Link Here
819
    };
819
    };
820
}
820
}
821
821
822
=head3 item_orders
823
824
my $orders = $item->item_orders();
825
826
Returns a Koha::Acquisition::Orders object
827
828
=cut
829
830
sub item_orders {
831
    my ( $self ) = @_;
832
833
    my $orders = $self->_result->item_orders;
834
    return Koha::Acquisition::Orders->_new_from_dbic($orders);
835
}
836
837
=head3 move_to_biblio
838
839
  $item->move_to_biblio($to_biblio);
840
841
Move the item to another biblio and update any references also in other tables.
842
843
=cut
844
845
sub move_to_biblio {
846
    my ( $self, $to_biblio ) = @_;
847
848
    my $biblionumber = $to_biblio->biblionumber;
849
850
    # Own biblionumber and biblioitemnumber
851
    $self->set({
852
        biblionumber => $biblionumber,
853
        biblioitemnumber => $to_biblio->biblioitem->biblioitemnumber
854
    })->store({ skip_modzebra_update => 1 });
855
856
    # Acquisition orders
857
    $self->item_orders->update({ biblionumber => $biblionumber }, { no_triggers => 1 });
858
859
    # Holds
860
    $self->holds->update({ biblionumber => $biblionumber }, { no_triggers => 1 });
861
862
    # hold_fill_target (there's no Koha object available)
863
    my $hold_fill_target = $self->_result->hold_fill_target;
864
    if ($hold_fill_target) {
865
        $hold_fill_target->update({ biblionumber => $biblionumber });
866
    }
867
868
    # tmp_holdsqueues - Can't update with DBIx since the table is missing a primary key
869
    # and can't even fake one since the significant columns are nullable.
870
    my $storage = $self->_result->result_source->storage;
871
    $storage->dbh_do(
872
        sub {
873
            my ($storage, $dbh, @cols) = @_;
874
875
            $dbh->do("UPDATE tmp_holdsqueue SET biblionumber=? WHERE itemnumber=?", undef, $biblionumber, $self->itemnumber);
876
        }
877
    );
878
879
    # linktrackers
880
    my $schema = Koha::Database->new()->schema();
881
    my $linktrackers = $schema->resultset('Linktracker')->search({ itemnumber => $self->itemnumber });
882
    $linktrackers->update_all({ biblionumber => $biblionumber });
883
}
884
822
=head2 Internal methods
885
=head2 Internal methods
823
886
824
=head3 _after_item_action_hooks
887
=head3 _after_item_action_hooks
(-)a/Koha/Schema/Result/Item.pm (+13 lines)
Lines 759-764 __PACKAGE__->belongs_to( Link Here
759
  { is_deferrable => 1, on_delete => "CASCADE", on_update => "CASCADE" },
759
  { is_deferrable => 1, on_delete => "CASCADE", on_update => "CASCADE" },
760
);
760
);
761
761
762
# Relationship with orders via the aqorders_item table that not have foreign keys
763
__PACKAGE__->has_many(
764
  "aqorders_item",
765
  "Koha::Schema::Result::AqordersItem",
766
  { "foreign.itemnumber" => "self.itemnumber" },
767
  { cascade_copy => 0, cascade_delete => 0 },
768
);
769
__PACKAGE__->many_to_many(
770
  "item_orders",
771
  "aqorders_item",
772
  "ordernumber",
773
);
774
762
use C4::Context;
775
use C4::Context;
763
sub effective_itemtype {
776
sub effective_itemtype {
764
    my ( $self ) = @_;
777
    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 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 and article requests 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
        $from_biblio->article_requests->update({ biblionumber => $ref_biblionumber }, { no_triggers => 1 });
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
    }
95
    }
104
96
105
    my $sth_subscription = $dbh->prepare("
97
    my $sth_subscription = $dbh->prepare("
Lines 163-169 if ($merge) { Link Here
163
    # Moving suggestions
155
    # Moving suggestions
164
    $sth_suggestions->execute($ref_biblionumber, $biblionumber);
156
    $sth_suggestions->execute($ref_biblionumber, $biblionumber);
165
157
166
    # Moving orders (orders linked to items of frombiblio have already been moved by MoveItemFromBiblio)
158
    # Moving orders (orders linked to items of frombiblio have already been moved by adopt_items_from_biblio)
167
    my @allorders = GetOrdersByBiblionumber($biblionumber);
159
    my @allorders = GetOrdersByBiblionumber($biblionumber);
168
    foreach my $myorder (@allorders) {
160
    foreach my $myorder (@allorders) {
169
        $myorder->{'biblionumber'} = $ref_biblionumber;
161
        $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 / +107 lines)
Lines 19-25 Link Here
19
19
20
use Modern::Perl;
20
use Modern::Perl;
21
21
22
use Test::More tests => 6;
22
use Test::More tests => 7;
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 500-503 subtest 'renewal_branchcode' => sub { Link Here
500
    is( $item->renewal_branchcode, $item->homebranch, "If interface opac and OpacRenewalBranch set to itemhomebranch, we get homebranch of item");
500
    is( $item->renewal_branchcode, $item->homebranch, "If interface opac and OpacRenewalBranch set to itemhomebranch, we get homebranch of item");
501
    is( $item->renewal_branchcode({branch=>'MANATEE'}), $item->homebranch, "If interface opac and OpacRenewalBranch set to itemhomebranch, we get homebranch of item even if branch passed");
501
    is( $item->renewal_branchcode({branch=>'MANATEE'}), $item->homebranch, "If interface opac and OpacRenewalBranch set to itemhomebranch, we get homebranch of item even if branch passed");
502
502
503
    $schema->storage->txn_rollback;
504
};
505
506
subtest 'move_to_biblio() tests' => sub {
507
508
    plan tests => 12;
509
510
    $schema->storage->txn_begin;
511
512
    my $dbh = C4::Context->dbh;
513
514
    my $source_biblio = $builder->build_sample_biblio();
515
    my $target_biblio = $builder->build_sample_biblio();
516
517
    my $source_biblionumber = $source_biblio->biblionumber;
518
519
    my $item1 = $builder->build_sample_item({ biblionumber => $source_biblionumber });
520
    my $item2 = $builder->build_sample_item({ biblionumber => $source_biblionumber });
521
522
    my $itemnumber1 = $item1->itemnumber;
523
    my $itemnumber2 = $item2->itemnumber;
524
525
    my $library = $builder->build_object({ class => 'Koha::Libraries' });
526
527
    my $patron = $builder->build_object({
528
        class => 'Koha::Patrons',
529
        value => { branchcode => $library->branchcode, }
530
    });
531
    my $borrowernumber = $patron->borrowernumber;
532
533
    $dbh->do("INSERT INTO aqbudgets (budget_notes) VALUES ('test')");
534
    my $budget_id = $dbh->last_insert_id(undef, undef, 'aqbudgets', 'budget_id');
535
536
    $dbh->do('INSERT INTO aqorders (biblionumber, budget_id) VALUES (?, ?)', undef, $source_biblionumber, $budget_id);
537
    my $ordernumber1 = $dbh->last_insert_id(undef, undef, 'aqorders', 'ordernumber');
538
    $dbh->do('INSERT INTO aqorders_items (ordernumber, itemnumber) VALUES (?, ?)', undef, $ordernumber1, $itemnumber1);
539
540
    $dbh->do('INSERT INTO aqorders (biblionumber, budget_id) VALUES (?, ?)', undef, $source_biblionumber, $budget_id);
541
    my $ordernumber2 = $dbh->last_insert_id(undef, undef, 'aqorders', 'ordernumber');
542
    $dbh->do('INSERT INTO aqorders_items (ordernumber, itemnumber) VALUES (?, ?)', undef, $ordernumber2, $source_biblionumber);
543
544
    my $reserve_id1 = C4::Reserves::AddReserve({
545
        branch => $library->branchcode,
546
        borrowernumber => $borrowernumber,
547
        biblionumber => $source_biblionumber,
548
        itemnumber => $itemnumber1,
549
        title => 'title'
550
    });
551
552
    my $reserve_id2 = C4::Reserves::AddReserve({
553
        branch => $library->branchcode,
554
        borrowernumber => $patron->borrowernumber,
555
        biblionumber => $source_biblionumber,
556
        itemnumber => $itemnumber2,
557
        title => 'title'
558
    });
559
560
    $dbh->do("INSERT INTO tmp_holdsqueue (surname,borrowernumber,itemnumber,biblionumber) VALUES ('Clamp',?,?,?)", undef, $borrowernumber, $itemnumber1, $source_biblionumber);
561
    $dbh->do("INSERT INTO tmp_holdsqueue (surname,borrowernumber,itemnumber,biblionumber) VALUES ('Clamp',?,?,?)", undef, $borrowernumber, $itemnumber2, $source_biblionumber);
562
563
    $dbh->do('INSERT INTO hold_fill_targets (borrowernumber,itemnumber,biblionumber) VALUES (?,?,?)', undef, $borrowernumber, $itemnumber1, $source_biblionumber);
564
    $dbh->do('INSERT INTO hold_fill_targets (borrowernumber,itemnumber,biblionumber) VALUES (?,?,?)', undef, $borrowernumber, $itemnumber2, $source_biblionumber);
565
566
    $dbh->do('INSERT INTO linktracker (borrowernumber,itemnumber,biblionumber) VALUES (?,?,?)', undef, $borrowernumber, $itemnumber1, $source_biblionumber);
567
    $dbh->do('INSERT INTO linktracker (borrowernumber,itemnumber,biblionumber) VALUES (?,?,?)', undef, $borrowernumber, $itemnumber2, $source_biblionumber);
568
569
    $item1->move_to_biblio($target_biblio);
570
571
    my @result = $dbh->selectrow_array('SELECT biblionumber FROM items WHERE itemnumber = ?', undef, $itemnumber1);
572
    is($result[0], $target_biblio->biblionumber, 'Correct biblionumber in the moved item');
573
574
    @result = $dbh->selectrow_array('SELECT biblionumber FROM items WHERE itemnumber = ?', undef, $itemnumber2);
575
    is($result[0], $source_biblionumber, 'Correct biblionumber in the unmoved item');
576
577
    @result = $dbh->selectrow_array('SELECT biblionumber FROM aqorders WHERE ordernumber = ?', undef, $ordernumber1);
578
    is($result[0], $target_biblio->biblionumber, 'Correct biblionumber in aqorders for order with the moved item');
579
580
    @result = $dbh->selectrow_array('SELECT biblionumber FROM aqorders WHERE ordernumber = ?', undef, $ordernumber2);
581
    is($result[0], $source_biblionumber, 'Correct biblionumber in aqorders for order with the unmoved item');
582
583
    @result = $dbh->selectrow_array('SELECT biblionumber FROM reserves WHERE reserve_id = ?', undef, $reserve_id1);
584
    is($result[0], $target_biblio->biblionumber, 'Correct biblionumber in reserves for moved item');
585
586
    @result = $dbh->selectrow_array('SELECT biblionumber FROM reserves WHERE reserve_id = ?', undef, $reserve_id2);
587
    is($result[0], $source_biblionumber, 'Correct biblionumber in reserves for unmoved item');
588
589
    @result = $dbh->selectrow_array('SELECT biblionumber FROM tmp_holdsqueue WHERE itemnumber = ?', undef, $itemnumber1);
590
    is($result[0], $target_biblio->biblionumber, 'Correct biblionumber in tmp_holdsqueue for moved item');
591
592
    @result = $dbh->selectrow_array('SELECT biblionumber FROM tmp_holdsqueue WHERE itemnumber = ?', undef, $itemnumber2);
593
    is($result[0], $source_biblionumber, 'Correct biblionumber in tmp_holdsqueue for unmoved item');
594
595
    @result = $dbh->selectrow_array('SELECT biblionumber FROM hold_fill_targets WHERE itemnumber = ?', undef, $itemnumber1);
596
    is($result[0], $target_biblio->biblionumber, 'Correct biblionumber in hold_fill_targets for moved item');
597
598
    @result = $dbh->selectrow_array('SELECT biblionumber FROM hold_fill_targets WHERE itemnumber = ?', undef, $itemnumber2);
599
    is($result[0], $source_biblionumber, 'Correct biblionumber in hold_fill_targets for unmoved item');
600
601
    @result = $dbh->selectrow_array('SELECT biblionumber FROM linktracker WHERE itemnumber = ?', undef, $itemnumber1);
602
    is($result[0], $target_biblio->biblionumber, 'Correct biblionumber in linktracker for moved item');
603
604
    @result = $dbh->selectrow_array('SELECT biblionumber FROM linktracker WHERE itemnumber = ?', undef, $itemnumber2);
605
    is($result[0], $source_biblionumber, 'Correct biblionumber in linktracker for unmoved item');
606
607
    $schema->storage->txn_rollback;
503
};
608
};
504
- 

Return to bug 22690