Bug 15632: Koha::Patron::Messages - Remove GetMessagesCount
[koha.git] / misc / maintenance / UNIMARC_sync_date_created_with_marc_biblio.pl
1 #!/usr/bin/perl
2 #
3 # This script should be used only with UNIMARC flavour
4 # It is designed to report some missing information from biblio
5 # table into marc data
6 #
7 use strict;
8 use warnings;
9
10 BEGIN {
11     use FindBin;
12     eval { require "$FindBin::Bin/../kohalib.pl" };
13 }
14
15 use C4::Biblio;
16 use Getopt::Long;
17
18 sub _read_marc_code {
19     my $input = shift;
20     my ( $field, $subfield );
21     if ( $input =~ /^(\d{3})$/ ) {
22         $field = $1;
23     }
24     elsif ( $input =~ /^(\d{3})(\w)$/ ) {
25         $field    = $1;
26         $subfield = $2;
27     }
28     return ( $field, $subfield );
29 }
30
31 my ( $run, $help, $verbose, $where, $date_created_marc, $date_modified_marc );
32 GetOptions(
33     'help|h'                 => \$help,
34     'verbose|v'              => \$verbose,
35     'run'                    => \$run,
36     'where:s'                => \$where,
37     'date-created-marc|c:s'  => \$date_created_marc,
38     'date-modified-marc|m:s' => \$date_modified_marc,
39 );
40 my $debug = $ENV{DEBUG};
41 $verbose = 1 if $debug;
42
43 # display help ?
44 if ($help) {
45     print_usage();
46     exit 0;
47 }
48
49 $verbose and print "================================\n";
50
51 # date created MARC field/subfield
52 $date_created_marc = '099c' unless $date_created_marc;
53 my ( $c_field, $c_subfield ) = _read_marc_code($date_created_marc);
54 die "date-created-marc '$date_created_marc' is not correct." unless $c_field;
55 die "date-created-marc field is greated that 009, it should have a subfield."
56   if ( $c_field > 9 && !defined $c_subfield );
57 die "date-created-marc field is lower that 010, it should not have a subfield."
58   if ( $c_field < 10 && defined $c_subfield );
59 if ($verbose) {
60     print "Date created on $c_field";
61     print $c_subfield if defined $c_subfield;    # use of defined to allow 0
62     print "\n";
63 }
64
65 # date last modified MARC field/subfield
66 $date_modified_marc = '099d' unless $date_modified_marc;
67 my ( $m_field, $m_subfield ) = _read_marc_code($date_modified_marc);
68 die "date-modified-marc '$date_modified_marc' is not correct." unless $m_field;
69 die "date-modified-marc field is greated that 009, it should have a subfield."
70   if ( $m_field > 9 && !defined $m_subfield );
71 die "date-modified-marc field is lower that 010, it should not have a subfield."
72   if ( $m_field < 10 && defined $m_subfield );
73 die
74 "When date-created-marc and date-modified-marc are on same field, they should have distinct subfields"
75   if ( $c_field eq $m_field )
76   && ( !defined $c_subfield
77     || !defined $m_subfield
78     || $c_subfield eq $m_subfield );
79 if ($verbose) {
80     print "Date last modified on $m_field";
81     print $m_subfield if defined $m_subfield;    # use of defined to allow 0
82     print "\n";
83 }
84
85 my $dbh;
86 my $sth_prepared;
87
88 sub updateMarc {
89     my $id     = shift;
90     my $biblio = GetMarcBiblio($id);
91
92     unless ($biblio) {
93         $debug and warn '[ERROR] GetMarcBiblio did not return any biblio.';
94         return;
95     }
96
97     my $c_marc_field = $biblio->field($c_field);
98     my $m_marc_field = $biblio->field($m_field);
99
100     my $c_marc_value;
101     if ($c_marc_field) {
102         $c_marc_value =
103           defined $c_subfield
104           ? $c_marc_field->subfield($c_subfield)
105           : $c_marc_field->data();
106     }
107     $c_marc_value = '' unless defined $c_marc_value;
108
109     my $m_marc_value;
110     if ($m_marc_field) {
111         $m_marc_value =
112           defined $m_subfield
113           ? $m_marc_field->subfield($m_subfield)
114           : $m_marc_field->data();
115     }
116     $m_marc_value ||= '';
117
118     $sth_prepared = $dbh->prepare(
119         q{
120         SELECT
121             DATE_FORMAT(datecreated,'%Y-%m-%d') AS datecreatediso,
122             DATE_FORMAT(timestamp,'%Y-%m-%d') AS datemodifiediso,
123             frameworkcode
124         FROM biblio
125         WHERE biblionumber = ?
126     }
127     ) unless $sth_prepared;
128     $sth_prepared->execute($id);
129     my $bibliorow     = $sth_prepared->fetchrow_hashref;
130     my $frameworkcode = $bibliorow->{'frameworkcode'};
131     my $c_db_value    = $bibliorow->{'datecreatediso'} || '';
132     my $m_db_value    = $bibliorow->{'datemodifiediso'} || '';
133
134     # do nothing if already sync
135     return if ( $c_marc_value eq $c_db_value && $m_marc_value eq $m_db_value );
136
137     # do apply to database ?
138     return 1 unless $run;
139
140     # update MARC record
141
142     # date created field
143     unless ($c_marc_field) {
144         if ( defined $c_subfield ) {
145             $biblio->add_fields(
146                 new MARC::Field(
147                     $c_field, ' ', ' ', $c_subfield => $c_db_value
148                 )
149             );
150         }
151         else {
152             $biblio->add_fields( new MARC::Field( $c_field, $c_db_value ) );
153         }
154         $debug and warn "[WARN] $c_field did not exist.";
155         $c_marc_field = $biblio->field($c_field);
156
157         # when on same field
158         if ( $m_field eq $c_field ) {
159             $m_marc_field = $c_marc_field;
160         }
161     }
162     else {
163         if ( defined $c_subfield ) {
164             $c_marc_field->update( $c_subfield, $c_db_value );
165         }
166         else {
167             $c_marc_field->update($c_db_value);
168         }
169     }
170
171     # date last modified field
172     unless ($m_marc_field) {
173         if ( defined $m_subfield ) {
174             $biblio->add_fields(
175                 new MARC::Field(
176                     $m_field, ' ', ' ', $m_subfield => $m_db_value
177                 )
178             );
179         }
180         else {
181             $biblio->add_fields( new MARC::Field( $m_field, $m_db_value ) );
182         }
183
184         $debug and warn "[WARN] $m_field did not exist.";
185         $m_marc_field = $biblio->field($m_field);
186     }
187     else {
188         if ( defined $m_subfield ) {
189             $m_marc_field->update( $m_subfield, $m_db_value );
190         }
191         else {
192             $m_marc_field->update($m_db_value);
193         }
194     }
195
196     # apply to databse
197     if ( &ModBiblio( $biblio, $id, $frameworkcode ) ) {
198         return 1;
199     }
200
201     $debug and warn '[ERROR] ModBiblio failed.';
202     return;
203 }
204
205 sub process {
206
207     $dbh = C4::Context->dbh;
208     my $mod_count = 0;
209
210     my $query = q{
211         SELECT biblionumber
212         FROM biblio
213         JOIN biblioitems USING (biblionumber)
214     };
215     $query .= qq{ WHERE $where} if $where;
216     my $sth = $dbh->prepare($query);
217     $sth->execute();
218
219     $verbose and print "Number of concerned biblios: " . $sth->rows . "\n";
220
221     while ( my $biblios = $sth->fetchrow_hashref ) {
222         $verbose and print 'Bib ' . $biblios->{'biblionumber'} . ':';
223         my $ret = updateMarc( $biblios->{'biblionumber'} );
224         if ($ret) {
225             $verbose and print 'modified';
226             $mod_count++;
227         }
228         $verbose and print "\n";
229     }
230
231     $verbose and print "Number of modified biblios: " . $mod_count . "\n";
232 }
233
234 if ( lc( C4::Context->preference('marcflavour') ) eq "unimarc" ) {
235     $verbose
236       and !$run
237       and print "*** Not in run mode, modifications will not be applyed ***\n";
238
239     $verbose and print "================================\n";
240     process();
241 }
242 else {
243     print
244 "This script is UNIMARC only and should be used only on UNIMARC databases\n";
245 }
246
247 sub print_usage {
248     print <<_USAGE_;
249 Synchronizes date created and date last modified from biblio table to MARC data.
250 Does not update biblio if dates are already synchronized.
251 UNIMARC specific.
252
253 Parameters:
254     --help or -h                show this message
255     --verbose or -v             verbose logging
256     --run                       run the command else modifications will not be applied to database
257     --where                     (optional) use this to limit execution to some biblios :
258                                 write a SQL where clause using biblio and/or biblioitems fields
259     --date-created-marc or c    (optional) date created MARC field and optional subfield,
260                                 099c by default
261     --date-modified-marc or m   (optional) date last modified MARC field and optional subfield,
262                                 099d by default
263 _USAGE_
264 }