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