Another purely documentation commit. Just changing formatting to ease
[koha.git] / C4 / Biblio.pm
1 package C4::Biblio;
2
3 # Copyright 2000-2002 Katipo Communications
4 #
5 # This file is part of Koha.
6 #
7 # Koha is free software; you can redistribute it and/or modify it under the
8 # terms of the GNU General Public License as published by the Free Software
9 # Foundation; either version 2 of the License, or (at your option) any later
10 # version.
11 #
12 # Koha is distributed in the hope that it will be useful, but WITHOUT ANY
13 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
14 # A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License along with
17 # Koha; if not, write to the Free Software Foundation, Inc., 59 Temple Place,
18 # Suite 330, Boston, MA  02111-1307 USA
19
20 use strict;
21 require Exporter;
22 use C4::Context;
23 use C4::Database;
24 use C4::Date;
25 use MARC::Record;
26 use MARC::File::USMARC;
27 use MARC::File::XML;
28 use ZOOM;
29
30 use vars qw($VERSION @ISA @EXPORT);
31
32 # set the version for version checking
33 $VERSION = do { my @v = '$Revision$' =~ /\d+/g;
34                 shift(@v) . "." . join("_", map {sprintf "%03d", $_ } @v); };
35
36 @ISA = qw(Exporter);
37
38 #
39 # don't forget MARCxxx subs are exported only for testing purposes. Should not be used
40 # as the old-style API and the NEW one are the only public functions.
41 #
42 @EXPORT = qw(
43   &newbiblio &newbiblioitem
44   &newsubject &newsubtitle &newitems 
45   
46   &modbiblio &checkitems &modbibitem
47   &modsubtitle &modsubject &modaddauthor &moditem
48   
49   &delitem &deletebiblioitem &delbiblio
50   
51   &getbiblio &bibdata &bibitems &bibitemdata 
52   &barcodes &ItemInfo &itemdata &itemissues &itemcount 
53   &getsubject &getaddauthor &getsubtitle
54   &getwebbiblioitems &getwebsites
55   &getbiblioitembybiblionumber
56   &getbiblioitem &getitemsbybiblioitem
57
58   &MARCfind_marc_from_kohafield
59   &MARCfind_frameworkcode
60   &find_biblioitemnumber
61   &MARCgettagslib
62
63   &NEWnewbiblio &NEWnewitem
64   &NEWmodbiblio &NEWmoditem
65   &NEWdelbiblio &NEWdelitem
66   &NEWmodbiblioframework
67
68   &MARCkoha2marcBiblio &MARCmarc2koha
69   &MARCkoha2marcItem &MARChtml2marc
70   &MARCgetbiblio &MARCgetitem
71   &XMLgetbiblio
72   
73   &FindDuplicate
74   &DisplayISBN
75
76   &z3950_extended_services
77   &set_service_options
78   
79   &get_item_from_barcode
80   &MARCfind_MARCbibid_from_oldbiblionumber
81
82 );
83
84 =head1 NAME
85
86 C4::Biblio - Acquisitions, Catalog Management Functions
87
88 =head1 SYNOPSIS
89
90 ( lot of changes for Koha 3.X)
91
92 Koha 1.2 and previous versions used a specific API to manage biblios. This API uses old-DB style parameters.
93 They are based on a hash, and store data in biblio/biblioitems/items tables (plus additionalauthors, 
94 bibliosubject and bibliosubtitle where applicable).
95
96 In Koha 2.X, we introduced a MARC-DB.
97
98 In Koha 3.X, we removed this MARC-DB for search as we wanted to use Zebra as search system.
99
100 So in Koha 3.X, saving a record means :
101
102  - storing the raw marc record (iso2709) in biblioitems.marc field. It contains both biblio & items information.
103  - storing the "decoded information" in biblio/biblioitems/items as previously.
104  - using zebra to manage search & indexing on the MARC data.
105  
106  In Koha, there is a systempreference for "MARC=ON" or "MARC=OFF" :
107  
108  * MARC=ON : when MARC=ON, Koha uses a MARC::Record object (in sub parameters). Saving information in the DB means : 
109
110  - transform the MARC record into a hash
111  - add the raw MARC record into the hash
112  - store them & update Zebra
113  
114  * MARC=OFF : when MARC=OFF, Koha uses a hash object (in sub parameters). Saving information in the DB means :
115
116  - transform the hash into a MARC record
117  - add the raw marc record into the hash
118  - store them & update zebra
119  
120 That's why we need 3 types of subs :
121
122 =head2 REALxxx subs
123
124 all I<subs beginning by REAL> do the effective storage of information (with a hash, one field of the hash being the raw marc record). Those subs also update the record in Zebra. REAL subs should be only for internal use (called by NEW or "something else" subs).
125
126 =head2 NEWxxx related subs
127
128 =over 4
129
130 all I<subs beginning by NEW> use MARC::Record as parameters. It's the API that MUST be used in the MARC acquisition system. They just create the hash, add it the raw marc record. Then, they call REALxxx sub.
131
132 all subs requires/use $dbh as 1st parameter and a MARC::Record object as 2nd parameter. They sometimes require another parameter.
133
134 =back
135
136 =head2 something_elsexxx related subs
137
138 =over 4
139
140 all I<subs beginning by seomething else> are the old-style API. They use a hash as parameter, transform the hash into a -small- marc record, and call REAL subs.
141
142 all subs require/use $dbh as 1st parameter and a hash as 2nd parameter.
143
144 =back
145
146 =head1 FUNCTIONS
147
148 =head2 z3950_extended_services
149
150 z3950_extended_services($Zconn,$serviceType,$serviceOptions,$record);
151
152         z3950_extended_services is used to handle all interactions with Zebra's extended serices package.
153
154 C<$Zconn> a connection object to the Zebra server
155
156 C<$serviceType> one of: itemorder,create,drop,commit,update,xmlupdate
157
158 C<$serviceOptions> a has of key/value pairs. For instance, if service_type is 'update', $service_options should contain:
159
160         action => update action, one of specialUpdate, recordInsert, recordReplace, recordDelete, elementUpdate.
161
162 and maybe
163
164         recordidOpaque => Opaque Record ID (user supplied) or recordidNumber => Record ID number (system number).
165         syntax => the record syntax (transfer syntax)
166         databaseName = Database from connection object
167
168         To set serviceOptions, call set_service_options($serviceType)
169
170 C<$record> the record, if one is needed for the service type
171
172         A record should be in XML. You can convert it to XML from MARC by running it through marc2xml().
173
174 =cut
175 sub z3950_extended_services {
176         my ($Zconn,$serviceType,$serviceOptions,$record) = @_;
177         
178         # create a new package object
179         my $Zpackage = $Zconn->package();
180
181         # set our options
182         $Zpackage->option(action => $serviceOptions->{'action'});
183
184         if ($serviceOptions->{'databaseName'}) {
185                 $Zpackage->option(databaseName => $serviceOptions->{'databaseName'});
186         }
187         if ($serviceOptions->{'recordIdNumber'}) {
188                 $Zpackage->option(recordIdNumber => $serviceOptions->{'recordIdNumber'});
189         }
190         if ($serviceOptions->{'recordIdOpaque'}) {
191                 $Zpackage->option(recordIdOpaque => $serviceOptions->{'recordIdOpaque'});
192         }
193
194         # this is an ILL request (Zebra doesn't support it)
195         #if ($serviceType eq 'itemorder') {
196         #   $Zpackage->option('contact-name' => $serviceOptions->{'contact-name'});
197         #   $Zpackage->option('contact-phone' => $serviceOptions->{'contact-phone'});
198         #   $Zpackage->option('contact-email' => $serviceOptions->{'contact-email'});
199         #   $Zpackage->option('itemorder-item' => $serviceOptions->{'itemorder-item'});
200         #}
201
202         if ($record) {
203                 my $xmlrecord = marc2xml($record);
204                 $Zpackage->option(record => $xmlrecord);
205                 if ($serviceOptions->{'syntax'}) {
206                         $Zpackage->option(syntax => $serviceOptions->{'syntax'});
207                 }
208         }
209
210         # send the request, handle any exception encountered
211         eval { $Zpackage->send($serviceType) };
212                 if ($@ && $@->isa("ZOOM::Exception")) {
213                         print "Oops!  ", $@->message(), "\n";
214                         return $@->code();
215                 }
216         # free up package resources
217         $Zpackage->destroy();
218 }
219
220 =head2 set_service_options
221
222 my $serviceOptions = set_service_options($serviceType);
223
224 C<$serviceType> itemorder,create,drop,commit,update,xmlupdate
225
226 Currently, we only support 'create', 'commit', and 'update'. 'drop' support will be added as soon as Zebra supports it.
227
228 =cut
229
230 sub set_service_options {
231         my ($serviceType) = @_;
232         my $serviceOptions;
233
234         if ($serviceType eq 'update') {
235                 $serviceOptions->{ 'action' } = 'specialUpdate';
236
237         # FIXME: This needs to be an OID ... if we ever need 'syntax' this sub will need to change
238         #       $serviceOptions->{ 'syntax' } = ''; #zebra doesn't support syntaxes other than xml
239         }
240
241         if ($serviceType eq 'commit') {
242         # nothing to do
243
244         }
245         if ($serviceType eq 'create') {
246         # nothing to do
247         }
248         if ($serviceType eq 'drop') {
249                 die "ERROR: 'drop' not currently supported (by Zebra)";
250         }
251         return $serviceOptions;
252 }
253
254 =head2 marc2xml
255
256 my $xmlrecord = marc2xml($record);
257
258 Convert from MARC to XML. Note that MARC::File::XML will automatically encode from MARC-8 to UTF-8 as of version .8
259
260 C<$record> a MARC record
261
262 =cut
263
264 sub marc2xml {
265         my ($record) = @_;
266         my $xmlrecord;
267         eval { $xmlrecord=$record->as_xml() };
268         #TODO: better error handling here
269         if ($@){
270                 warn "ERROR: I suspect a badly formatted MARC record";
271         }
272         return $xmlrecord;
273 }
274
275 =head2 MARCgettagslib
276
277 @tagslib = &MARCgettagslib($dbh,1|0,$frameworkcode);
278
279 =over 4
280
281 2nd param is 1 for liblibrarian and 0 for libopac
282 $frameworkcode contains the framework reference. If empty or does not exist, the default one is used
283
284 returns a hash with all values for all fields and subfields for a given MARC framework :
285         $res->{$tag}->{lib}        = ($forlibrarian or !$libopac)?$liblibrarian:$libopac;
286                     ->{tab}        = "";            # XXX
287                     ->{mandatory}  = $mandatory;
288                     ->{repeatable} = $repeatable;
289                     ->{$subfield}->{lib}              = ($forlibrarian or !$libopac)?$liblibrarian:$libopac;
290                                  ->{tab}              = $tab;
291                                  ->{mandatory}        = $mandatory;
292                                  ->{repeatable}       = $repeatable;
293                                  ->{authorised_value} = $authorised_value;
294                                  ->{authtypecode}     = $authtypecode;
295                                  ->{value_builder}    = $value_builder;
296                                  ->{kohafield}        = $kohafield;
297                                  ->{seealso}          = $seealso;
298                                  ->{hidden}           = $hidden;
299                                  ->{isurl}            = $isurl;
300                                  ->{link}            = $link;
301
302 =back
303
304 =cut
305
306 sub MARCgettagslib {
307     my ( $dbh, $forlibrarian, $frameworkcode ) = @_;
308     $frameworkcode = "" unless $frameworkcode;
309     $forlibrarian = 1 unless $forlibrarian;
310     my $sth;
311     my $libfield = ( $forlibrarian eq 1 ) ? 'liblibrarian' : 'libopac';
312
313     # check that framework exists
314     $sth =
315       $dbh->prepare(
316         "select count(*) from marc_tag_structure where frameworkcode=?");
317     $sth->execute($frameworkcode);
318     my ($total) = $sth->fetchrow;
319     $frameworkcode = "" unless ( $total > 0 );
320     $sth =
321       $dbh->prepare(
322 "select tagfield,liblibrarian,libopac,mandatory,repeatable from marc_tag_structure where frameworkcode=? order by tagfield"
323     );
324     $sth->execute($frameworkcode);
325     my ( $liblibrarian, $libopac, $tag, $res, $tab, $mandatory, $repeatable );
326
327     while ( ( $tag, $liblibrarian, $libopac, $mandatory, $repeatable ) = $sth->fetchrow ) {
328         $res->{$tag}->{lib}        = ($forlibrarian or !$libopac)?$liblibrarian:$libopac;
329         $res->{$tag}->{tab}        = "";            # XXX
330         $res->{$tag}->{mandatory}  = $mandatory;
331         $res->{$tag}->{repeatable} = $repeatable;
332     }
333
334     $sth =
335       $dbh->prepare(
336 "select tagfield,tagsubfield,liblibrarian,libopac,tab, mandatory, repeatable,authorised_value,authtypecode,value_builder,kohafield,seealso,hidden,isurl,link from marc_subfield_structure where frameworkcode=? order by tagfield,tagsubfield"
337     );
338     $sth->execute($frameworkcode);
339
340     my $subfield;
341     my $authorised_value;
342     my $authtypecode;
343     my $value_builder;
344     my $kohafield;
345     my $seealso;
346     my $hidden;
347     my $isurl;
348         my $link;
349
350     while (
351         ( $tag,         $subfield,   $liblibrarian,   , $libopac,      $tab,
352         $mandatory,     $repeatable, $authorised_value, $authtypecode,
353         $value_builder, $kohafield,  $seealso,          $hidden,
354         $isurl,                 $link )
355         = $sth->fetchrow
356       )
357     {
358         $res->{$tag}->{$subfield}->{lib}              = ($forlibrarian or !$libopac)?$liblibrarian:$libopac;
359         $res->{$tag}->{$subfield}->{tab}              = $tab;
360         $res->{$tag}->{$subfield}->{mandatory}        = $mandatory;
361         $res->{$tag}->{$subfield}->{repeatable}       = $repeatable;
362         $res->{$tag}->{$subfield}->{authorised_value} = $authorised_value;
363         $res->{$tag}->{$subfield}->{authtypecode}     = $authtypecode;
364         $res->{$tag}->{$subfield}->{value_builder}    = $value_builder;
365         $res->{$tag}->{$subfield}->{kohafield}        = $kohafield;
366         $res->{$tag}->{$subfield}->{seealso}          = $seealso;
367         $res->{$tag}->{$subfield}->{hidden}           = $hidden;
368         $res->{$tag}->{$subfield}->{isurl}            = $isurl;
369         $res->{$tag}->{$subfield}->{link}            = $link;
370     }
371     return $res;
372 }
373
374 =head2 MARCfind_marc_from_kohafield
375
376 ($tagfield,$tagsubfield) = &MARCfind_marc_from_kohafield($dbh,$kohafield);
377
378 =over 4
379
380 finds MARC tag and subfield for a given kohafield
381 kohafield is "table.field" where table= biblio|biblioitems|items, and field a field of the previous table
382
383 =back
384
385 =cut
386
387 sub MARCfind_marc_from_kohafield {
388     my ( $dbh, $kohafield,$frameworkcode ) = @_;
389     return 0, 0 unless $kohafield;
390     $frameworkcode='' unless $frameworkcode;
391         my $relations = C4::Context->marcfromkohafield;
392         return ($relations->{$frameworkcode}->{$kohafield}->[0],$relations->{$frameworkcode}->{$kohafield}->[1]);
393 }
394
395 =head2 MARCgetbiblio
396
397 $MARCRecord = &MARCgetbiblio($dbh,$biblionumber);
398
399 =over 4
400
401 Returns a MARC::Record for the biblio $biblionumber.
402
403 =cut
404
405 sub MARCgetbiblio {
406
407     # Returns MARC::Record of the biblio passed in parameter.
408     my ( $dbh, $biblionumber ) = @_;
409         my $sth = $dbh->prepare('select marc from biblioitems where biblionumber=?');
410         $sth->execute($biblionumber);
411         my ($marc) = $sth->fetchrow;
412         my $record = MARC::Record::new_from_usmarc($marc);
413     return $record;
414 }
415
416 =head2 XMLgetbiblio
417
418 $XML = &XMLgetbiblio($dbh,$biblionumber);
419
420 =over 4
421
422 Returns a raw XML for the biblio $biblionumber.
423
424 =cut
425
426 sub XMLgetbiblio {
427
428     # Returns MARC::Record of the biblio passed in parameter.
429     my ( $dbh, $biblionumber ) = @_;
430         my $sth = $dbh->prepare('select marcxml,marc from biblioitems where biblionumber=?');
431         $sth->execute($biblionumber);
432         my ($XML,$marc) = $sth->fetchrow;
433 #       my $record =MARC::Record::new_from_usmarc($marc);
434 #       warn "MARC : \n*-************************\n".$record->as_xml."\n*-************************\n";
435     return $XML;
436 }
437
438 =head2 MARCgetitem
439
440 $MARCrecord = &MARCgetitem($dbh,$biblionumber);
441
442 =over 4
443
444 Returns a MARC::Record with all items of biblio # $biblionumber
445
446 =back
447
448 =cut
449
450 sub MARCgetitem {
451
452     my ( $dbh, $biblionumber, $itemnumber ) = @_;
453         my $frameworkcode=MARCfind_frameworkcode($dbh,$biblionumber);
454         # get the complete MARC record
455         my $sth = $dbh->prepare("select marc from biblioitems where biblionumber=?");
456         $sth->execute($biblionumber);
457         my ($rawmarc) = $sth->fetchrow;
458         my $record = MARC::File::USMARC::decode($rawmarc);
459         # now, find the relevant itemnumber
460         my ($itemnumberfield,$itemnumbersubfield) = MARCfind_marc_from_kohafield($dbh,'items.itemnumber',$frameworkcode);
461         # prepare the new item record
462         my $itemrecord = MARC::Record->new();
463         # parse all fields fields from the complete record
464         foreach ($record->field($itemnumberfield)) {
465                 # when the item field is found, save it
466                 if ($_->subfield($itemnumbersubfield) == $itemnumber) {
467                         $itemrecord->append_fields($_);
468                 }
469         }
470
471     return $itemrecord;
472 }
473
474 =head2 find_biblioitemnumber
475
476 my $biblioitemnumber = find_biblioitemnumber($dbh,$biblionumber);
477
478 =over 4
479
480 Returns the 1st biblioitemnumber related to $biblionumber. When MARC=ON we should have 1 biblionumber = 1 and only 1 biblioitemnumber
481 This sub is useless when MARC=OFF
482
483 =back
484
485 =cut
486 sub find_biblioitemnumber {
487         my ( $dbh, $biblionumber ) = @_;
488         my $sth = $dbh->prepare("select biblioitemnumber from biblioitems where biblionumber=?");
489         $sth->execute($biblionumber);
490         my ($biblioitemnumber) = $sth->fetchrow;
491         return $biblioitemnumber;
492 }
493
494 =head2 MARCfind_frameworkcode
495
496 my $frameworkcode = MARCfind_frameworkcode($dbh,$biblionumber);
497
498 =over 4
499
500 returns the framework of a given biblio
501
502 =back
503
504 =cut
505
506 sub MARCfind_frameworkcode {
507         my ( $dbh, $biblionumber ) = @_;
508         my $sth = $dbh->prepare("select frameworkcode from biblio where biblionumber=?");
509         $sth->execute($biblionumber);
510         my ($frameworkcode) = $sth->fetchrow;
511         return $frameworkcode;
512 }
513
514 =head2 MARCkoha2marcBiblio
515
516 $MARCRecord = &MARCkoha2marcBiblio($dbh,$bibliohash);
517
518 =over 4
519
520 MARCkoha2marcBiblio is a wrapper between old-DB and MARC-DB. It returns a MARC::Record builded with old-DB biblio/biblioitem :
521 all entries of the hash are transformed into their matching MARC field/subfield.
522
523 =back
524
525 =cut
526
527 sub MARCkoha2marcBiblio {
528
529         # this function builds partial MARC::Record from the old koha-DB fields
530         my ( $dbh, $bibliohash ) = @_;
531         # we don't have biblio entries in the hash, so we add them first
532         my $sth = $dbh->prepare("select * from biblio where biblionumber=?");
533         $sth->execute($bibliohash->{biblionumber});
534         my $biblio = $sth->fetchrow_hashref;
535         foreach (keys %$biblio) {
536                 $bibliohash->{$_}=$biblio->{$_};
537         }
538         $sth = $dbh->prepare("select tagfield,tagsubfield from marc_subfield_structure where frameworkcode=? and kohafield=?");
539         my $record = MARC::Record->new();
540         foreach ( keys %$bibliohash ) {
541                 &MARCkoha2marcOnefield( $sth, $record, "biblio." . $_, $bibliohash->{$_}, '') if $bibliohash->{$_};
542                 &MARCkoha2marcOnefield( $sth, $record, "biblioitems." . $_, $bibliohash->{$_}, '') if $bibliohash->{$_};
543         }
544
545         # other fields => additional authors, subjects, subtitles
546         my $sth2 = $dbh->prepare(" SELECT author FROM additionalauthors WHERE biblionumber=?");
547         $sth2->execute($bibliohash->{biblionumber});
548         while ( my $row = $sth2->fetchrow_hashref ) {
549                 &MARCkoha2marcOnefield( $sth, $record, "additionalauthors.author", $bibliohash->{'author'},'' );
550         }
551         $sth2 = $dbh->prepare(" SELECT subject FROM bibliosubject WHERE biblionumber=?");
552         $sth2->execute($bibliohash->{biblionumber});
553         while ( my $row = $sth2->fetchrow_hashref ) {
554                 &MARCkoha2marcOnefield( $sth, $record, "bibliosubject.subject", $row->{'subject'},'' );
555         }
556         $sth2 = $dbh->prepare(" SELECT subtitle FROM bibliosubtitle WHERE biblionumber=?");
557         $sth2->execute($bibliohash->{biblionumber});
558         while ( my $row = $sth2->fetchrow_hashref ) {
559                 &MARCkoha2marcOnefield( $sth, $record, "bibliosubtitle.subtitle", $row->{'subtitle'},'' );
560         }
561         
562         return $record;
563 }
564
565 =head2 MARCkoha2marcItem
566
567 $MARCRecord = &MARCkoha2marcItem($dbh,$biblionumber,itemnumber);
568
569 MARCkoha2marcItem is a wrapper between old-DB and MARC-DB. It returns a MARC::Record builded with old-DB items :
570 all entries of the hash are transformed into their matching MARC field/subfield.
571
572 =over 4
573
574 =back
575
576 =cut
577
578 sub MARCkoha2marcItem {
579
580     # this function builds partial MARC::Record from the old koha-DB fields
581     my ( $dbh, $item ) = @_;
582
583     #    my $dbh=&C4Connect;
584     my $sth = $dbh->prepare("select tagfield,tagsubfield from marc_subfield_structure where frameworkcode=? and kohafield=?");
585     my $record = MARC::Record->new();
586
587         foreach( keys %$item ) {
588                 if ( $item->{$_} ) {
589                         &MARCkoha2marcOnefield( $sth, $record, "items." . $_,
590                                 $item->{$_},'' );
591                 }
592         }
593     return $record;
594 }
595
596 =head2 MARCkoha2marcOnefield
597
598 =over 4
599
600 This sub is for internal use only, used by koha2marcBiblio & koha2marcItem
601
602 =back
603
604 =cut
605
606 sub MARCkoha2marcOnefield {
607     my ( $sth, $record, $kohafieldname, $value,$frameworkcode ) = @_;
608     my $tagfield;
609     my $tagsubfield;
610     $sth->execute($frameworkcode,$kohafieldname);
611     if ( ( $tagfield, $tagsubfield ) = $sth->fetchrow ) {
612         if ( $record->field($tagfield) ) {
613             my $tag = $record->field($tagfield);
614             if ($tag) {
615                 $tag->add_subfields( $tagsubfield, $value );
616                 $record->delete_field($tag);
617                 $record->add_fields($tag);
618             }
619         }
620         else {
621             $record->add_fields( $tagfield, " ", " ", $tagsubfield => $value );
622         }
623     }
624     return $record;
625 }
626
627 =head2 MARChtml2marc
628
629 $MARCrecord = MARChtml2marc($dbh,$rtags,$rsubfields,$rvalues,%indicators);
630
631 =over 4
632
633 transforms the parameters (coming from HTML form) into a MARC::Record
634 parameters with r are references to arrays.
635
636 FIXME : should be improved for 3.0, to avoid having 4 differents arrays
637
638 =back
639
640 =cut
641
642 sub MARChtml2marc {
643         my ($dbh,$rtags,$rsubfields,$rvalues,%indicators) = @_;
644         my $prevtag = -1;
645         my $record = MARC::Record->new();
646 #       my %subfieldlist=();
647         my $prevvalue; # if tag <10
648         my $field; # if tag >=10
649         for (my $i=0; $i< @$rtags; $i++) {
650                 next unless @$rvalues[$i];
651                 # rebuild MARC::Record
652 #                       warn "0=>".@$rtags[$i].@$rsubfields[$i]." = ".@$rvalues[$i].": ";
653                 if (@$rtags[$i] ne $prevtag) {
654                         if ($prevtag < 10) {
655                                 if ($prevvalue) {
656                                         if ($prevtag ne '000') {
657                                                 $record->add_fields((sprintf "%03s",$prevtag),$prevvalue);
658                                         } else {
659                                                 $record->leader($prevvalue);
660                                         }
661                                 }
662                         } else {
663                                 if ($field) {
664                                         $record->add_fields($field);
665                                 }
666                         }
667                         $indicators{@$rtags[$i]}.='  ';
668                         if (@$rtags[$i] <10) {
669                                 $prevvalue= @$rvalues[$i];
670                                 undef $field;
671                         } else {
672                                 undef $prevvalue;
673                                 $field = MARC::Field->new( (sprintf "%03s",@$rtags[$i]), substr($indicators{@$rtags[$i]},0,1),substr($indicators{@$rtags[$i]},1,1), @$rsubfields[$i] => @$rvalues[$i]);
674 #                       warn "1=>".@$rtags[$i].@$rsubfields[$i]." = ".@$rvalues[$i].": ".$field->as_formatted;
675                         }
676                         $prevtag = @$rtags[$i];
677                 } else {
678                         if (@$rtags[$i] <10) {
679                                 $prevvalue=@$rvalues[$i];
680                         } else {
681                                 if (length(@$rvalues[$i])>0) {
682                                         $field->add_subfields(@$rsubfields[$i] => @$rvalues[$i]);
683 #                       warn "2=>".@$rtags[$i].@$rsubfields[$i]." = ".@$rvalues[$i].": ".$field->as_formatted;
684                                 }
685                         }
686                         $prevtag= @$rtags[$i];
687                 }
688         }
689         # the last has not been included inside the loop... do it now !
690         $record->add_fields($field) if $field;
691 #       warn "HTML2MARC=".$record->as_formatted;
692         return $record;
693 }
694
695
696 =head2 MARCmarc2koha
697
698 $hash = &MARCmarc2koha($dbh,$MARCRecord);
699
700 =over 4
701
702 builds a hash with old-db datas from a MARC::Record
703
704 =back
705
706 =cut
707
708 sub MARCmarc2koha {
709         my ($dbh,$record,$frameworkcode) = @_;
710         my $sth=$dbh->prepare("select tagfield,tagsubfield from marc_subfield_structure where frameworkcode=? and kohafield=?");
711         my $result;  
712         my $sth2=$dbh->prepare("SHOW COLUMNS from biblio");
713         $sth2->execute;
714         my $field;
715         while (($field)=$sth2->fetchrow) {
716 #               warn "biblio.".$field;
717                 $result=&MARCmarc2kohaOneField($sth,"biblio",$field,$record,$result,$frameworkcode);
718         }
719         $sth2=$dbh->prepare("SHOW COLUMNS from biblioitems");
720         $sth2->execute;
721         while (($field)=$sth2->fetchrow) {
722                 if ($field eq 'notes') { $field = 'bnotes'; }
723 #               warn "biblioitems".$field;
724                 $result=&MARCmarc2kohaOneField($sth,"biblioitems",$field,$record,$result,$frameworkcode);
725         }
726         $sth2=$dbh->prepare("SHOW COLUMNS from items");
727         $sth2->execute;
728         while (($field)=$sth2->fetchrow) {
729 #               warn "items".$field;
730                 $result=&MARCmarc2kohaOneField($sth,"items",$field,$record,$result,$frameworkcode);
731         }
732         # additional authors : specific
733         $result = &MARCmarc2kohaOneField($sth,"bibliosubtitle","subtitle",$record,$result,$frameworkcode);
734         $result = &MARCmarc2kohaOneField($sth,"additionalauthors","additionalauthors",$record,$result,$frameworkcode);
735 # modify copyrightdate to keep only the 1st year found
736         my $temp = $result->{'copyrightdate'};
737         if ($temp){
738                 $temp =~ m/c(\d\d\d\d)/; # search cYYYY first
739                 if ($1>0) {
740                         $result->{'copyrightdate'} = $1;
741                 } else { # if no cYYYY, get the 1st date.
742                         $temp =~ m/(\d\d\d\d)/;
743                         $result->{'copyrightdate'} = $1;
744                 }
745         }
746 # modify publicationyear to keep only the 1st year found
747         $temp = $result->{'publicationyear'};
748         $temp =~ m/c(\d\d\d\d)/; # search cYYYY first
749         if ($1>0) {
750                 $result->{'publicationyear'} = $1;
751         } else { # if no cYYYY, get the 1st date.
752                 $temp =~ m/(\d\d\d\d)/;
753                 $result->{'publicationyear'} = $1;
754         }
755         return $result;
756 }
757
758 sub MARCmarc2kohaOneField {
759
760 # FIXME ? if a field has a repeatable subfield that is used in old-db, only the 1st will be retrieved...
761     my ( $sth, $kohatable, $kohafield, $record, $result,$frameworkcode ) = @_;
762     #    warn "kohatable / $kohafield / $result / ";
763     my $res = "";
764     my $tagfield;
765     my $subfield;
766     ( $tagfield, $subfield ) = MARCfind_marc_from_kohafield("",$kohatable.".".$kohafield,$frameworkcode);
767     foreach my $field ( $record->field($tagfield) ) {
768                 if ($field->tag()<10) {
769                         if ($result->{$kohafield}) {
770                                 # Reverse array filled with elements from repeated subfields 
771                                 # from first to last to avoid last to first concatenation of 
772                                 # elements in Koha DB.  -- thd.
773                                 $result->{$kohafield} .= " | ".reverse($field->data());
774                         } else {
775                                 $result->{$kohafield} = $field->data();
776                         }
777                 } else {
778                         if ( $field->subfields ) {
779                                 my @subfields = $field->subfields();
780                                 foreach my $subfieldcount ( 0 .. $#subfields ) {
781                                         if ($subfields[$subfieldcount][0] eq $subfield) {
782                                                 if ( $result->{$kohafield} ) {
783                                                         $result->{$kohafield} .= " | " . $subfields[$subfieldcount][1];
784                                                 }
785                                                 else {
786                                                         $result->{$kohafield} = $subfields[$subfieldcount][1];
787                                                 }
788                                         }
789                                 }
790                         }
791                 }
792     }
793 #       warn "OneField for $kohatable.$kohafield and $frameworkcode=> $tagfield, $subfield";
794     return $result;
795 }
796
797 =head2 NEWnewbibilio
798
799 ($biblionumber,$biblioitemnumber) = NEWnewbibilio($dbh,$MARCRecord,$frameworkcode);
800
801 =over 4
802
803 creates a biblio from a MARC::Record.
804
805 =back
806
807 =cut
808
809 sub NEWnewbiblio {
810     my ( $dbh,$Zconn,$record,$frameworkcode ) = @_;
811     my $biblionumber;
812     my $biblioitemnumber;
813     my $olddata = MARCmarc2koha( $dbh, $record,$frameworkcode );
814         $olddata->{frameworkcode} = $frameworkcode;
815     $biblionumber = REALnewbiblio( $dbh, $olddata );
816         $olddata->{biblionumber} = $biblionumber;
817         # add biblionumber into the MARC record (it's the ID for zebra)
818         my ( $tagfield, $tagsubfield ) =
819                                         MARCfind_marc_from_kohafield( $dbh, "biblio.biblionumber",$frameworkcode );
820         # create the field
821         my $newfield;
822         if ($tagfield<10) {
823                 $newfield = MARC::Field->new(
824                         $tagfield, $biblionumber,
825                 );
826         } else {
827                 $newfield = MARC::Field->new(
828                         $tagfield, '', '', "$tagsubfield" => $biblionumber,
829                 );
830         }
831         # drop old field (just in case it already exist and create new one...
832         my $old_field = $record->field($tagfield);
833         $record->delete_field($old_field);
834         $record->add_fields($newfield);
835
836         #create the marc entry, that stores the rax marc record in Koha 3.0
837         $olddata->{marc} = $record->as_usmarc();
838         $olddata->{marcxml} = $record->as_xml();
839         # and create biblioitem, that's all folks !
840     $biblioitemnumber = REALnewbiblioitem( $dbh, $Zconn, $olddata );
841
842     # search subtiles, addiauthors and subjects
843     ( $tagfield, $tagsubfield ) =
844       MARCfind_marc_from_kohafield( $dbh, "additionalauthors.author",$frameworkcode );
845     my @addiauthfields = $record->field($tagfield);
846     foreach my $addiauthfield (@addiauthfields) {
847         my @addiauthsubfields = $addiauthfield->subfield($tagsubfield);
848         foreach my $subfieldcount ( 0 .. $#addiauthsubfields ) {
849             REALmodaddauthor( $dbh, $biblionumber,
850                 $addiauthsubfields[$subfieldcount] );
851         }
852     }
853     ( $tagfield, $tagsubfield ) =
854       MARCfind_marc_from_kohafield( $dbh, "bibliosubtitle.subtitle",$frameworkcode );
855     my @subtitlefields = $record->field($tagfield);
856     foreach my $subtitlefield (@subtitlefields) {
857         my @subtitlesubfields = $subtitlefield->subfield($tagsubfield);
858         foreach my $subfieldcount ( 0 .. $#subtitlesubfields ) {
859             REALnewsubtitle( $dbh, $biblionumber,
860                 $subtitlesubfields[$subfieldcount] );
861         }
862     }
863     ( $tagfield, $tagsubfield ) =
864       MARCfind_marc_from_kohafield( $dbh, "bibliosubject.subject",$frameworkcode );
865     my @subj = $record->field($tagfield);
866     my @subjects;
867     foreach my $subject (@subj) {
868         my @subjsubfield = $subject->subfield($tagsubfield);
869         foreach my $subfieldcount ( 0 .. $#subjsubfield ) {
870             push @subjects, $subjsubfield[$subfieldcount];
871         }
872     }
873     REALmodsubject( $dbh, $biblionumber, 1, @subjects );
874     return ( $biblionumber, $biblioitemnumber );
875 }
876
877 =head2 NEWmodbilbioframework
878
879 NEWmodbilbioframework($dbh,$biblionumber,$frameworkcode);
880
881 =over 4
882
883 modify the framework of a biblio
884
885 =back
886
887 =cut
888
889 sub NEWmodbiblioframework {
890         my ($dbh,$biblionumber,$frameworkcode) =@_;
891         my $sth = $dbh->prepare("Update biblio SET frameworkcode=? WHERE biblionumber=?");
892         $sth->execute($frameworkcode,$biblionumber);
893         return 1;
894 }
895
896 =head2 NEWmodbiblio
897
898 NEWmodbiblio($dbh,$Zconn,$MARCrecord,$biblionumber,$frameworkcode);
899
900 =over 4
901
902 modify a biblio (MARC=ON)
903
904 =back
905
906 =cut
907
908 sub NEWmodbiblio {
909         my ($dbh,$Zconn,$record,$biblionumber,$frameworkcode) =@_;
910         $frameworkcode="" unless $frameworkcode;
911 #       &MARCmodbiblio($dbh,$bibid,$record,$frameworkcode,0);
912         my $oldbiblio = MARCmarc2koha($dbh,$record,$frameworkcode);
913         
914         $oldbiblio->{frameworkcode} = $frameworkcode;
915         #create the marc entry, that stores the rax marc record in Koha 3.0
916         $oldbiblio->{biblionumber} = $biblionumber unless $oldbiblio->{biblionumber};
917         $oldbiblio->{marc} = $record->as_usmarc();
918         $oldbiblio->{marcxml} = $record->as_xml();
919         warn "dans NEWmodbiblio $biblionumber = ".$oldbiblio->{biblionumber}." = ".$oldbiblio->{marcxml};
920         REALmodbiblio($dbh,$oldbiblio);
921         REALmodbiblioitem($dbh,$Zconn,$oldbiblio);
922         # now, modify addi authors, subject, addititles.
923         my ($tagfield,$tagsubfield) = MARCfind_marc_from_kohafield($dbh,"additionalauthors.author",$frameworkcode);
924         my @addiauthfields = $record->field($tagfield);
925         foreach my $addiauthfield (@addiauthfields) {
926                 my @addiauthsubfields = $addiauthfield->subfield($tagsubfield);
927                 $dbh->do("delete from additionalauthors where biblionumber=$biblionumber");
928                 foreach my $subfieldcount (0..$#addiauthsubfields) {
929                         REALmodaddauthor($dbh,$biblionumber,$addiauthsubfields[$subfieldcount]);
930                 }
931         }
932         ($tagfield,$tagsubfield) = MARCfind_marc_from_kohafield($dbh,"bibliosubtitle.subtitle",$frameworkcode);
933         my @subtitlefields = $record->field($tagfield);
934         foreach my $subtitlefield (@subtitlefields) {
935                 my @subtitlesubfields = $subtitlefield->subfield($tagsubfield);
936                 # delete & create subtitle again because REALmodsubtitle can't handle new subtitles
937                 # between 2 modifs
938                 $dbh->do("delete from bibliosubtitle where biblionumber=$biblionumber");
939                 foreach my $subfieldcount (0..$#subtitlesubfields) {
940                         foreach my $subtit(split /\||#/,$subtitlesubfields[$subfieldcount]) {
941                                 REALnewsubtitle($dbh,$biblionumber,$subtit);
942                         }
943                 }
944         }
945         ($tagfield,$tagsubfield) = MARCfind_marc_from_kohafield($dbh,"bibliosubject.subject",$frameworkcode);
946         my @subj = $record->field($tagfield);
947         my @subjects;
948         foreach my $subject (@subj) {
949                 my @subjsubfield = $subject->subfield($tagsubfield);
950                 foreach my $subfieldcount (0..$#subjsubfield) {
951                         push @subjects,$subjsubfield[$subfieldcount];
952                 }
953         }
954         REALmodsubject($dbh,$biblionumber,1,@subjects);
955         return 1;
956 }
957
958 =head2 NEWmodbilbioframework
959
960 NEWmodbilbioframework($dbh,$biblionumber,$frameworkcode);
961
962 =over 4
963
964 delete a biblio
965
966 =back
967
968 =cut
969
970 sub NEWdelbiblio {
971     my ( $dbh, $bibid ) = @_;
972     my $biblio = &MARCfind_oldbiblionumber_from_MARCbibid( $dbh, $bibid );
973     &REALdelbiblio( $dbh, $biblio );
974     my $sth =
975       $dbh->prepare(
976         "select biblioitemnumber from biblioitems where biblionumber=?");
977     $sth->execute($biblio);
978     while ( my ($biblioitemnumber) = $sth->fetchrow ) {
979         REALdelbiblioitem( $dbh, $biblioitemnumber );
980     }
981     &MARCdelbiblio( $dbh, $bibid, 0 );
982 }
983
984 =head2 NEWnewitem
985
986 $itemnumber = NEWnewitem($dbh, $Zconn, $record, $biblionumber, $biblioitemnumber);
987
988 =over 4
989
990 creates an item from a MARC::Record
991
992 =back
993
994 =cut
995
996 sub NEWnewitem {
997     my ( $dbh,$Zconn,$record,$biblionumber,$biblioitemnumber ) = @_;
998
999     # add item in old-DB
1000         my $frameworkcode=MARCfind_frameworkcode($dbh,$biblionumber);
1001     my $item = &MARCmarc2koha( $dbh,$record,$frameworkcode );
1002     # needs old biblionumber and biblioitemnumber
1003     $item->{'biblionumber'} = $biblionumber;
1004     $item->{'biblioitemnumber'}=$biblioitemnumber;
1005     $item->{marc} = $record->as_usmarc();
1006     warn $item->{marc};
1007     my ( $itemnumber, $error ) = &REALnewitems( $dbh, $Zconn, $item, $item->{barcode} );
1008         return $itemnumber;
1009 }
1010
1011
1012 =head2 NEWmoditem
1013
1014 $itemnumber = NEWmoditem($dbh, $Zconn, $record, $biblionumber, $biblioitemnumber,$itemnumber);
1015
1016 =over 4
1017
1018 Modify an item
1019
1020 =back
1021
1022 =cut
1023
1024 sub NEWmoditem {
1025     my ( $dbh, $Zconn, $record, $biblionumber, $biblioitemnumber, $itemnumber) = @_;
1026     
1027         my $frameworkcode=MARCfind_frameworkcode($dbh,$biblionumber);
1028     my $olditem = MARCmarc2koha( $dbh, $record,$frameworkcode );
1029         # add MARC record
1030         $olditem->{marc} = $record->as_usmarc();
1031         $olditem->{biblionumber} = $biblionumber;
1032         $olditem->{biblioitemnumber} = $biblioitemnumber;
1033         # and modify item
1034     REALmoditem( $dbh, $Zconn, $olditem );
1035 }
1036
1037
1038 =head2 NEWdelitem
1039
1040 $itemnumber = NEWdelitem($dbh, $biblionumber, $biblioitemnumber, $itemnumber);
1041
1042 =over 4
1043
1044 delete an item
1045
1046 =back
1047
1048 =cut
1049
1050 sub NEWdelitem {
1051     my ( $dbh, $bibid, $itemnumber ) = @_;
1052     my $biblio = &MARCfind_oldbiblionumber_from_MARCbibid( $dbh, $bibid );
1053     &REALdelitem( $dbh, $itemnumber );
1054     &MARCdelitem( $dbh, $bibid, $itemnumber );
1055 }
1056
1057
1058 =head2 REALnewbiblio
1059
1060 $biblionumber = REALnewbiblio($dbh,$biblio);
1061
1062 =over 4
1063
1064 adds a record in biblio table. Datas are in the hash $biblio.
1065
1066 =back
1067
1068 =cut
1069
1070 sub REALnewbiblio {
1071     my ( $dbh, $biblio ) = @_;
1072
1073         $dbh->do('lock tables biblio WRITE');
1074     my $sth = $dbh->prepare("Select max(biblionumber) from biblio");
1075     $sth->execute;
1076     my $data   = $sth->fetchrow_arrayref;
1077     my $bibnum = $$data[0] + 1;
1078     my $series = 0;
1079
1080     if ( $biblio->{'seriestitle'} ) { $series = 1 }
1081     $sth->finish;
1082     $sth =
1083       $dbh->prepare("insert into biblio set     biblionumber=?, title=?,                author=?,       copyrightdate=?,
1084                                                                                         serial=?,               seriestitle=?,  notes=?,        abstract=?,
1085                                                                                         unititle=?"
1086     );
1087     $sth->execute(
1088         $bibnum,             $biblio->{'title'},
1089         $biblio->{'author'}, $biblio->{'copyrightdate'},
1090         $biblio->{'serial'},             $biblio->{'seriestitle'},
1091         $biblio->{'notes'},  $biblio->{'abstract'},
1092                 $biblio->{'unititle'}
1093     );
1094
1095     $sth->finish;
1096         $dbh->do('unlock tables');
1097     return ($bibnum);
1098 }
1099
1100 =head2 REALmodbiblio
1101
1102 $biblionumber = REALmodbiblio($dbh,$biblio);
1103
1104 =over 4
1105
1106 modify a record in biblio table. Datas are in the hash $biblio.
1107
1108 =back
1109
1110 =cut
1111
1112 sub REALmodbiblio {
1113     my ( $dbh, $biblio ) = @_;
1114     my $sth = $dbh->prepare("Update biblio set  title=?,                author=?,       abstract=?,     copyrightdate=?,
1115                                                                                                 seriestitle=?,  serial=?,       unititle=?,     notes=?,        frameworkcode=? 
1116                                                                                         where biblionumber = ?"
1117     );
1118     $sth->execute(
1119                 $biblio->{'title'},       $biblio->{'author'},
1120                 $biblio->{'abstract'},    $biblio->{'copyrightdate'},
1121                 $biblio->{'seriestitle'}, $biblio->{'serial'},
1122                 $biblio->{'unititle'},    $biblio->{'notes'},
1123                 $biblio->{frameworkcode},
1124                 $biblio->{'biblionumber'}
1125     );
1126         $sth->finish;
1127         return ( $biblio->{'biblionumber'} );
1128 }    # sub modbiblio
1129
1130 =head2 REALmodsubtitle
1131
1132 REALmodsubtitle($dbh,$bibnum,$subtitle);
1133
1134 =over 4
1135
1136 modify subtitles in bibliosubtitle table.
1137
1138 =back
1139
1140 =cut
1141
1142 sub REALmodsubtitle {
1143     my ( $dbh, $bibnum, $subtitle ) = @_;
1144     my $sth =
1145       $dbh->prepare(
1146         "update bibliosubtitle set subtitle = ? where biblionumber = ?");
1147     $sth->execute( $subtitle, $bibnum );
1148     $sth->finish;
1149 }    # sub modsubtitle
1150
1151 =head2 REALmodaddauthor
1152
1153 REALmodaddauthor($dbh,$bibnum,$author);
1154
1155 =over 4
1156
1157 adds or modify additional authors
1158 NOTE :  Strange sub : seems to delete MANY and add only ONE author... maybe buggy ?
1159
1160 =back
1161
1162 =cut
1163
1164 sub REALmodaddauthor {
1165     my ( $dbh, $bibnum, @authors ) = @_;
1166
1167     #    my $dbh   = C4Connect;
1168     my $sth =
1169       $dbh->prepare("Delete from additionalauthors where biblionumber = ?");
1170
1171     $sth->execute($bibnum);
1172     $sth->finish;
1173     foreach my $author (@authors) {
1174         if ( $author ne '' ) {
1175             $sth =
1176               $dbh->prepare(
1177                 "Insert into additionalauthors set author = ?, biblionumber = ?"
1178             );
1179
1180             $sth->execute( $author, $bibnum );
1181
1182             $sth->finish;
1183         }    # if
1184     }
1185 }    # sub modaddauthor
1186
1187 =head2 REALmodsubject
1188
1189 $errors = REALmodsubject($dbh,$bibnum, $force, @subject);
1190
1191 =over 4
1192
1193 modify/adds subjects
1194
1195 =back
1196
1197 =cut
1198 sub REALmodsubject {
1199     my ( $dbh, $bibnum, $force, @subject ) = @_;
1200
1201     #  my $dbh   = C4Connect;
1202     my $count = @subject;
1203     my $error="";
1204     for ( my $i = 0 ; $i < $count ; $i++ ) {
1205         $subject[$i] =~ s/^ //g;
1206         $subject[$i] =~ s/ $//g;
1207         my $sth =
1208           $dbh->prepare(
1209 "select * from catalogueentry where entrytype = 's' and catalogueentry = ?"
1210         );
1211         $sth->execute( $subject[$i] );
1212
1213         if ( my $data = $sth->fetchrow_hashref ) {
1214         }
1215         else {
1216             if ( $force eq $subject[$i] || $force == 1 ) {
1217
1218                 # subject not in aut, chosen to force anway
1219                 # so insert into cataloguentry so its in auth file
1220                 my $sth2 =
1221                   $dbh->prepare(
1222 "Insert into catalogueentry (entrytype,catalogueentry) values ('s',?)"
1223                 );
1224
1225                 $sth2->execute( $subject[$i] ) if ( $subject[$i] );
1226                 $sth2->finish;
1227             }
1228             else {
1229                 $error =
1230                   "$subject[$i]\n does not exist in the subject authority file";
1231                 my $sth2 =
1232                   $dbh->prepare(
1233 "Select * from catalogueentry where entrytype = 's' and (catalogueentry like ? or catalogueentry like ? or catalogueentry like ?)"
1234                 );
1235                 $sth2->execute( "$subject[$i] %", "% $subject[$i] %",
1236                     "% $subject[$i]" );
1237                 while ( my $data = $sth2->fetchrow_hashref ) {
1238                     $error .= "<br>$data->{'catalogueentry'}";
1239                 }    # while
1240                 $sth2->finish;
1241             }    # else
1242         }    # else
1243         $sth->finish;
1244     }    # else
1245     if ($error eq '') {
1246         my $sth =
1247           $dbh->prepare("Delete from bibliosubject where biblionumber = ?");
1248         $sth->execute($bibnum);
1249         $sth->finish;
1250         $sth =
1251           $dbh->prepare(
1252             "Insert into bibliosubject (subject,biblionumber) values (?,?)");
1253         my $query;
1254         foreach $query (@subject) {
1255             $sth->execute( $query, $bibnum ) if ( $query && $bibnum );
1256         }    # foreach
1257         $sth->finish;
1258     }    # if
1259
1260     #  $dbh->disconnect;
1261     return ($error);
1262 }    # sub modsubject
1263
1264 =head2 REALmodbiblioitem
1265
1266 REALmodbiblioitem($dbh, $biblioitem);
1267
1268 =over 4
1269
1270 modify a biblioitem
1271
1272 =back
1273
1274 =cut
1275 sub REALmodbiblioitem {
1276     my ( $dbh, $Zconn, $biblioitem ) = @_;
1277     my $query;
1278
1279     my $sth = $dbh->prepare("update biblioitems set number=?,volume=?,                  volumedate=?,           lccn=?,
1280                                                                                 itemtype=?,                     url=?,                          isbn=?,                         issn=?,
1281                                                                                 publishercode=?,        publicationyear=?,      classification=?,       dewey=?,
1282                                                                                 subclass=?,                     illus=?,                        pages=?,                        volumeddesc=?,
1283                                                                                 notes=?,                        size=?,                         place=?,                        marc=?,
1284                                                                                 marcxml=?
1285                                                         where biblioitemnumber=?");
1286         $sth->execute(  $biblioitem->{number},                  $biblioitem->{volume},  $biblioitem->{volumedate},      $biblioitem->{lccn},
1287                                         $biblioitem->{itemtype},                $biblioitem->{url},             $biblioitem->{isbn},    $biblioitem->{issn},
1288                                 $biblioitem->{publishercode},   $biblioitem->{publicationyear}, $biblioitem->{classification},  $biblioitem->{dewey},
1289                                 $biblioitem->{subclass},                $biblioitem->{illus},           $biblioitem->{pages},   $biblioitem->{volumeddesc},
1290                                 $biblioitem->{bnotes},                  $biblioitem->{size},            $biblioitem->{place},   $biblioitem->{marc},
1291                                         $biblioitem->{marcxml},                 $biblioitem->{biblioitemnumber});
1292
1293         my $record = MARC::File::USMARC::decode($biblioitem->{marc});
1294
1295         z3950_extended_services($Zconn,'update',set_service_options('update'),$record);
1296
1297
1298 #       warn "MOD : $biblioitem->{biblioitemnumber} = ".$biblioitem->{marc};
1299 }    # sub modbibitem
1300
1301 =head2 REALnewbiblioitem
1302
1303 REALnewbiblioitem($dbh,$Zconn,$biblioitem);
1304
1305 =over 4
1306
1307 adds a biblioitem ($biblioitem is a hash with the values)
1308
1309 =back
1310
1311 =cut
1312
1313 sub REALnewbiblioitem {
1314         my ( $dbh, $Zconn, $biblioitem ) = @_;
1315
1316         $dbh->do("lock tables biblioitems WRITE, biblio WRITE, marc_subfield_structure READ");
1317         my $sth = $dbh->prepare("Select max(biblioitemnumber) from biblioitems");
1318         my $data;
1319         my $biblioitemnumber;
1320
1321         $sth->execute;
1322         $data       = $sth->fetchrow_arrayref;
1323         $biblioitemnumber = $$data[0] + 1;
1324         
1325         # Insert biblioitemnumber in MARC record, we need it to manage items later...
1326         my $frameworkcode=MARCfind_frameworkcode($dbh,$biblioitem->{biblionumber});
1327         my ($biblioitemnumberfield,$biblioitemnumbersubfield) = MARCfind_marc_from_kohafield($dbh,'biblioitems.biblioitemnumber',$frameworkcode);
1328         my $record = MARC::File::USMARC::decode($biblioitem->{marc});
1329         my $field=$record->field($biblioitemnumberfield);
1330         $field->update($biblioitemnumbersubfield => "$biblioitemnumber");
1331         $biblioitem->{marc} = $record->as_usmarc();
1332         $biblioitem->{marcxml} = $record->as_xml();
1333
1334         $sth = $dbh->prepare( "insert into biblioitems set
1335                                                                         biblioitemnumber = ?,           biblionumber     = ?,
1336                                                                         volume           = ?,                   number           = ?,
1337                                                                         classification  = ?,                    itemtype         = ?,
1338                                                                         url              = ?,                           isbn             = ?,
1339                                                                         issn             = ?,                           dewey            = ?,
1340                                                                         subclass         = ?,                           publicationyear  = ?,
1341                                                                         publishercode    = ?,           volumedate       = ?,
1342                                                                         volumeddesc      = ?,           illus            = ?,
1343                                                                         pages            = ?,                           notes            = ?,
1344                                                                         size             = ?,                           lccn             = ?,
1345                                                                         marc             = ?,                           place            = ?,
1346                                                                         marcxml          = ?"
1347         );
1348         $sth->execute(
1349                 $biblioitemnumber,               $biblioitem->{'biblionumber'},
1350                 $biblioitem->{'volume'},         $biblioitem->{'number'},
1351                 $biblioitem->{'classification'}, $biblioitem->{'itemtype'},
1352                 $biblioitem->{'url'},            $biblioitem->{'isbn'},
1353                 $biblioitem->{'issn'},           $biblioitem->{'dewey'},
1354                 $biblioitem->{'subclass'},       $biblioitem->{'publicationyear'},
1355                 $biblioitem->{'publishercode'},  $biblioitem->{'volumedate'},
1356                 $biblioitem->{'volumeddesc'},    $biblioitem->{'illus'},
1357                 $biblioitem->{'pages'},          $biblioitem->{'bnotes'},
1358                 $biblioitem->{'size'},           $biblioitem->{'lccn'},
1359                 $biblioitem->{'marc'},           $biblioitem->{'place'},
1360                 $biblioitem->{marcxml},
1361         );
1362         $dbh->do("unlock tables");
1363         z3950_extended_services($Zconn,'update',set_service_options('update'),$record);
1364         return ($biblioitemnumber);
1365 }
1366
1367 =head2 REALnewsubtitle
1368
1369 REALnewsubtitle($dbh,$bibnum,$subtitle);
1370
1371 =over 4
1372
1373 create a new subtitle
1374
1375 =back
1376
1377 =cut
1378 sub REALnewsubtitle {
1379     my ( $dbh, $bibnum, $subtitle ) = @_;
1380     my $sth =
1381       $dbh->prepare(
1382         "insert into bibliosubtitle set biblionumber = ?, subtitle = ?");
1383     $sth->execute( $bibnum, $subtitle ) if $subtitle;
1384     $sth->finish;
1385 }
1386
1387 =head2 REALnewitems
1388
1389 ($itemnumber,$errors)= REALnewitems($dbh,$Zconn,$item,$barcode);
1390
1391 =over 4
1392
1393 create a item. $item is a hash and $barcode the barcode.
1394
1395 =back
1396
1397 =cut
1398
1399 sub REALnewitems {
1400     my ( $dbh, $Zconn, $item, $barcode ) = @_;
1401
1402 #       warn "OLDNEWITEMS";
1403         
1404         $dbh->do('lock tables items WRITE, biblio WRITE,biblioitems WRITE,marc_subfield_structure WRITE');
1405     my $sth = $dbh->prepare("Select max(itemnumber) from items");
1406     my $data;
1407     my $itemnumber;
1408     my $error = "";
1409     $sth->execute;
1410     $data       = $sth->fetchrow_hashref;
1411     $itemnumber = $data->{'max(itemnumber)'} + 1;
1412
1413 # FIXME the "notforloan" field seems to be named "loan" in some places. workaround bugfix.
1414     if ( $item->{'loan'} ) {
1415         $item->{'notforloan'} = $item->{'loan'};
1416     }
1417         $item->{'biblioitemnumber'} = 1;
1418     # if dateaccessioned is provided, use it. Otherwise, set to NOW()
1419     if ( $item->{'dateaccessioned'} ) {
1420         $sth = $dbh->prepare( "Insert into items set
1421                                                         itemnumber           = ?,                       biblionumber         = ?,
1422                                                         multivolumepart      = ?,
1423                                                         biblioitemnumber     = ?,                       barcode              = ?,
1424                                                         booksellerid         = ?,                       dateaccessioned      = ?,
1425                                                         homebranch           = ?,                       holdingbranch        = ?,
1426                                                         price                = ?,                       replacementprice     = ?,
1427                                                         replacementpricedate = NOW(),           datelastseen            = NOW(),
1428                                                         multivolume                     = ?,                    stack                           = ?,
1429                                                         itemlost                        = ?,                    wthdrawn                        = ?,
1430                                                         paidfor                         = ?,                    itemnotes            = ?,
1431                                                         itemcallnumber  =?,                                                     notforloan = ?,
1432                                                         location = ?
1433                                                         "
1434         );
1435         $sth->execute(
1436                         $itemnumber,                            $item->{'biblionumber'},
1437                         $item->{'multivolumepart'},
1438                         $item->{'biblioitemnumber'},$item->{barcode},
1439                         $item->{'booksellerid'},        $item->{'dateaccessioned'},
1440                         $item->{'homebranch'},          $item->{'holdingbranch'},
1441                         $item->{'price'},                       $item->{'replacementprice'},
1442                         $item->{multivolume},           $item->{stack},
1443                         $item->{itemlost},                      $item->{wthdrawn},
1444                         $item->{paidfor},                       $item->{'itemnotes'},
1445                         $item->{'itemcallnumber'},      $item->{'notforloan'},
1446                         $item->{'location'}
1447         );
1448                 if ( defined $sth->errstr ) {
1449                         $error .= $sth->errstr;
1450                 }
1451     }
1452     else {
1453         $sth = $dbh->prepare( "Insert into items set
1454                                                         itemnumber           = ?,                       biblionumber         = ?,
1455                                                         multivolumepart      = ?,
1456                                                         biblioitemnumber     = ?,                       barcode              = ?,
1457                                                         booksellerid         = ?,                       dateaccessioned      = NOW(),
1458                                                         homebranch           = ?,                       holdingbranch        = ?,
1459                                                         price                = ?,                       replacementprice     = ?,
1460                                                         replacementpricedate = NOW(),           datelastseen            = NOW(),
1461                                                         multivolume                     = ?,                    stack                           = ?,
1462                                                         itemlost                        = ?,                    wthdrawn                        = ?,
1463                                                         paidfor                         = ?,                    itemnotes            = ?,
1464                                                         itemcallnumber  =?,                                                     notforloan = ?,
1465                                                         location = ?
1466                                                         "
1467         );
1468         $sth->execute(
1469                         $itemnumber,                            $item->{'biblionumber'},
1470                         $item->{'multivolumepart'},
1471                         $item->{'biblioitemnumber'},$item->{barcode},
1472                         $item->{'booksellerid'},
1473                         $item->{'homebranch'},          $item->{'holdingbranch'},
1474                         $item->{'price'},                       $item->{'replacementprice'},
1475                         $item->{multivolume},           $item->{stack},
1476                         $item->{itemlost},                      $item->{wthdrawn},
1477                         $item->{paidfor},                       $item->{'itemnotes'},
1478                         $item->{'itemcallnumber'},      $item->{'notforloan'},
1479                         $item->{'location'}
1480         );
1481                 if ( defined $sth->errstr ) {
1482                         $error .= $sth->errstr;
1483                 }
1484     }
1485         # item stored, now, deal with the marc part...
1486         $sth = $dbh->prepare("select biblioitems.marc,biblio.frameworkcode from biblioitems,biblio 
1487                                                         where   biblio.biblionumber=biblioitems.biblionumber and 
1488                                                                         biblio.biblionumber=?");
1489         $sth->execute($item->{biblionumber});
1490     if ( defined $sth->errstr ) {
1491         $error .= $sth->errstr;
1492     }
1493         my ($rawmarc,$frameworkcode) = $sth->fetchrow;
1494         warn "ERROR IN REALnewitem, MARC record not found FOR $item->{biblionumber} => $rawmarc <=" unless $rawmarc;
1495         my $record = MARC::File::USMARC::decode($rawmarc);
1496         # ok, we have the marc record, add item number to the item field (in {marc}, and add the field to the record)
1497         my ($itemnumberfield,$itemnumbersubfield) = MARCfind_marc_from_kohafield($dbh,'items.itemnumber',$frameworkcode);
1498         my $itemrecord = MARC::Record->new_from_usmarc($item->{marc});
1499         warn $itemrecord;
1500         warn $itemnumberfield;
1501         warn $itemrecord->field($itemnumberfield);
1502         my $itemfield = $itemrecord->field($itemnumberfield);
1503         $itemfield->add_subfields($itemnumbersubfield => "$itemnumber");
1504         $record->insert_grouped_field($itemfield);
1505         # save the record into biblioitem
1506         $sth=$dbh->prepare("update biblioitems set marc=?,marcxml=? where biblionumber=?");
1507         $sth->execute($record->as_usmarc(),$record->as_xml(),$item->{biblionumber});
1508     if ( defined $sth->errstr ) {
1509         $error .= $sth->errstr;
1510     }
1511         z3950_extended_services($Zconn,'update',set_service_options('update'),$record);
1512         $dbh->do('unlock tables');
1513     return ( $itemnumber, $error );
1514 }
1515
1516 =head2 REALmoditem($dbh,$Zconn,$item);
1517
1518 =over 4
1519
1520 modify item
1521
1522 =back
1523
1524 =cut
1525
1526 sub REALmoditem {
1527     my ( $dbh, $Zconn, $item ) = @_;
1528     $item->{'bibitemnum'} = 1;
1529         my $error;
1530         $dbh->do('lock tables items WRITE, biblio WRITE,biblioitems WRITE');
1531     $item->{'itemnum'} = $item->{'itemnumber'} unless $item->{'itemnum'};
1532     my $query = "update items set  barcode=?,itemnotes=?,itemcallnumber=?,notforloan=?,location=?,multivolumepart=?,multivolume=?,stack=?,wthdrawn=?";
1533     my @bind = (
1534         $item->{'barcode'},                     $item->{'itemnotes'},
1535         $item->{'itemcallnumber'},      $item->{'notforloan'},
1536         $item->{'location'},            $item->{multivolumepart},
1537                 $item->{multivolume},           $item->{stack},
1538                 $item->{wthdrawn},
1539     );
1540     if ( $item->{'lost'} ne '' ) {
1541         $query = "update items set biblioitemnumber=?,barcode=?,itemnotes=?,homebranch=?,
1542                                                         itemlost=?,wthdrawn=?,itemcallnumber=?,notforloan=?,
1543                                                         location=?,multivolumepart=?,multivolume=?,stack=?,wthdrawn=?";
1544         @bind = (
1545             $item->{'bibitemnum'},     $item->{'barcode'},
1546             $item->{'itemnotes'},          $item->{'homebranch'},
1547             $item->{'lost'},           $item->{'wthdrawn'},
1548             $item->{'itemcallnumber'}, $item->{'notforloan'},
1549             $item->{'location'},                $item->{multivolumepart},
1550                         $item->{multivolume},           $item->{stack},
1551                         $item->{wthdrawn},
1552         );
1553                 if ($item->{homebranch}) {
1554                         $query.=",homebranch=?";
1555                         push @bind, $item->{homebranch};
1556                 }
1557                 if ($item->{holdingbranch}) {
1558                         $query.=",holdingbranch=?";
1559                         push @bind, $item->{holdingbranch};
1560                 }
1561     }
1562         $query.=" where itemnumber=?";
1563         push @bind,$item->{'itemnum'};
1564    if ( $item->{'replacement'} ne '' ) {
1565         $query =~ s/ where/,replacementprice='$item->{'replacement'}' where/;
1566     }
1567     my $sth = $dbh->prepare($query);
1568     $sth->execute(@bind);
1569         
1570         # item stored, now, deal with the marc part...
1571         $sth = $dbh->prepare("select biblioitems.marc,biblio.frameworkcode from biblioitems,biblio 
1572                                                         where   biblio.biblionumber=biblioitems.biblionumber and 
1573                                                                         biblio.biblionumber=? and 
1574                                                                         biblioitems.biblioitemnumber=?");
1575         $sth->execute($item->{biblionumber},$item->{biblioitemnumber});
1576     if ( defined $sth->errstr ) {
1577         $error .= $sth->errstr;
1578     }
1579         my ($rawmarc,$frameworkcode) = $sth->fetchrow;
1580         warn "ERROR IN REALmoditem, MARC record not found" unless $rawmarc;
1581         my $record = MARC::File::USMARC::decode($rawmarc);
1582         # ok, we have the marc record, find the previous item record for this itemnumber and delete it
1583         my ($itemnumberfield,$itemnumbersubfield) = MARCfind_marc_from_kohafield($dbh,'items.itemnumber',$frameworkcode);
1584         # prepare the new item record
1585         my $itemrecord = MARC::File::USMARC::decode($item->{marc});
1586         my $itemfield = $itemrecord->field($itemnumberfield);
1587         $itemfield->add_subfields($itemnumbersubfield => '$itemnumber');
1588         # parse all fields fields from the complete record
1589         foreach ($record->field($itemnumberfield)) {
1590                 # when the previous field is found, replace by the new one
1591                 if ($_->subfield($itemnumbersubfield) == $item->{itemnum}) {
1592                         $_->replace_with($itemfield);
1593                 }
1594         }
1595 #       $record->insert_grouped_field($itemfield);
1596         # save the record into biblioitem
1597         $sth=$dbh->prepare("update biblioitems set marc=?,marcxml=? where biblionumber=? and biblioitemnumber=?");
1598         $sth->execute($record->as_usmarc(),$record->as_xml(),$item->{biblionumber},$item->{biblioitemnumber});
1599         z3950_extended_services($Zconn,'update',set_service_options('update'),$record);
1600     if ( defined $sth->errstr ) {
1601         $error .= $sth->errstr;
1602     }
1603         $dbh->do('unlock tables');
1604
1605 }
1606
1607 =head2 REALdelitem($dbh,$itemnum);
1608
1609 =over 4
1610
1611 delete item
1612
1613 =back
1614
1615 =cut
1616
1617 sub REALdelitem {
1618     my ( $dbh, $itemnum ) = @_;
1619
1620     #  my $dbh=C4Connect;
1621     my $sth = $dbh->prepare("select * from items where itemnumber=?");
1622     $sth->execute($itemnum);
1623     my $data = $sth->fetchrow_hashref;
1624     $sth->finish;
1625     my $query = "Insert into deleteditems set ";
1626     my @bind  = ();
1627     foreach my $temp ( keys %$data ) {
1628         $query .= "$temp = ?,";
1629         push ( @bind, $data->{$temp} );
1630     }
1631     $query =~ s/\,$//;
1632
1633     #  print $query;
1634     $sth = $dbh->prepare($query);
1635     $sth->execute(@bind);
1636     $sth->finish;
1637     $sth = $dbh->prepare("Delete from items where itemnumber=?");
1638     $sth->execute($itemnum);
1639     $sth->finish;
1640
1641     #  $dbh->disconnect;
1642 }
1643
1644 =head2 REALdelbiblioitem($dbh,$biblioitemnumber);
1645
1646 =over 4
1647
1648 deletes a biblioitem
1649 NOTE : not standard sub name. Should be REALdelbiblioitem()
1650
1651 =back
1652
1653 =cut
1654
1655 sub REALdelbiblioitem {
1656     my ( $dbh, $biblioitemnumber ) = @_;
1657
1658     #    my $dbh   = C4Connect;
1659     my $sth = $dbh->prepare( "Select * from biblioitems
1660 where biblioitemnumber = ?"
1661     );
1662     my $results;
1663
1664     $sth->execute($biblioitemnumber);
1665
1666     if ( $results = $sth->fetchrow_hashref ) {
1667         $sth->finish;
1668         $sth =
1669           $dbh->prepare(
1670 "Insert into deletedbiblioitems (biblioitemnumber, biblionumber, volume, number, classification, itemtype,
1671                                         isbn, issn ,dewey ,subclass ,publicationyear ,publishercode ,volumedate ,volumeddesc ,timestamp ,illus ,
1672                                         pages ,notes ,size ,url ,lccn ) values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"
1673         );
1674
1675         $sth->execute(
1676             $results->{biblioitemnumber}, $results->{biblionumber},
1677             $results->{volume},           $results->{number},
1678             $results->{classification},   $results->{itemtype},
1679             $results->{isbn},             $results->{issn},
1680             $results->{dewey},            $results->{subclass},
1681             $results->{publicationyear},  $results->{publishercode},
1682             $results->{volumedate},       $results->{volumeddesc},
1683             $results->{timestamp},        $results->{illus},
1684             $results->{pages},            $results->{notes},
1685             $results->{size},             $results->{url},
1686             $results->{lccn}
1687         );
1688         my $sth2 =
1689           $dbh->prepare("Delete from biblioitems where biblioitemnumber = ?");
1690         $sth2->execute($biblioitemnumber);
1691         $sth2->finish();
1692     }    # if
1693     $sth->finish;
1694
1695     # Now delete all the items attached to the biblioitem
1696     $sth = $dbh->prepare("Select * from items where biblioitemnumber = ?");
1697     $sth->execute($biblioitemnumber);
1698     my @results;
1699     while ( my $data = $sth->fetchrow_hashref ) {
1700         my $query = "Insert into deleteditems set ";
1701         my @bind  = ();
1702         foreach my $temp ( keys %$data ) {
1703             $query .= "$temp = ?,";
1704             push ( @bind, $data->{$temp} );
1705         }
1706         $query =~ s/\,$//;
1707         my $sth2 = $dbh->prepare($query);
1708         $sth2->execute(@bind);
1709     }    # while
1710     $sth->finish;
1711     $sth = $dbh->prepare("Delete from items where biblioitemnumber = ?");
1712     $sth->execute($biblioitemnumber);
1713     $sth->finish();
1714
1715     #    $dbh->disconnect;
1716 }    # sub deletebiblioitem
1717
1718 =head2 REALdelbiblio($dbh,$biblio);
1719
1720 =over 4
1721
1722 delete a biblio
1723
1724 =back
1725
1726 =cut
1727
1728 sub REALdelbiblio {
1729     my ( $dbh, $biblio ) = @_;
1730     my $sth = $dbh->prepare("select * from biblio where biblionumber=?");
1731     $sth->execute($biblio);
1732     if ( my $data = $sth->fetchrow_hashref ) {
1733         $sth->finish;
1734         my $query = "Insert into deletedbiblio set ";
1735         my @bind  = ();
1736         foreach my $temp ( keys %$data ) {
1737             $query .= "$temp = ?,";
1738             push ( @bind, $data->{$temp} );
1739         }
1740
1741         #replacing the last , by ",?)"
1742         $query =~ s/\,$//;
1743         $sth = $dbh->prepare($query);
1744         $sth->execute(@bind);
1745         $sth->finish;
1746         $sth = $dbh->prepare("Delete from biblio where biblionumber=?");
1747         $sth->execute($biblio);
1748         $sth->finish;
1749     }
1750     $sth->finish;
1751 }
1752
1753 =head2 itemcount
1754
1755 $number = itemcount($biblio);
1756
1757 =over 4
1758
1759 returns the number of items attached to a biblio
1760
1761 =back
1762
1763 =cut
1764
1765 sub itemcount {
1766     my ($biblio) = @_;
1767     my $dbh = C4::Context->dbh;
1768
1769     #  print $query;
1770     my $sth = $dbh->prepare("Select count(*) from items where biblionumber=?");
1771     $sth->execute($biblio);
1772     my $data = $sth->fetchrow_hashref;
1773     $sth->finish;
1774     return ( $data->{'count(*)'} );
1775 }
1776
1777 =head2 newbiblio
1778
1779 $biblionumber = newbiblio($biblio);
1780
1781 =over 4
1782
1783 create a biblio. The parameter is a hash
1784
1785 =back
1786
1787 =cut
1788
1789 sub newbiblio {
1790     my ($biblio) = @_;
1791     my $dbh    = C4::Context->dbh;
1792     my $bibnum = REALnewbiblio( $dbh, $biblio );
1793     # finds new (MARC bibid
1794     #   my $bibid = &MARCfind_MARCbibid_from_oldbiblionumber($dbh,$bibnum);
1795 #     my $record = &MARCkoha2marcBiblio( $dbh, $bibnum );
1796 #     MARCaddbiblio( $dbh, $record, $bibnum,'' );
1797     return ($bibnum);
1798 }
1799
1800 =head2  modbiblio
1801
1802 $biblionumber = &modbiblio($biblio);
1803
1804 =over 4
1805
1806 Update a biblio record.
1807
1808 C<$biblio> is a reference-to-hash whose keys are the fields in the
1809 biblio table in the Koha database. All fields must be present, not
1810 just the ones you wish to change.
1811
1812 C<&modbiblio> updates the record defined by
1813 C<$biblio-E<gt>{biblionumber}> with the values in C<$biblio>.
1814
1815 C<&modbiblio> returns C<$biblio-E<gt>{biblionumber}> whether it was
1816 successful or not.
1817
1818 =back
1819
1820 =cut
1821
1822 sub modbiblio {
1823         my ($biblio) = @_;
1824         my $dbh  = C4::Context->dbh;
1825         my $biblionumber=REALmodbiblio($dbh,$biblio);
1826         my $record = MARCkoha2marcBiblio($dbh,$biblionumber,$biblionumber);
1827         # finds new (MARC bibid
1828         my $bibid = &MARCfind_MARCbibid_from_oldbiblionumber($dbh,$biblionumber);
1829         MARCmodbiblio($dbh,$bibid,$record,"",0);
1830         return($biblionumber);
1831 } # sub modbiblio
1832
1833 =head2 &modsubtitle($biblionumber, $subtitle);
1834
1835 =over 4
1836
1837 Sets the subtitle of a book.
1838
1839 C<$biblionumber> is the biblionumber of the book to modify.
1840
1841 C<$subtitle> is the new subtitle.
1842
1843 =back
1844
1845 =cut
1846
1847 sub modsubtitle {
1848     my ( $bibnum, $subtitle ) = @_;
1849     my $dbh = C4::Context->dbh;
1850     &REALmodsubtitle( $dbh, $bibnum, $subtitle );
1851 }    # sub modsubtitle
1852
1853 =head2 &modaddauthor($biblionumber, $author);
1854
1855 =over 4
1856
1857 Replaces all additional authors for the book with biblio number
1858 C<$biblionumber> with C<$author>. If C<$author> is the empty string,
1859 C<&modaddauthor> deletes all additional authors.
1860
1861 =back
1862
1863 =cut
1864
1865 sub modaddauthor {
1866     my ( $bibnum, @authors ) = @_;
1867     my $dbh = C4::Context->dbh;
1868     &REALmodaddauthor( $dbh, $bibnum, @authors );
1869 }    # sub modaddauthor
1870
1871 =head2 modsubject
1872
1873 $error = &modsubject($biblionumber, $force, @subjects);
1874
1875 =over 4
1876
1877 $force - a subject to force
1878 $error - Error message, or undef if successful.
1879
1880 =back
1881
1882 =cut
1883
1884 sub modsubject {
1885     my ( $bibnum, $force, @subject ) = @_;
1886     my $dbh = C4::Context->dbh;
1887     my $error = &REALmodsubject( $dbh, $bibnum, $force, @subject );
1888     if ($error eq ''){
1889                 # When MARC is off, ensures that the MARC biblio table gets updated with new
1890                 # subjects, of course, it deletes the biblio in marc, and then recreates.
1891                 # This check is to ensure that no MARC data exists to lose.
1892 #               if (C4::Context->preference("MARC") eq '0'){
1893 #               warn "in modSUBJECT";
1894 #                       my $MARCRecord = &MARCkoha2marcBiblio($dbh,$bibnum);
1895 #                       my $bibid = &MARCfind_MARCbibid_from_oldbiblionumber($dbh,$bibnum);
1896 #                       &MARCmodbiblio($dbh,$bibid, $MARCRecord);
1897 #               }
1898         }
1899         return ($error);
1900 }    # sub modsubject
1901
1902 =head2 modbibitem($dbh, $Zconn,$biblioitem);
1903
1904 =over 4
1905
1906 modify a biblioitem. The parameter is a hash
1907
1908 =back
1909
1910 =cut
1911
1912 sub modbibitem {
1913     my ($dbh, $Zconn, $biblioitem) = @_;
1914     #my $dbh = C4::Context->dbh;
1915     &REALmodbiblioitem( $dbh, $Zconn, $biblioitem );
1916 }    # sub modbibitem
1917
1918 =head2 newbiblioitem
1919
1920 $biblioitemnumber = newbiblioitem($biblioitem)
1921
1922 =over 4
1923
1924 create a biblioitem, the parameter is a hash
1925
1926 =back
1927
1928 =cut
1929
1930 sub newbiblioitem {
1931     my ($dbh, $Zconn, $biblioitem) = @_;
1932     #my $dbh        = C4::Context->dbh;
1933         # add biblio information to the hash
1934     my $MARCbiblio = MARCkoha2marcBiblio( $dbh, $biblioitem );
1935         $biblioitem->{marc} = $MARCbiblio->as_usmarc();
1936     my $bibitemnum = &REALnewbiblioitem( $dbh, $Zconn, $biblioitem );
1937     return ($bibitemnum);
1938 }
1939
1940 =head2 newsubtitle($biblionumber,$subtitle);
1941
1942 =over 4
1943
1944 insert a subtitle for $biblionumber biblio
1945
1946 =back
1947
1948 =cut
1949
1950
1951 sub newsubtitle {
1952     my ( $bibnum, $subtitle ) = @_;
1953     my $dbh = C4::Context->dbh;
1954     &REALnewsubtitle( $dbh, $bibnum, $subtitle );
1955 }
1956
1957 =head2 newitems
1958
1959 $errors = newitems($dbh, $Zconn, $item, @barcodes);
1960
1961 =over 4
1962
1963 insert items ($item is a hash)
1964
1965 =back
1966
1967 =cut
1968
1969
1970 sub newitems {
1971     my ( $dbh, $Zconn, $item, @barcodes ) = @_;
1972     #my $dbh = C4::Context->dbh;
1973     my $errors;
1974     my $itemnumber;
1975     my $error;
1976     foreach my $barcode (@barcodes) {
1977                 # add items, one by one for each barcode.
1978                 my $oneitem=$item;
1979                 $oneitem->{barcode}= $barcode;
1980         my $MARCitem = &MARCkoha2marcItem( $dbh, $oneitem);
1981                 $oneitem->{marc} = $MARCitem->as_usmarc;
1982         ( $itemnumber, $error ) = &REALnewitems( $dbh,$Zconn,$oneitem);
1983 #         $errors .= $error;
1984 #         &MARCadditem( $dbh, $MARCitem, $item->{biblionumber} );
1985     }
1986     return ($errors);
1987 }
1988
1989 =head2 moditem($dbh,$Zconn,$item);
1990
1991 =over 4
1992
1993 modify an item ($item is a hash with all item informations)
1994
1995 =back
1996
1997 =cut
1998
1999
2000 sub moditem {
2001     my ($dbh,$Zconn,$item) = @_;
2002     #my $dbh = C4::Context->dbh;
2003     &REALmoditem( $dbh, $Zconn, $item );
2004     my $MARCitem =
2005       &MARCkoha2marcItem( $dbh, $item->{'biblionumber'}, $item->{'itemnum'} );
2006     my $bibid =
2007       &MARCfind_MARCbibid_from_oldbiblionumber( $dbh, $item->{biblionumber} );
2008     &MARCmoditem( $dbh, $MARCitem, $bibid, $item->{itemnum}, 0 );
2009 }
2010
2011 =head2 checkitems
2012
2013 $error = checkitems($count,@barcodes);
2014
2015 =over 4
2016
2017 check for each @barcode entry that the barcode is not a duplicate
2018
2019 =back
2020
2021 =cut
2022
2023 sub checkitems {
2024     my ( $count, @barcodes ) = @_;
2025     my $dbh = C4::Context->dbh;
2026     my $error;
2027     my $sth = $dbh->prepare("Select * from items where barcode=?");
2028     for ( my $i = 0 ; $i < $count ; $i++ ) {
2029         $barcodes[$i] = uc $barcodes[$i];
2030         $sth->execute( $barcodes[$i] );
2031         if ( my $data = $sth->fetchrow_hashref ) {
2032             $error .= " Duplicate Barcode: $barcodes[$i]";
2033         }
2034     }
2035     $sth->finish;
2036     return ($error);
2037 }
2038
2039 =head2 delitem($itemnum);
2040
2041 =over 4
2042
2043 delete item $itemnum being the item number to delete
2044
2045 =back
2046
2047 =cut
2048
2049 sub delitem {
2050     my ($itemnum) = @_;
2051     my $dbh = C4::Context->dbh;
2052     &REALdelitem( $dbh, $itemnum );
2053 }
2054
2055 =head2 deletebiblioitem($biblioitemnumber);
2056
2057 =over 4
2058
2059 delete the biblioitem $biblioitemnumber
2060
2061 =back
2062
2063 =cut
2064
2065 sub deletebiblioitem {
2066     my ($biblioitemnumber) = @_;
2067     my $dbh = C4::Context->dbh;
2068     &REALdelbiblioitem( $dbh, $biblioitemnumber );
2069 }    # sub deletebiblioitem
2070
2071 =head2 delbiblio($biblionumber)
2072
2073 =over 4
2074
2075 delete biblio $biblionumber
2076
2077 =back
2078
2079 =cut
2080
2081 sub delbiblio {
2082     my ($biblio) = @_;
2083     my $dbh = C4::Context->dbh;
2084     &REALdelbiblio( $dbh, $biblio );
2085     my $bibid = &MARCfind_MARCbibid_from_oldbiblionumber( $dbh, $biblio );
2086     &MARCdelbiblio( $dbh, $bibid, 0 );
2087 }
2088
2089 =head2 getbiblio
2090
2091 ($count,@results) = getbiblio($biblionumber);
2092
2093 =over 4
2094
2095 return an array with hash of biblios.
2096
2097 FIXME : biblionumber being the primary key, this sub will always return only 1 result, API should be modified...
2098
2099 =back
2100
2101 =cut
2102
2103 sub getbiblio {
2104     my ($biblionumber) = @_;
2105     my $dbh = C4::Context->dbh;
2106     my $sth = $dbh->prepare("Select * from biblio where biblionumber = ?");
2107
2108     # || die "Cannot prepare $query\n" . $dbh->errstr;
2109     my $count = 0;
2110     my @results;
2111
2112     $sth->execute($biblionumber);
2113
2114     # || die "Cannot execute $query\n" . $sth->errstr;
2115     while ( my $data = $sth->fetchrow_hashref ) {
2116         $results[$count] = $data;
2117         $count++;
2118     }    # while
2119
2120     $sth->finish;
2121     return ( $count, @results );
2122 }    # sub getbiblio
2123
2124 =head2 bibdata
2125
2126   $data = &bibdata($biblionumber, $type);
2127
2128 Returns information about the book with the given biblionumber.
2129
2130 C<$type> is ignored.
2131
2132 C<&bibdata> returns a reference-to-hash. The keys are the fields in
2133 the C<biblio>, C<biblioitems>, and C<bibliosubtitle> tables in the
2134 Koha database.
2135
2136 In addition, C<$data-E<gt>{subject}> is the list of the book's
2137 subjects, separated by C<" , "> (space, comma, space).
2138
2139 If there are multiple biblioitems with the given biblionumber, only
2140 the first one is considered.
2141
2142 =cut
2143 #'
2144 sub bibdata {
2145         my ($bibnum, $type) = @_;
2146         my $dbh   = C4::Context->dbh;
2147         my $sth   = $dbh->prepare("Select *, biblioitems.notes AS bnotes, biblio.notes
2148                                                                 from biblio 
2149                                                                 left join biblioitems on biblioitems.biblionumber = biblio.biblionumber
2150                                                                 left join bibliosubtitle on
2151                                                                 biblio.biblionumber = bibliosubtitle.biblionumber
2152                                                                 left join itemtypes on biblioitems.itemtype=itemtypes.itemtype
2153                                                                 where biblio.biblionumber = ?
2154                                                                 ");
2155         $sth->execute($bibnum);
2156         my $data;
2157         $data  = $sth->fetchrow_hashref;
2158         $sth->finish;
2159         # handle management of repeated subtitle
2160         $sth   = $dbh->prepare("Select * from bibliosubtitle where biblionumber = ?");
2161         $sth->execute($bibnum);
2162         my @subtitles;
2163         while (my $dat = $sth->fetchrow_hashref){
2164                 my %line;
2165                 $line{subtitle} = $dat->{subtitle};
2166                 push @subtitles, \%line;
2167         } # while
2168         $data->{subtitles} = \@subtitles;
2169         $sth->finish;
2170         $sth   = $dbh->prepare("Select * from bibliosubject where biblionumber = ?");
2171         $sth->execute($bibnum);
2172         my @subjects;
2173         while (my $dat = $sth->fetchrow_hashref){
2174                 my %line;
2175                 $line{subject} = $dat->{'subject'};
2176                 push @subjects, \%line;
2177         } # while
2178         $data->{subjects} = \@subjects;
2179         $sth->finish;
2180         $sth   = $dbh->prepare("Select * from additionalauthors where biblionumber = ?");
2181         $sth->execute($bibnum);
2182         while (my $dat = $sth->fetchrow_hashref){
2183                 $data->{'additionalauthors'} .= "$dat->{'author'} - ";
2184         } # while
2185         chop $data->{'additionalauthors'};
2186         chop $data->{'additionalauthors'};
2187         chop $data->{'additionalauthors'};
2188         $sth->finish;
2189         return($data);
2190 } # sub bibdata
2191
2192 =head2 getbiblioitem
2193
2194 ($count,@results) = getbiblioitem($biblioitemnumber);
2195
2196 =over 4
2197
2198 return an array with hash of biblioitemss.
2199
2200 FIXME : biblioitemnumber being unique, this sub will always return only 1 result, API should be modified...
2201
2202 =back
2203
2204 =cut
2205
2206 sub getbiblioitem {
2207     my ($biblioitemnum) = @_;
2208     my $dbh = C4::Context->dbh;
2209     my $sth = $dbh->prepare( "Select * from biblioitems where
2210 biblioitemnumber = ?"
2211     );
2212     my $count = 0;
2213     my @results;
2214
2215     $sth->execute($biblioitemnum);
2216
2217     while ( my $data = $sth->fetchrow_hashref ) {
2218         $results[$count] = $data;
2219         $count++;
2220     }    # while
2221
2222     $sth->finish;
2223     return ( $count, @results );
2224 }    # sub getbiblioitem
2225
2226 =head2 getbiblioitembybiblionumber
2227
2228 ($count,@results) = getbiblioitembybiblionumber($biblionumber);
2229
2230 =over 4
2231
2232 return an array with hash of biblioitems for the given biblionumber.
2233
2234 =back
2235
2236 =cut
2237
2238 sub getbiblioitembybiblionumber {
2239     my ($biblionumber) = @_;
2240     my $dbh = C4::Context->dbh;
2241     my $sth = $dbh->prepare("Select * from biblioitems where biblionumber = ?");
2242     my $count = 0;
2243     my @results;
2244
2245     $sth->execute($biblionumber);
2246
2247     while ( my $data = $sth->fetchrow_hashref ) {
2248         $results[$count] = $data;
2249         $count++;
2250     }    # while
2251
2252     $sth->finish;
2253     return ( $count, @results );
2254 }    # sub
2255
2256 =head2 getitemsbybiblioitem
2257
2258 ($count,@results) = getitemsbybiblioitem($biblionumber);
2259
2260 =over 4
2261
2262 returns an array with hash of items
2263
2264 =back
2265
2266 =cut
2267
2268 sub getitemsbybiblioitem {
2269     my ($biblioitemnum) = @_;
2270     my $dbh = C4::Context->dbh;
2271     my $sth = $dbh->prepare( "Select * from items, biblio where
2272 biblio.biblionumber = items.biblionumber and biblioitemnumber
2273 = ?"
2274     );
2275
2276     # || die "Cannot prepare $query\n" . $dbh->errstr;
2277     my $count = 0;
2278     my @results;
2279
2280     $sth->execute($biblioitemnum);
2281
2282     # || die "Cannot execute $query\n" . $sth->errstr;
2283     while ( my $data = $sth->fetchrow_hashref ) {
2284         $results[$count] = $data;
2285         $count++;
2286     }    # while
2287
2288     $sth->finish;
2289     return ( $count, @results );
2290 }    # sub getitemsbybiblioitem
2291
2292 =head2 ItemInfo
2293
2294   @results = &ItemInfo($env, $biblionumber, $type);
2295
2296 Returns information about books with the given biblionumber.
2297
2298 C<$type> may be either C<intra> or anything else. If it is not set to
2299 C<intra>, then the search will exclude lost, very overdue, and
2300 withdrawn items.
2301
2302 C<$env> is ignored.
2303
2304 C<&ItemInfo> returns a list of references-to-hash. Each element
2305 contains a number of keys. Most of them are table items from the
2306 C<biblio>, C<biblioitems>, C<items>, and C<itemtypes> tables in the
2307 Koha database. Other keys include:
2308
2309 =over 4
2310
2311 =item C<$data-E<gt>{branchname}>
2312
2313 The name (not the code) of the branch to which the book belongs.
2314
2315 =item C<$data-E<gt>{datelastseen}>
2316
2317 This is simply C<items.datelastseen>, except that while the date is
2318 stored in YYYY-MM-DD format in the database, here it is converted to
2319 DD/MM/YYYY format. A NULL date is returned as C<//>.
2320
2321 =item C<$data-E<gt>{datedue}>
2322
2323 =item C<$data-E<gt>{class}>
2324
2325 This is the concatenation of C<biblioitems.classification>, the book's
2326 Dewey code, and C<biblioitems.subclass>.
2327
2328 =item C<$data-E<gt>{ocount}>
2329
2330 I think this is the number of copies of the book available.
2331
2332 =item C<$data-E<gt>{order}>
2333
2334 If this is set, it is set to C<One Order>.
2335
2336 =back
2337
2338 =cut
2339 #'
2340 sub ItemInfo {
2341         my ($env,$biblionumber,$type) = @_;
2342         my $dbh   = C4::Context->dbh;
2343         my $query = "SELECT *,items.notforloan as itemnotforloan FROM items, biblio, biblioitems 
2344                                         left join itemtypes on biblioitems.itemtype = itemtypes.itemtype
2345                                         WHERE items.biblionumber = ?
2346                                         AND biblioitems.biblioitemnumber = items.biblioitemnumber
2347                                         AND biblio.biblionumber = items.biblionumber";
2348         $query .= " order by items.dateaccessioned desc";
2349         my $sth=$dbh->prepare($query);
2350         $sth->execute($biblionumber);
2351         my $i=0;
2352         my @results;
2353         while (my $data=$sth->fetchrow_hashref){
2354                 my $datedue = '';
2355                 my $isth=$dbh->prepare("Select issues.*,borrowers.cardnumber from issues,borrowers where itemnumber = ? and returndate is null and issues.borrowernumber=borrowers.borrowernumber");
2356                 $isth->execute($data->{'itemnumber'});
2357                 if (my $idata=$isth->fetchrow_hashref){
2358                 $data->{borrowernumber} = $idata->{borrowernumber};
2359                 $data->{cardnumber} = $idata->{cardnumber};
2360                 $datedue = format_date($idata->{'date_due'});
2361                 }
2362                 if ($datedue eq ''){
2363                         my ($restype,$reserves)=C4::Reserves2::CheckReserves($data->{'itemnumber'});
2364                         if ($restype) {
2365                                 $datedue=$restype;
2366                         }
2367                 }
2368                 $isth->finish;
2369         #get branch information.....
2370                 my $bsth=$dbh->prepare("SELECT * FROM branches WHERE branchcode = ?");
2371                 $bsth->execute($data->{'holdingbranch'});
2372                 if (my $bdata=$bsth->fetchrow_hashref){
2373                         $data->{'branchname'} = $bdata->{'branchname'};
2374                 }
2375                 my $date=format_date($data->{'datelastseen'});
2376                 $data->{'datelastseen'}=$date;
2377                 $data->{'datedue'}=$datedue;
2378         # get notforloan complete status if applicable
2379                 my $sthnflstatus = $dbh->prepare('select authorised_value from marc_subfield_structure where kohafield="items.notforloan"');
2380                 $sthnflstatus->execute;
2381                 my ($authorised_valuecode) = $sthnflstatus->fetchrow;
2382                 if ($authorised_valuecode) {
2383                         $sthnflstatus = $dbh->prepare("select lib from authorised_values where category=? and authorised_value=?");
2384                         $sthnflstatus->execute($authorised_valuecode,$data->{itemnotforloan});
2385                         my ($lib) = $sthnflstatus->fetchrow;
2386                         $data->{notforloan} = $lib;
2387                 }
2388                 $results[$i]=$data;
2389                 $i++;
2390         }
2391         $sth->finish;
2392         return(@results);
2393 }
2394
2395 =head2 bibitems
2396
2397   ($count, @results) = &bibitems($biblionumber);
2398
2399 Given the biblionumber for a book, C<&bibitems> looks up that book's
2400 biblioitems (different publications of the same book, the audio book
2401 and film versions, etc.).
2402
2403 C<$count> is the number of elements in C<@results>.
2404
2405 C<@results> is an array of references-to-hash; the keys are the fields
2406 of the C<biblioitems> and C<itemtypes> tables of the Koha database. In
2407 addition, C<itemlost> indicates the availability of the item: if it is
2408 "2", then all copies of the item are long overdue; if it is "1", then
2409 all copies are lost; otherwise, there is at least one copy available.
2410
2411 =cut
2412 #'
2413 sub bibitems {
2414     my ($bibnum) = @_;
2415     my $dbh   = C4::Context->dbh;
2416     my $sth   = $dbh->prepare("SELECT biblioitems.*,
2417                         itemtypes.*,
2418                         MIN(items.itemlost)        as itemlost,
2419                         MIN(items.dateaccessioned) as dateaccessioned
2420                           FROM biblioitems, itemtypes, items
2421                          WHERE biblioitems.biblionumber     = ?
2422                            AND biblioitems.itemtype         = itemtypes.itemtype
2423                            AND biblioitems.biblioitemnumber = items.biblioitemnumber
2424                       GROUP BY items.biblioitemnumber");
2425     my $count = 0;
2426     my @results;
2427     $sth->execute($bibnum);
2428     while (my $data = $sth->fetchrow_hashref) {
2429         $results[$count] = $data;
2430         $count++;
2431     } # while
2432     $sth->finish;
2433     return($count, @results);
2434 } # sub bibitems
2435
2436
2437 =head2 bibitemdata
2438
2439   $itemdata = &bibitemdata($biblioitemnumber);
2440
2441 Looks up the biblioitem with the given biblioitemnumber. Returns a
2442 reference-to-hash. The keys are the fields from the C<biblio>,
2443 C<biblioitems>, and C<itemtypes> tables in the Koha database, except
2444 that C<biblioitems.notes> is given as C<$itemdata-E<gt>{bnotes}>.
2445
2446 =cut
2447 #'
2448 sub bibitemdata {
2449     my ($bibitem) = @_;
2450     my $dbh   = C4::Context->dbh;
2451     my $sth   = $dbh->prepare("Select *,biblioitems.notes as bnotes from biblio, biblioitems,itemtypes where biblio.biblionumber = biblioitems.biblionumber and biblioitemnumber = ? and biblioitems.itemtype = itemtypes.itemtype");
2452     my $data;
2453
2454     $sth->execute($bibitem);
2455
2456     $data = $sth->fetchrow_hashref;
2457
2458     $sth->finish;
2459     return($data);
2460 } # sub bibitemdata
2461
2462
2463 =head2 getbibliofromitemnumber
2464
2465   $item = &getbibliofromitemnumber($env, $dbh, $itemnumber);
2466
2467 Looks up the item with the given itemnumber.
2468
2469 C<$env> and C<$dbh> are ignored.
2470
2471 C<&itemnodata> returns a reference-to-hash whose keys are the fields
2472 from the C<biblio>, C<biblioitems>, and C<items> tables in the Koha
2473 database.
2474
2475 =cut
2476 #'
2477 sub getbibliofromitemnumber {
2478   my ($env,$dbh,$itemnumber) = @_;
2479   $dbh = C4::Context->dbh;
2480   my $sth=$dbh->prepare("Select * from biblio,items,biblioitems
2481     where items.itemnumber = ?
2482     and biblio.biblionumber = items.biblionumber
2483     and biblioitems.biblioitemnumber = items.biblioitemnumber");
2484 #  print $query;
2485   $sth->execute($itemnumber);
2486   my $data=$sth->fetchrow_hashref;
2487   $sth->finish;
2488   return($data);
2489 }
2490
2491 =head2 barcodes
2492
2493   @barcodes = &barcodes($biblioitemnumber);
2494
2495 Given a biblioitemnumber, looks up the corresponding items.
2496
2497 Returns an array of references-to-hash; the keys are C<barcode> and
2498 C<itemlost>.
2499
2500 The returned items include very overdue items, but not lost ones.
2501
2502 =cut
2503 #'
2504 sub barcodes{
2505     #called from request.pl
2506     my ($biblioitemnumber)=@_;
2507     my $dbh = C4::Context->dbh;
2508     my $sth=$dbh->prepare("SELECT barcode, itemlost, holdingbranch FROM items
2509                            WHERE biblioitemnumber = ?
2510                              AND (wthdrawn <> 1 OR wthdrawn IS NULL)");
2511     $sth->execute($biblioitemnumber);
2512     my @barcodes;
2513     my $i=0;
2514     while (my $data=$sth->fetchrow_hashref){
2515         $barcodes[$i]=$data;
2516         $i++;
2517     }
2518     $sth->finish;
2519     return(@barcodes);
2520 }
2521
2522
2523 =head2 itemdata
2524
2525   $item = &itemdata($barcode);
2526
2527 Looks up the item with the given barcode, and returns a
2528 reference-to-hash containing information about that item. The keys of
2529 the hash are the fields from the C<items> and C<biblioitems> tables in
2530 the Koha database.
2531
2532 =cut
2533 #'
2534 sub get_item_from_barcode {
2535   my ($barcode)=@_;
2536   my $dbh = C4::Context->dbh;
2537   my $sth=$dbh->prepare("Select * from items,biblioitems where barcode=?
2538   and items.biblioitemnumber=biblioitems.biblioitemnumber");
2539   $sth->execute($barcode);
2540   my $data=$sth->fetchrow_hashref;
2541   $sth->finish;
2542   return($data);
2543 }
2544
2545
2546 =head2 itemissues
2547
2548   @issues = &itemissues($biblioitemnumber, $biblio);
2549
2550 Looks up information about who has borrowed the bookZ<>(s) with the
2551 given biblioitemnumber.
2552
2553 C<$biblio> is ignored.
2554
2555 C<&itemissues> returns an array of references-to-hash. The keys
2556 include the fields from the C<items> table in the Koha database.
2557 Additional keys include:
2558
2559 =over 4
2560
2561 =item C<date_due>
2562
2563 If the item is currently on loan, this gives the due date.
2564
2565 If the item is not on loan, then this is either "Available" or
2566 "Cancelled", if the item has been withdrawn.
2567
2568 =item C<card>
2569
2570 If the item is currently on loan, this gives the card number of the
2571 patron who currently has the item.
2572
2573 =item C<timestamp0>, C<timestamp1>, C<timestamp2>
2574
2575 These give the timestamp for the last three times the item was
2576 borrowed.
2577
2578 =item C<card0>, C<card1>, C<card2>
2579
2580 The card number of the last three patrons who borrowed this item.
2581
2582 =item C<borrower0>, C<borrower1>, C<borrower2>
2583
2584 The borrower number of the last three patrons who borrowed this item.
2585
2586 =back
2587
2588 =cut
2589 #'
2590 sub itemissues {
2591     my ($bibitem, $biblio)=@_;
2592     my $dbh   = C4::Context->dbh;
2593     # FIXME - If this function die()s, the script will abort, and the
2594     # user won't get anything; depending on how far the script has
2595     # gotten, the user might get a blank page. It would be much better
2596     # to at least print an error message. The easiest way to do this
2597     # is to set $SIG{__DIE__}.
2598     my $sth   = $dbh->prepare("Select * from items where
2599 items.biblioitemnumber = ?")
2600       || die $dbh->errstr;
2601     my $i     = 0;
2602     my @results;
2603
2604     $sth->execute($bibitem)
2605       || die $sth->errstr;
2606
2607     while (my $data = $sth->fetchrow_hashref) {
2608         # Find out who currently has this item.
2609         # FIXME - Wouldn't it be better to do this as a left join of
2610         # some sort? Currently, this code assumes that if
2611         # fetchrow_hashref() fails, then the book is on the shelf.
2612         # fetchrow_hashref() can fail for any number of reasons (e.g.,
2613         # database server crash), not just because no items match the
2614         # search criteria.
2615         my $sth2   = $dbh->prepare("select * from issues,borrowers
2616 where itemnumber = ?
2617 and returndate is NULL
2618 and issues.borrowernumber = borrowers.borrowernumber");
2619
2620         $sth2->execute($data->{'itemnumber'});
2621         if (my $data2 = $sth2->fetchrow_hashref) {
2622             $data->{'date_due'} = $data2->{'date_due'};
2623             $data->{'card'}     = $data2->{'cardnumber'};
2624             $data->{'borrower'}     = $data2->{'borrowernumber'};
2625         } else {
2626             if ($data->{'wthdrawn'} eq '1') {
2627                 $data->{'date_due'} = 'Cancelled';
2628             } else {
2629                 $data->{'date_due'} = 'Available';
2630             } # else
2631         } # else
2632
2633         $sth2->finish;
2634
2635         # Find the last 3 people who borrowed this item.
2636         $sth2 = $dbh->prepare("select * from issues, borrowers
2637                                                 where itemnumber = ?
2638                                                                         and issues.borrowernumber = borrowers.borrowernumber
2639                                                                         and returndate is not NULL
2640                                                                         order by returndate desc,timestamp desc") || die $dbh->errstr;
2641         $sth2->execute($data->{'itemnumber'}) || die $sth2->errstr;
2642         for (my $i2 = 0; $i2 < 2; $i2++) { # FIXME : error if there is less than 3 pple borrowing this item
2643             if (my $data2 = $sth2->fetchrow_hashref) {
2644                 $data->{"timestamp$i2"} = $data2->{'timestamp'};
2645                 $data->{"card$i2"}      = $data2->{'cardnumber'};
2646                 $data->{"borrower$i2"}  = $data2->{'borrowernumber'};
2647             } # if
2648         } # for
2649
2650         $sth2->finish;
2651         $results[$i] = $data;
2652         $i++;
2653     }
2654
2655     $sth->finish;
2656     return(@results);
2657 }
2658
2659 =head2 getsubject
2660
2661   ($count, $subjects) = &getsubject($biblionumber);
2662
2663 Looks up the subjects of the book with the given biblionumber. Returns
2664 a two-element list. C<$subjects> is a reference-to-array, where each
2665 element is a subject of the book, and C<$count> is the number of
2666 elements in C<$subjects>.
2667
2668 =cut
2669 #'
2670 sub getsubject {
2671   my ($bibnum)=@_;
2672   my $dbh = C4::Context->dbh;
2673   my $sth=$dbh->prepare("Select * from bibliosubject where biblionumber=?");
2674   $sth->execute($bibnum);
2675   my @results;
2676   my $i=0;
2677   while (my $data=$sth->fetchrow_hashref){
2678     $results[$i]=$data;
2679     $i++;
2680   }
2681   $sth->finish;
2682   return($i,\@results);
2683 }
2684
2685 =head2 getaddauthor
2686
2687   ($count, $authors) = &getaddauthor($biblionumber);
2688
2689 Looks up the additional authors for the book with the given
2690 biblionumber.
2691
2692 Returns a two-element list. C<$authors> is a reference-to-array, where
2693 each element is an additional author, and C<$count> is the number of
2694 elements in C<$authors>.
2695
2696 =cut
2697 #'
2698 sub getaddauthor {
2699   my ($bibnum)=@_;
2700   my $dbh = C4::Context->dbh;
2701   my $sth=$dbh->prepare("Select * from additionalauthors where biblionumber=?");
2702   $sth->execute($bibnum);
2703   my @results;
2704   my $i=0;
2705   while (my $data=$sth->fetchrow_hashref){
2706     $results[$i]=$data;
2707     $i++;
2708   }
2709   $sth->finish;
2710   return($i,\@results);
2711 }
2712
2713
2714 =head2 getsubtitle
2715
2716   ($count, $subtitles) = &getsubtitle($biblionumber);
2717
2718 Looks up the subtitles for the book with the given biblionumber.
2719
2720 Returns a two-element list. C<$subtitles> is a reference-to-array,
2721 where each element is a subtitle, and C<$count> is the number of
2722 elements in C<$subtitles>.
2723
2724 =cut
2725 #'
2726 sub getsubtitle {
2727   my ($bibnum)=@_;
2728   my $dbh = C4::Context->dbh;
2729   my $sth=$dbh->prepare("Select * from bibliosubtitle where biblionumber=?");
2730   $sth->execute($bibnum);
2731   my @results;
2732   my $i=0;
2733   while (my $data=$sth->fetchrow_hashref){
2734     $results[$i]=$data;
2735     $i++;
2736   }
2737   $sth->finish;
2738   return($i,\@results);
2739 }
2740
2741
2742 =head2 getwebsites
2743
2744   ($count, @websites) = &getwebsites($biblionumber);
2745
2746 Looks up the web sites pertaining to the book with the given
2747 biblionumber.
2748
2749 C<$count> is the number of elements in C<@websites>.
2750
2751 C<@websites> is an array of references-to-hash; the keys are the
2752 fields from the C<websites> table in the Koha database.
2753
2754 =cut
2755 #FIXME : could maybe be deleted. Otherwise, would be better in a Websites.pm package
2756 #(with add / modify / delete subs)
2757
2758 sub getwebsites {
2759     my ($biblionumber) = @_;
2760     my $dbh   = C4::Context->dbh;
2761     my $sth   = $dbh->prepare("Select * from websites where biblionumber = ?");
2762     my $count = 0;
2763     my @results;
2764
2765     $sth->execute($biblionumber);
2766     while (my $data = $sth->fetchrow_hashref) {
2767         # FIXME - The URL scheme shouldn't be stripped off, at least
2768         # not here, since it's part of the URL, and will be useful in
2769         # constructing a link to the site. If you don't want the user
2770         # to see the "http://" part, strip that off when building the
2771         # HTML code.
2772         $data->{'url'} =~ s/^http:\/\///;       # FIXME - Leaning toothpick
2773                                                 # syndrome
2774         $results[$count] = $data;
2775         $count++;
2776     } # while
2777
2778     $sth->finish;
2779     return($count, @results);
2780 } # sub getwebsites
2781
2782 =head2 getwebbiblioitems
2783
2784   ($count, @results) = &getwebbiblioitems($biblionumber);
2785
2786 Given a book's biblionumber, looks up the web versions of the book
2787 (biblioitems with itemtype C<WEB>).
2788
2789 C<$count> is the number of items in C<@results>. C<@results> is an
2790 array of references-to-hash; the keys are the items from the
2791 C<biblioitems> table of the Koha database.
2792
2793 =cut
2794 #'
2795 sub getwebbiblioitems {
2796     my ($biblionumber) = @_;
2797     my $dbh   = C4::Context->dbh;
2798     my $sth   = $dbh->prepare("Select * from biblioitems where biblionumber = ?
2799 and itemtype = 'WEB'");
2800     my $count = 0;
2801     my @results;
2802
2803     $sth->execute($biblionumber);
2804     while (my $data = $sth->fetchrow_hashref) {
2805         $data->{'url'} =~ s/^http:\/\///;
2806         $results[$count] = $data;
2807         $count++;
2808     } # while
2809
2810     $sth->finish;
2811     return($count, @results);
2812 } # sub getwebbiblioitems
2813
2814 sub nsb_clean {
2815     my $NSB = '\x88';    # NSB : begin Non Sorting Block
2816     my $NSE = '\x89';    # NSE : Non Sorting Block end
2817                          # handles non sorting blocks
2818     my ($string) = @_;
2819     $_ = $string;
2820     s/$NSB/(/gm;
2821     s/[ ]{0,1}$NSE/) /gm;
2822     $string = $_;
2823     return ($string);
2824 }
2825
2826 sub FindDuplicate {
2827         my ($record)=@_;
2828         my $dbh = C4::Context->dbh;
2829         my $result = MARCmarc2koha($dbh,$record,'');
2830         my $sth;
2831         my ($biblionumber,$bibid,$title);
2832         # search duplicate on ISBN, easy and fast...
2833         if ($result->{isbn}) {
2834                 $sth = $dbh->prepare("select biblio.biblionumber,bibid,title from biblio,biblioitems,marc_biblio where biblio.biblionumber=biblioitems.biblionumber and marc_biblio.biblionumber=biblioitems.biblionumber and isbn=?");
2835                 $sth->execute($result->{'isbn'});
2836                 ($biblionumber,$bibid,$title) = $sth->fetchrow;
2837                 return $biblionumber,$bibid,$title if ($biblionumber);
2838         }
2839         # a more complex search : build a request for SearchMarc::catalogsearch()
2840         my (@tags, @and_or, @excluding, @operator, @value, $offset,$length);
2841         # search on biblio.title
2842         my ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblio.title","");
2843         if ($record->field($tag)) {
2844                 if ($record->field($tag)->subfields($subfield)) {
2845                         push @tags, "'".$tag.$subfield."'";
2846                         push @and_or, "and";
2847                         push @excluding, "";
2848                         push @operator, "contains";
2849                         push @value, $record->field($tag)->subfield($subfield);
2850 #                       warn "for title, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
2851                 }
2852         }
2853         # ... and on biblio.author
2854         ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblio.author","");
2855         if ($record->field($tag)) {
2856                 if ($record->field($tag)->subfields($subfield)) {
2857                         push @tags, "'".$tag.$subfield."'";
2858                         push @and_or, "and";
2859                         push @excluding, "";
2860                         push @operator, "contains";
2861                         push @value, $record->field($tag)->subfield($subfield);
2862 #                       warn "for author, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
2863                 }
2864         }
2865         # ... and on publicationyear.
2866         ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblioitems.publicationyear","");
2867         if ($record->field($tag)) {
2868                 if ($record->field($tag)->subfields($subfield)) {
2869                         push @tags, "'".$tag.$subfield."'";
2870                         push @and_or, "and";
2871                         push @excluding, "";
2872                         push @operator, "=";
2873                         push @value, $record->field($tag)->subfield($subfield);
2874 #                       warn "for publicationyear, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
2875                 }
2876         }
2877         # ... and on size.
2878         ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblioitems.size","");
2879         if ($record->field($tag)) {
2880                 if ($record->field($tag)->subfields($subfield)) {
2881                         push @tags, "'".$tag.$subfield."'";
2882                         push @and_or, "and";
2883                         push @excluding, "";
2884                         push @operator, "=";
2885                         push @value, $record->field($tag)->subfield($subfield);
2886 #                       warn "for size, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
2887                 }
2888         }
2889         # ... and on publisher.
2890         ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblioitems.publishercode","");
2891         if ($record->field($tag)) {
2892                 if ($record->field($tag)->subfields($subfield)) {
2893                         push @tags, "'".$tag.$subfield."'";
2894                         push @and_or, "and";
2895                         push @excluding, "";
2896                         push @operator, "=";
2897                         push @value, $record->field($tag)->subfield($subfield);
2898 #                       warn "for publishercode, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
2899                 }
2900         }
2901         # ... and on volume.
2902         ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblioitems.volume","");
2903         if ($record->field($tag)) {
2904                 if ($record->field($tag)->subfields($subfield)) {
2905                         push @tags, "'".$tag.$subfield."'";
2906                         push @and_or, "and";
2907                         push @excluding, "";
2908                         push @operator, "=";
2909                         push @value, $record->field($tag)->subfield($subfield);
2910 #                       warn "for volume, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
2911                 }
2912         }
2913
2914         my ($finalresult,$nbresult) = C4::SearchMarc::catalogsearch($dbh,\@tags,\@and_or,\@excluding,\@operator,\@value,0,10);
2915         # there is at least 1 result => return the 1st one
2916         if ($nbresult) {
2917 #               warn "$nbresult => ".@$finalresult[0]->{biblionumber},@$finalresult[0]->{bibid},@$finalresult[0]->{title};
2918                 return @$finalresult[0]->{biblionumber},@$finalresult[0]->{bibid},@$finalresult[0]->{title};
2919         }
2920         # no result, returns nothing
2921         return;
2922 }
2923
2924 sub DisplayISBN {
2925         my ($isbn)=@_;
2926         my $seg1;
2927         if(substr($isbn, 0, 1) <=7) {
2928                 $seg1 = substr($isbn, 0, 1);
2929         } elsif(substr($isbn, 0, 2) <= 94) {
2930                 $seg1 = substr($isbn, 0, 2);
2931         } elsif(substr($isbn, 0, 3) <= 995) {
2932                 $seg1 = substr($isbn, 0, 3);
2933         } elsif(substr($isbn, 0, 4) <= 9989) {
2934                 $seg1 = substr($isbn, 0, 4);
2935         } else {
2936                 $seg1 = substr($isbn, 0, 5);
2937         }
2938         my $x = substr($isbn, length($seg1));
2939         my $seg2;
2940         if(substr($x, 0, 2) <= 19) {
2941 #               if(sTmp2 < 10) sTmp2 = "0" sTmp2;
2942                 $seg2 = substr($x, 0, 2);
2943         } elsif(substr($x, 0, 3) <= 699) {
2944                 $seg2 = substr($x, 0, 3);
2945         } elsif(substr($x, 0, 4) <= 8399) {
2946                 $seg2 = substr($x, 0, 4);
2947         } elsif(substr($x, 0, 5) <= 89999) {
2948                 $seg2 = substr($x, 0, 5);
2949         } elsif(substr($x, 0, 6) <= 9499999) {
2950                 $seg2 = substr($x, 0, 6);
2951         } else {
2952                 $seg2 = substr($x, 0, 7);
2953         }
2954         my $seg3=substr($x,length($seg2));
2955         $seg3=substr($seg3,0,length($seg3)-1) ;
2956         my $seg4 = substr($x, -1, 1);
2957         return "$seg1-$seg2-$seg3-$seg4";
2958 }
2959
2960
2961 END { }    # module clean-up code here (global destructor)
2962
2963 =back
2964
2965 =head1 AUTHOR
2966
2967 Koha Developement team <info@koha.org>
2968
2969 Paul POULAIN paul.poulain@free.fr
2970
2971 =cut
2972
2973 # $Id$
2974 # $Log$
2975 # Revision 1.153  2006/02/25 22:39:10  kados
2976 # Another purely documentation commit. Just changing formatting to ease
2977 # readability.
2978 #
2979 # Revision 1.152  2006/02/25 21:17:20  kados
2980 # Purely documentation change: converted all =head2 entries to use function
2981 # name as title rather than usage as title
2982 #
2983 # Revision 1.151  2006/02/25 21:02:20  kados
2984 #
2985 # Further cleanup, convering new routines to 4-chars
2986 #
2987 # Revision 1.150  2006/02/25 20:49:15  kados
2988 # Better documentation, added warning if serviceType is 'drop' since it's
2989 # not supported in Zebra.
2990 #
2991 # Revision 1.149  2006/02/25 20:30:32  kados
2992 # IMPORTANT: Paul, I've removed the decode_char routine because it's no
2993 # longer necessary. If we need to convert from MARC-8 for display, we should:
2994 #
2995 # 1. use utf-8
2996 # 2. do it with MARC::Charset
2997 #
2998 # If you still need it, let me know and I'll put it back in.
2999 #
3000 # Revision 1.148  2006/02/25 19:23:01  kados
3001 # cleaning up POD docs, deleting zebra_create as it's no longer used (
3002 # replaced by z3950_extended_services).
3003 #
3004 # Revision 1.147  2006/02/25 19:09:59  kados
3005 # readding some lost subs
3006 #
3007 # Revision 1.145  2006/02/22 01:02:39  kados
3008 # Replacing all calls to zebra_update with calls to
3009 # z3950_extended_services. More work coming, but it's
3010 # working now.
3011 #
3012 # Revision 1.144  2006/02/20 14:22:38  kados
3013 # typo
3014 #
3015 # Revision 1.143  2006/02/20 13:26:11  kados
3016 # A new subroutine to handle Z39.50 extended services. You pass it a
3017 # connection object, service type, service options, and a record, and
3018 # it performs the service and handles any exception found.
3019 #
3020 # Revision 1.142  2006/02/16 20:49:56  kados
3021 # destroy a connection after we're done -- we really should just have one
3022 # connection object and not destroy it until the whole transaction is
3023 # finished -- but this will do for now
3024 #
3025 # Revision 1.141  2006/02/16 19:47:22  rangi
3026 # Trying to error trap a little more.
3027 #
3028 # Revision 1.140  2006/02/14 21:36:03  kados
3029 # adding a 'use ZOOM' to biblio.pm, needed for non-mod_perl install.
3030 # also adding diagnostic error if not able to connect to Zebra
3031 #
3032 # Revision 1.139  2006/02/14 19:53:25  rangi
3033 # Just a little missing my
3034 #
3035 # Seems to be working great Paul, and I like what you did with zebradb
3036 #
3037 # Revision 1.138  2006/02/14 11:25:22  tipaul
3038 # road to 3.0 : updating a biblio in zebra seems to work. Still working on it, there are probably some bugs !
3039 #
3040 # Revision 1.137  2006/02/13 16:34:26  tipaul
3041 # fixing some warnings (perl -w should be quiet)
3042 #
3043 # Revision 1.136  2006/01/10 17:01:29  tipaul
3044 # adding a XMLgetbiblio in Biblio.pm (1st draft, to use with zebra)
3045 #
3046 # Revision 1.135  2006/01/06 16:39:37  tipaul
3047 # synch'ing head and rel_2_2 (from 2.2.5, including npl templates)
3048 # Seems not to break too many things, but i'm probably wrong here.
3049 # at least, new features/bugfixes from 2.2.5 are here (tested on some features on my head local copy)
3050 #
3051 # - removing useless directories (koha-html and koha-plucene)
3052 #
3053 # Revision 1.134  2006/01/04 15:54:55  tipaul
3054 # utf8 is a : go for beta test in HEAD.
3055 # some explanations :
3056 # - updater/updatedatabase => will transform all tables in innoDB (not related to utf8, just to warn you) AND collate them in utf8 / utf8_general_ci. The SQL command is : ALTER TABLE tablename DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci.
3057 # - *-top.inc will show the pages in utf8
3058 # - THE HARD THING : for me, mysql-client and mysql-server were set up to communicate in iso8859-1, whatever the mysql collation ! Thus, pages were improperly shown, as datas were transmitted in iso8859-1 format ! After a full day of investigation, someone on usenet pointed "set NAMES 'utf8'" to explain that I wanted utf8. I could put this in my.cnf, but if I do that, ALL databases will "speak" in utf8, that's not what we want. Thus, I added a line in Context.pm : everytime a DB handle is opened, the communication is set to utf8.
3059 # - using marcxml field and no more the iso2709 raw marc biblioitems.marc field.
3060 #
3061 # Revision 1.133  2005/12/12 14:25:51  thd
3062 #
3063 #
3064 # Reverse array filled with elements from repeated subfields
3065 # to avoid last to first concatenation of elements in Koha DB.-
3066 #
3067 # Revision 1.132  2005-10-26 09:12:33  tipaul
3068 # big commit, still breaking things...
3069 #
3070 # * synch with rel_2_2. Probably the last non manual synch, as rel_2_2 should not be modified deeply.
3071 # * code cleaning (cleaning warnings from perl -w) continued
3072 #
3073 # Revision 1.131  2005/09/22 10:01:45  tipaul
3074 # see mail on koha-devel : code cleaning on Search.pm + normalizing API + use of biblionumber everywhere (instead of bn, biblio, ...)
3075 #
3076 # Revision 1.130  2005/09/02 14:34:14  tipaul
3077 # continuing the work to move to zebra. Begin of work for MARC=OFF support.
3078 # IMPORTANT NOTE : the MARCkoha2marc sub API has been modified. Instead of biblionumber & biblioitemnumber, it now gets a hash.
3079 # The sub is used only in Biblio.pm, so the API change should be harmless (except for me, but i'm aware ;-) )
3080 #
3081 # Revision 1.129  2005/08/12 13:50:31  tipaul
3082 # removing useless sub declarations
3083 #
3084 # Revision 1.128  2005/08/11 16:12:47  tipaul
3085 # Playing with the zebra...
3086 #
3087 # * go to koha cvs home directory
3088 # * in misc/zebra there is a unimarc directory. I suggest that marc21 libraries create a marc21 directory
3089 # * put your zebra.cfg files here & create your database.
3090 # * from koha cvs home directory, ln -s misc/zebra/marc21 zebra (I mean create a symbolic link to YOUR zebra directory)
3091 # * now, everytime you add/modify a biblio/item your zebra DB is updated correctly.
3092 #
3093 # NOTE :
3094 # * this uses a system call in perl. CPU consumming, but we are waiting for indexdata Perl/zoom
3095 # * deletion still not work
3096 # * UNIMARC zebra config files are provided in misc/zebra/unimarc directory. The most important line being :
3097 # in zebra.cfg :
3098 # recordId: (bib1,Local-number)
3099 # storeKeys:1
3100 #
3101 # in .abs file :
3102 # elm 090            Local-number            -
3103 # elm 090/?          Local-number            -
3104 # elm 090/?/9        Local-number            !:w
3105 #
3106 # (090$9 being the field mapped to biblio.biblionumber in Koha)
3107 #
3108 # Revision 1.127  2005/08/11 14:37:32  tipaul
3109 # * POD documenting
3110 # * removing useless subs
3111 # * removing some subs that are also elsewhere
3112 # * renaming all OLDxxx subs to REALxxx subs (should not change anything, as OLDxxx, as well as REAL, are supposed to be for Biblio.pm internal use only)
3113 #
3114 # Revision 1.126  2005/08/11 09:13:28  tipaul
3115 # just removing useless subs (a lot !!!) for code cleaning
3116 #
3117 # Revision 1.125  2005/08/11 09:00:07  tipaul
3118 # Ok guys, this time, it seems that item add and modif begin working as expected...
3119 # Still a lot of bugs to fix, of course
3120 #
3121 # Revision 1.124  2005/08/10 10:21:15  tipaul
3122 # continuing the road to zebra :
3123 # - the biblio add begins to work.
3124 # - the biblio modif begins to work.
3125 #
3126 # (still without doing anything on zebra)
3127 # (no new change in updatedatabase)
3128 #
3129 # Revision 1.123  2005/08/09 14:10:28  tipaul
3130 # 1st commit to go to zebra.
3131 # don't update your cvs if you want to have a working head...
3132 #
3133 # this commit contains :
3134 # * updater/updatedatabase : get rid with marc_* tables, but DON'T remove them. As a lot of things uses them, it would not be a good idea for instance to drop them. If you really want to play, you can rename them to test head without them but being still able to reintroduce them...
3135 # * Biblio.pm : modify MARCgetbiblio to find the raw marc record in biblioitems.marc field, not from marc_subfield_table, modify MARCfindframeworkcode to find frameworkcode in biblio.frameworkcode, modify some other subs to use biblio.biblionumber & get rid of bibid.
3136 # * other files : get rid of bibid and use biblionumber instead.
3137 #
3138 # What is broken :
3139 # * does not do anything on zebra yet.
3140 # * if you rename marc_subfield_table, you can't search anymore.
3141 # * you can view a biblio & bibliodetails, go to MARC editor, but NOT save any modif.
3142 # * don't try to add a biblio, it would add data poorly... (don't try to delete either, it may work, but that would be a surprise ;-) )
3143 #
3144 # IMPORTANT NOTE : you need MARC::XML package (http://search.cpan.org/~esummers/MARC-XML-0.7/lib/MARC/File/XML.pm), that requires a recent version of MARC::Record
3145 # Updatedatabase stores the iso2709 data in biblioitems.marc field & an xml version in biblioitems.marcxml Not sure we will keep it when releasing the stable version, but I think it's a good idea to have something readable in sql, at least for development stage.
3146
3147 # tipaul cutted previous commit notes