Bug 7593: Move orders on the destination record when merging 2 records
[koha.git] / cataloguing / merge.pl
1 #!/usr/bin/perl
2
3
4 # Copyright 2009 BibLibre
5 # Parts Copyright Catalyst IT 2011
6 #
7 # This file is part of Koha.
8 #
9 # Koha is free software; you can redistribute it and/or modify it under the
10 # terms of the GNU General Public License as published by the Free Software
11 # Foundation; either version 2 of the License, or (at your option) any later
12 # version.
13 #
14 # Koha is distributed in the hope that it will be useful, but WITHOUT ANY
15 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
16 # A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
17 #
18 # You should have received a copy of the GNU General Public License along
19 # with Koha; if not, write to the Free Software Foundation, Inc.,
20 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21
22 use strict;
23 #use warnings; FIXME - Bug 2505
24 use CGI;
25 use C4::Output;
26 use C4::Auth;
27 use C4::Items;
28 use C4::Biblio;
29 use C4::Serials;
30 use C4::Koha;
31 use C4::Reserves qw/MergeHolds/;
32 use C4::Acquisition qw/ModOrder GetOrdersByBiblionumber/;
33
34 my $input = new CGI;
35 my @biblionumber = $input->param('biblionumber');
36 my $merge = $input->param('merge');
37
38 my @errors;
39
40 my ( $template, $loggedinuser, $cookie ) = get_template_and_user(
41     {
42         template_name   => "cataloguing/merge.tmpl",
43         query           => $input,
44         type            => "intranet",
45         authnotrequired => 0,
46         flagsrequired   => { editcatalogue => 'edit_catalogue' },
47     }
48 );
49
50 #------------------------
51 # Merging
52 #------------------------
53 if ($merge) {
54
55     my $dbh = C4::Context->dbh;
56     my $sth;
57
58     # Creating a new record from the html code
59     my $record       = TransformHtmlToMarc( $input );
60     my $tobiblio     =  $input->param('biblio1');
61     my $frombiblio   =  $input->param('biblio2');
62
63     # Rewriting the leader
64     $record->leader(GetMarcBiblio($tobiblio)->leader());
65
66     my $frameworkcode = $input->param('frameworkcode');
67     my @notmoveditems;
68
69     # Modifying the reference record
70     ModBiblio($record, $tobiblio, $frameworkcode);
71
72     # Moving items from the other record to the reference record
73     # Also moving orders from the other record to the reference record, only if the order is linked to an item of the other record
74     my $itemnumbers = get_itemnumbers_of($frombiblio);
75     foreach my $itloop ($itemnumbers->{$frombiblio}) {
76     foreach my $itemnumber (@$itloop) {
77         my $res = MoveItemFromBiblio($itemnumber, $frombiblio, $tobiblio);
78         if (not defined $res) {
79             push @notmoveditems, $itemnumber;
80         }
81     }
82     }
83     # If some items could not be moved :
84     if (scalar(@notmoveditems) > 0) {
85         my $itemlist = join(' ',@notmoveditems);
86         push @errors, { code => "CANNOT_MOVE", value => $itemlist };
87     }
88
89     # Moving subscriptions from the other record to the reference record
90     my $subcount = CountSubscriptionFromBiblionumber($frombiblio);
91     if ($subcount > 0) {
92     $sth = $dbh->prepare("UPDATE subscription SET biblionumber = ? WHERE biblionumber = ?");
93     $sth->execute($tobiblio, $frombiblio);
94
95     $sth = $dbh->prepare("UPDATE subscriptionhistory SET biblionumber = ? WHERE biblionumber = ?");
96     $sth->execute($tobiblio, $frombiblio);
97
98     }
99
100     # Moving serials
101     $sth = $dbh->prepare("UPDATE serial SET biblionumber = ? WHERE biblionumber = ?");
102     $sth->execute($tobiblio, $frombiblio);
103
104     # TODO : Moving reserves
105
106     # Moving orders (orders linked to items of frombiblio have already been moved by MoveItemFromBiblio)
107     my @allorders = GetOrdersByBiblionumber($frombiblio);
108     my @tobiblioitem = GetBiblioItemByBiblioNumber ($tobiblio);
109     my $tobiblioitem_biblioitemnumber = $tobiblioitem [0]-> {biblioitemnumber };
110     foreach my $myorder (@allorders) {
111         $myorder->{'biblionumber'} = $tobiblio;
112         ModOrder ($myorder);
113     # TODO : add error control (in ModOrder?)
114     }
115
116     # Deleting the other record
117     if (scalar(@errors) == 0) {
118     # Move holds
119     MergeHolds($dbh,$tobiblio,$frombiblio);
120     my $error = DelBiblio($frombiblio);
121     push @errors, $error if ($error);
122     }
123
124     # Parameters
125     $template->param(
126     result => 1,
127     biblio1 => $input->param('biblio1')
128     );
129
130 #-------------------------
131 # Show records to merge
132 #-------------------------
133 } else {
134     my $mergereference = $input->param('mergereference');
135     my $biblionumber = $input->param('biblionumber');
136
137     if (scalar(@biblionumber) != 2) {
138         push @errors, { code => "WRONG_COUNT", value => scalar(@biblionumber) };
139     }
140     else {
141         my $data1 = GetBiblioData($biblionumber[0]);
142         my $record1 = GetMarcBiblio($biblionumber[0]);
143
144         my $data2 = GetBiblioData($biblionumber[1]);
145         my $record2 = GetMarcBiblio($biblionumber[1]);
146
147         # Checks if both records use the same framework
148         my $frameworkcode1 = &GetFrameworkCode($biblionumber[0]);
149         my $frameworkcode2 = &GetFrameworkCode($biblionumber[1]);
150
151
152         my $subtitle1 = GetRecordValue('subtitle', $record1, $frameworkcode1);
153         my $subtitle2 = GetRecordValue('subtitle', $record2, $frameworkcode1);
154
155         if ($mergereference) {
156
157             my $framework;
158             if ($frameworkcode1 ne $frameworkcode2) {
159                 $framework = $input->param('frameworkcode')
160                   or push @errors, "Famework not selected.";
161             } else {
162                 $framework = $frameworkcode1;
163             }
164
165             # Getting MARC Structure
166             my $tagslib = GetMarcStructure(1, $framework);
167
168             my $notreference = ($biblionumber[0] == $mergereference) ? $biblionumber[1] : $biblionumber[0];
169
170             # Creating a loop for display
171             my @record1 = _createMarcHash(GetMarcBiblio($mergereference), $tagslib);
172             my @record2 = _createMarcHash(GetMarcBiblio($notreference), $tagslib);
173
174             # Parameters
175             $template->param(
176                 biblio1 => $mergereference,
177                 biblio2 => $notreference,
178                 mergereference => $mergereference,
179                 record1 => @record1,
180                 record2 => @record2,
181                 framework => $framework,
182             );
183         }
184         else {
185
186         # Ask the user to choose which record will be the kept
187             $template->param(
188                 choosereference => 1,
189                 biblio1 => $biblionumber[0],
190                 biblio2 => $biblionumber[1],
191                 title1 => $data1->{'title'},
192                 subtitle1 => $subtitle1,
193                 title2 => $data2->{'title'},
194                 subtitle2 => $subtitle2
195             );
196             if ($frameworkcode1 ne $frameworkcode2) {
197                 my $frameworks = getframeworks;
198                 my @frameworkselect;
199                 foreach my $thisframeworkcode ( keys %$frameworks ) {
200                     my %row = (
201                         value         => $thisframeworkcode,
202                         frameworktext => $frameworks->{$thisframeworkcode}->{'frameworktext'},
203                     );
204                     if ($frameworkcode1 eq $thisframeworkcode){
205                         $row{'selected'} = 1;
206                         }
207                     push @frameworkselect, \%row;
208                 }
209                 $template->param(
210                     frameworkselect => \@frameworkselect,
211                     frameworkcode1 => $frameworkcode1,
212                     frameworkcode2 => $frameworkcode2,
213                 );
214             }
215         }
216     }
217 }
218
219 if (@errors) {
220     # Errors
221     $template->param( errors  => \@errors );
222 }
223
224 output_html_with_http_headers $input, $cookie, $template->output;
225 exit;
226
227 =head1 FUNCTIONS
228
229 =cut
230
231 # ------------------------
232 # Functions
233 # ------------------------
234 sub _createMarcHash {
235      my $record = shift;
236     my $tagslib = shift;
237     my @array;
238     my @fields = $record->fields();
239
240
241     foreach my $field (@fields) {
242     my $fieldtag = $field->tag();
243     if ($fieldtag < 10) {
244         if ($tagslib->{$fieldtag}->{'@'}->{'tab'} >= 0) {
245         push @array, {
246             field => [
247                     {
248                     tag => $fieldtag,
249                     key => createKey(),
250                     value => $field->data(),
251                     }
252                 ]
253                 };
254         }
255     } else {
256         my @subfields = $field->subfields();
257         my @subfield_array;
258         foreach my $subfield (@subfields) {
259         if ($tagslib->{$fieldtag}->{@$subfield[0]}->{'tab'} >= 0) {
260             push @subfield_array, {
261                                     subtag => @$subfield[0],
262                                     subkey => createKey(),
263                                     value => @$subfield[1],
264                                   };
265         }
266
267         }
268
269         if ($tagslib->{$fieldtag}->{'tab'} >= 0 && $fieldtag ne '995') {
270         push @array, {
271             field => [
272                 {
273                     tag => $fieldtag,
274                     key => createKey(),
275                     indicator1 => $field->indicator(1),
276                     indicator2 => $field->indicator(2),
277                     subfield   => [@subfield_array],
278                 }
279             ]
280             };
281         }
282
283     }
284     }
285     return [@array];
286
287 }
288
289 =head2 CreateKey
290
291 Create a random value to set it into the input name
292
293 =cut
294
295 sub createKey {
296     return int(rand(1000000));
297 }
298