Improve performance and fault tolerance for sync_items...
[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
22 my $result = GetOptions(
23     'run-update'    => \$do_update,
24     'h|help'        => \$want_help,
25 );
26
27 if (not $result or $want_help or not $do_update) {
28     print_usage();
29     exit 0;
30 }
31
32 my $num_bibs_processed     = 0;
33 my $num_bibs_modified      = 0;
34 my $num_marc_items_deleted = 0;
35 my $num_marc_items_added   = 0;
36 my $num_bad_bibs           = 0;
37 my $dbh = C4::Context->dbh;
38 $dbh->{AutoCommit} = 0;
39
40 our ($itemtag, $itemsubfield) = GetMarcFromKohaField("items.itemnumber", '');
41 our ($item_sth) = $dbh->prepare("SELECT itemnumber FROM items WHERE biblionumber = ?");
42
43 process_bibs();
44 $dbh->commit();
45
46 exit 0;
47
48 sub process_bibs {
49     my $sql = "SELECT biblionumber FROM biblio ORDER BY biblionumber ASC";
50     my $sth = $dbh->prepare($sql);
51     $sth->execute();
52     while (my ($biblionumber) = $sth->fetchrow_array()) {
53         $num_bibs_processed++;
54         process_bib($biblionumber);
55
56         if (($num_bibs_processed % 100) == 0) {
57             print_progress_and_commit($num_bibs_processed);
58         }
59     }
60
61     $dbh->commit;
62
63     print <<_SUMMARY_;
64
65 Embedded item synchronization report
66 ------------------------------------
67 Number of bibs checked:                   $num_bibs_processed
68 Number of bibs modified:                  $num_bibs_modified
69 Number of item fields removed from bibs:  $num_marc_items_deleted
70 Number of item fields added to bibs:      $num_marc_items_added
71 Number of bibs with errors:               $num_bad_bibs
72 _SUMMARY_
73 }
74
75 sub process_bib {
76     my $biblionumber = shift;
77
78     my $bib = GetMarcBiblio($biblionumber);
79     unless (defined $bib) {
80         print "\nCould not retrieve bib $biblionumber from the database - record is corrupt.\n";
81         $num_bad_bibs++;
82         return;
83     }
84
85     my $bib_modified = 0;
86
87     # delete any item tags
88     foreach my $field ($bib->field($itemtag)) {
89         unless ($bib->delete_field($field)) {
90             warn "Could not delete item in $itemtag for biblionumber $biblionumber";
91             next;
92         }
93         $num_marc_items_deleted++;
94         $bib_modified = 1;
95     }
96
97     # add back items from items table
98     $item_sth->execute($biblionumber);
99     while (my $itemnumber = $item_sth->fetchrow_array) {
100         my $marc_item = C4::Items::GetMarcItem($biblionumber, $itemnumber);
101         unless ($marc_item) {
102             warn "FAILED C4::Items::GetMarcItem for biblionumber=$biblionumber, itemnumber=$itemnumber";
103             next;
104         }
105         foreach my $item_field ($marc_item->field($itemtag)) {
106             $bib->insert_fields_ordered($item_field);
107             $num_marc_items_added++;
108             $bib_modified = 1;
109         }
110     }
111
112     if ($bib_modified) {
113         ModBiblioMarc($bib, $biblionumber, GetFrameworkCode($biblionumber));
114         $num_bibs_modified++;
115     }
116
117 }
118
119 sub print_progress_and_commit {
120     my $recs = shift;
121     $dbh->commit();
122     print "... processed $recs records\n";
123 }
124
125 sub print_usage {
126     print <<_USAGE_;
127 $0: synchronize item data embedded in MARC bibs
128
129 Replaces the item data embedded in the MARC bib 
130 records (for indexing) with the authoritative 
131 item data as stored in the items table.
132
133 If Zebra is used, run rebuild_zebra.pl -b -r after
134 running this script.
135
136 NOTE: this script should be run only if there is
137 reason to suspect that the embedded item tags are
138 not in sync with the items table.
139
140 Parameters:
141     --run-update            run the synchronization
142     --help or -h            show this message.
143 _USAGE_
144 }