Bug 4154 - Follow-up
[koha.git] / misc / maintenance / sync_items_in_marc_bib.pl
1 #!/usr/bin/perl
2
3 use strict;
4 BEGIN {
5     # find Koha's Perl modules
6     # test carefully before changing this
7     use FindBin;
8     eval { require "$FindBin::Bin/../kohalib.pl" };
9 }
10
11 use C4::Context;
12 use C4::Biblio;
13 use C4::Items;
14 use Getopt::Long;
15
16 $| = 1;
17
18 # command-line parameters
19 my $want_help = 0;
20 my $do_update = 0;
21 my $wherestrings;
22
23 my $result = GetOptions(
24     'run-update'    => \$do_update,
25     'where=s@'         => \$wherestrings,
26     'h|help'        => \$want_help,
27 );
28
29 if (not $result or $want_help or not $do_update) {
30     print_usage();
31     exit 0;
32 }
33
34 my $num_bibs_processed     = 0;
35 my $num_bibs_modified      = 0;
36 my $num_marc_items_deleted = 0;
37 my $num_marc_items_added   = 0;
38 my $num_bad_bibs           = 0;
39 my $dbh = C4::Context->dbh;
40 $dbh->{AutoCommit} = 0;
41
42 our ($itemtag, $itemsubfield) = GetMarcFromKohaField("items.itemnumber", '');
43 our ($item_sth) = $dbh->prepare("SELECT itemnumber FROM items WHERE biblionumber = ?");
44
45 process_bibs();
46 $dbh->commit();
47
48 exit 0;
49
50 sub process_bibs {
51     my $sql = "SELECT biblionumber FROM biblio JOIN biblioitems USING (biblionumber)";
52     $sql.="WHERE ". join(" AND ",@$wherestrings) if ($wherestrings);
53     $sql.="ORDER BY biblionumber ASC";
54     my $sth = $dbh->prepare($sql);
55     eval{$sth->execute();};
56     if ($@){ die "error $@";};
57     while (my ($biblionumber) = $sth->fetchrow_array()) {
58         $num_bibs_processed++;
59         process_bib($biblionumber);
60
61         if (($num_bibs_processed % 100) == 0) {
62             print_progress_and_commit($num_bibs_processed);
63         }
64     }
65
66     $dbh->commit;
67
68     print <<_SUMMARY_;
69
70 Embedded item synchronization report
71 ------------------------------------
72 Number of bibs checked:                   $num_bibs_processed
73 Number of bibs modified:                  $num_bibs_modified
74 Number of item fields removed from bibs:  $num_marc_items_deleted
75 Number of item fields added to bibs:      $num_marc_items_added
76 Number of bibs with errors:               $num_bad_bibs
77 _SUMMARY_
78 }
79
80 sub process_bib {
81     my $biblionumber = shift;
82
83     my $bib = GetMarcBiblio($biblionumber);
84     unless (defined $bib) {
85         print "\nCould not retrieve bib $biblionumber from the database - record is corrupt.\n";
86         $num_bad_bibs++;
87         return;
88     }
89
90     my $bib_modified = 0;
91
92     # delete any item tags
93     foreach my $field ($bib->field($itemtag)) {
94         unless ($bib->delete_field($field)) {
95             warn "Could not delete item in $itemtag for biblionumber $biblionumber";
96             next;
97         }
98         $num_marc_items_deleted++;
99         $bib_modified = 1;
100     }
101
102     # add back items from items table
103     $item_sth->execute($biblionumber);
104     while (my $itemnumber = $item_sth->fetchrow_array) {
105         my $marc_item = C4::Items::GetMarcItem($biblionumber, $itemnumber);
106         unless ($marc_item) {
107             warn "FAILED C4::Items::GetMarcItem for biblionumber=$biblionumber, itemnumber=$itemnumber";
108             next;
109         }
110         foreach my $item_field ($marc_item->field($itemtag)) {
111             $bib->insert_fields_ordered($item_field);
112             $num_marc_items_added++;
113             $bib_modified = 1;
114         }
115     }
116
117     if ($bib_modified) {
118         ModBiblioMarc($bib, $biblionumber, GetFrameworkCode($biblionumber));
119         $num_bibs_modified++;
120     }
121
122 }
123
124 sub print_progress_and_commit {
125     my $recs = shift;
126     $dbh->commit();
127     print "... processed $recs records\n";
128 }
129
130 sub print_usage {
131     print <<_USAGE_;
132 $0: synchronize item data embedded in MARC bibs
133
134 Replaces the item data embedded in the MARC bib 
135 records (for indexing) with the authoritative 
136 item data as stored in the items table.
137
138 If Zebra is used, run rebuild_zebra.pl -b -r after
139 running this script.
140
141 NOTE: this script should be run only if there is
142 reason to suspect that the embedded item tags are
143 not in sync with the items table.
144
145 Parameters:
146     --run-update            run the synchronization
147     --where condition       selects the biblios on a criterium (Repeatable)
148     --help or -h            show this message.
149 _USAGE_
150 }