3 # Copyright 2000-2002 Katipo Communications
5 # This file is part of Koha.
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
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.
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
26 use MARC::File::USMARC;
30 use vars qw($VERSION @ISA @EXPORT);
32 # set the version for version checking
33 $VERSION = do { my @v = '$Revision$' =~ /\d+/g;
34 shift(@v) . "." . join("_", map {sprintf "%03d", $_ } @v); };
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.
43 &newbiblio &newbiblioitem
44 &newsubject &newsubtitle &newitems
46 &modbiblio &checkitems &modbibitem
47 &modsubtitle &modsubject &modaddauthor &moditem
49 &delitem &deletebiblioitem &delbiblio
51 &getbiblio &bibdata &bibitems &bibitemdata
52 &barcodes &ItemInfo &itemdata &itemissues &itemcount
53 &getsubject &getaddauthor &getsubtitle
54 &getwebbiblioitems &getwebsites
55 &getbiblioitembybiblionumber
56 &getbiblioitem &getitemsbybiblioitem
58 &MARCfind_marc_from_kohafield
59 &MARCfind_frameworkcode
60 &find_biblioitemnumber
63 &NEWnewbiblio &NEWnewitem
64 &NEWmodbiblio &NEWmoditem
65 &NEWdelbiblio &NEWdelitem
66 &NEWmodbiblioframework
68 &MARCkoha2marcBiblio &MARCmarc2koha
69 &MARCkoha2marcItem &MARChtml2marc
70 &MARCgetbiblio &MARCgetitem
76 &z3950_extended_services
79 &get_item_from_barcode
80 &MARCfind_MARCbibid_from_oldbiblionumber
86 C4::Biblio - Acquisitions, Catalog Management Functions
90 ( lot of changes for Koha 3.X)
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).
96 In Koha 2.X, we introduced a MARC-DB.
98 In Koha 3.X, we removed this MARC-DB for search as we wanted to use Zebra as search system.
100 So in Koha 3.X, saving a record means :
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.
106 In Koha, there is a systempreference for "MARC=ON" or "MARC=OFF" :
108 * MARC=ON : when MARC=ON, Koha uses a MARC::Record object (in sub parameters). Saving information in the DB means :
110 - transform the MARC record into a hash
111 - add the raw MARC record into the hash
112 - store them & update Zebra
114 * MARC=OFF : when MARC=OFF, Koha uses a hash object (in sub parameters). Saving information in the DB means :
116 - transform the hash into a MARC record
117 - add the raw marc record into the hash
118 - store them & update zebra
120 That's why we need 3 types of subs :
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).
126 =head2 NEWxxx related subs
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.
132 all subs requires/use $dbh as 1st parameter and a MARC::Record object as 2nd parameter. They sometimes require another parameter.
136 =head2 something_elsexxx related subs
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.
142 all subs require/use $dbh as 1st parameter and a hash as 2nd parameter.
154 =head2 z3950_extended_services
156 z3950_extended_services($Zconn,$serviceType,$serviceOptions,$record);
158 z3950_extended_services is used to handle all interactions with Zebra's extended serices package.
160 C<$Zconn> a connection object to the Zebra server
162 C<$serviceType> one of: itemorder,create,drop,commit,update,xmlupdate
164 C<$serviceOptions> a has of key/value pairs. For instance, if service_type is 'update', $service_options should contain:
166 action => update action, one of specialUpdate, recordInsert, recordReplace, recordDelete, elementUpdate.
170 recordidOpaque => Opaque Record ID (user supplied) or recordidNumber => Record ID number (system number).
171 syntax => the record syntax (transfer syntax)
172 databaseName = Database from connection object
174 To set serviceOptions, call set_service_options($serviceType)
176 C<$record> the record, if one is needed for the service type
178 A record should be in XML. You can convert it to XML from MARC by running it through marc2xml().
181 sub z3950_extended_services {
182 my ($Zconn,$serviceType,$serviceOptions,$record) = @_;
184 # create a new package object
185 my $Zpackage = $Zconn->package();
188 $Zpackage->option(action => $serviceOptions->{'action'});
190 if ($serviceOptions->{'databaseName'}) {
191 $Zpackage->option(databaseName => $serviceOptions->{'databaseName'});
193 if ($serviceOptions->{'recordIdNumber'}) {
194 $Zpackage->option(recordIdNumber => $serviceOptions->{'recordIdNumber'});
196 if ($serviceOptions->{'recordIdOpaque'}) {
197 $Zpackage->option(recordIdOpaque => $serviceOptions->{'recordIdOpaque'});
200 # this is an ILL request (Zebra doesn't support it)
201 if ($serviceType eq 'itemorder') {
202 $Zpackage->option('contact-name' => $serviceOptions->{'contact-name'});
203 $Zpackage->option('contact-phone' => $serviceOptions->{'contact-phone'});
204 $Zpackage->option('contact-email' => $serviceOptions->{'contact-email'});
205 $Zpackage->option('itemorder-item' => $serviceOptions->{'itemorder-item'});
209 my $xmlrecord = marc2xml($record);
210 $Zpackage->option(record => $xmlrecord);
211 if ($serviceOptions->{'syntax'}) {
212 $Zpackage->option(syntax => $serviceOptions->{'syntax'});
216 # send the request, handle any exception encountered
217 eval { $Zpackage->send($serviceType) };
218 if ($@ && $@->isa("ZOOM::Exception")) {
219 print "Oops! ", $@->message(), "\n";
222 # free up package resources
223 $Zpackage->destroy();
236 $xmlrecord=$record->as_xml();
239 warn "ERROR badly formatted marc record";
240 warn "Skipping record";
244 sub set_service_options {
247 if ($option eq 'update') {
248 $serviceOptions->{ 'action' } = 'specialUpdate';
249 $serviceOptions->{ 'syntax' } = 'xml'; #zebra doesn't support others
251 if ($option eq 'commit') {
255 return $serviceOptions;
259 =head2 @tagslib = &MARCgettagslib($dbh,1|0,$frameworkcode);
263 2nd param is 1 for liblibrarian and 0 for libopac
264 $frameworkcode contains the framework reference. If empty or does not exist, the default one is used
266 returns a hash with all values for all fields and subfields for a given MARC framework :
267 $res->{$tag}->{lib} = ($forlibrarian or !$libopac)?$liblibrarian:$libopac;
269 ->{mandatory} = $mandatory;
270 ->{repeatable} = $repeatable;
271 ->{$subfield}->{lib} = ($forlibrarian or !$libopac)?$liblibrarian:$libopac;
273 ->{mandatory} = $mandatory;
274 ->{repeatable} = $repeatable;
275 ->{authorised_value} = $authorised_value;
276 ->{authtypecode} = $authtypecode;
277 ->{value_builder} = $value_builder;
278 ->{kohafield} = $kohafield;
279 ->{seealso} = $seealso;
280 ->{hidden} = $hidden;
289 my ( $dbh, $forlibrarian, $frameworkcode ) = @_;
290 $frameworkcode = "" unless $frameworkcode;
291 $forlibrarian = 1 unless $forlibrarian;
293 my $libfield = ( $forlibrarian eq 1 ) ? 'liblibrarian' : 'libopac';
295 # check that framework exists
298 "select count(*) from marc_tag_structure where frameworkcode=?");
299 $sth->execute($frameworkcode);
300 my ($total) = $sth->fetchrow;
301 $frameworkcode = "" unless ( $total > 0 );
304 "select tagfield,liblibrarian,libopac,mandatory,repeatable from marc_tag_structure where frameworkcode=? order by tagfield"
306 $sth->execute($frameworkcode);
307 my ( $liblibrarian, $libopac, $tag, $res, $tab, $mandatory, $repeatable );
309 while ( ( $tag, $liblibrarian, $libopac, $mandatory, $repeatable ) = $sth->fetchrow ) {
310 $res->{$tag}->{lib} = ($forlibrarian or !$libopac)?$liblibrarian:$libopac;
311 $res->{$tag}->{tab} = ""; # XXX
312 $res->{$tag}->{mandatory} = $mandatory;
313 $res->{$tag}->{repeatable} = $repeatable;
318 "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"
320 $sth->execute($frameworkcode);
323 my $authorised_value;
333 ( $tag, $subfield, $liblibrarian, , $libopac, $tab,
334 $mandatory, $repeatable, $authorised_value, $authtypecode,
335 $value_builder, $kohafield, $seealso, $hidden,
340 $res->{$tag}->{$subfield}->{lib} = ($forlibrarian or !$libopac)?$liblibrarian:$libopac;
341 $res->{$tag}->{$subfield}->{tab} = $tab;
342 $res->{$tag}->{$subfield}->{mandatory} = $mandatory;
343 $res->{$tag}->{$subfield}->{repeatable} = $repeatable;
344 $res->{$tag}->{$subfield}->{authorised_value} = $authorised_value;
345 $res->{$tag}->{$subfield}->{authtypecode} = $authtypecode;
346 $res->{$tag}->{$subfield}->{value_builder} = $value_builder;
347 $res->{$tag}->{$subfield}->{kohafield} = $kohafield;
348 $res->{$tag}->{$subfield}->{seealso} = $seealso;
349 $res->{$tag}->{$subfield}->{hidden} = $hidden;
350 $res->{$tag}->{$subfield}->{isurl} = $isurl;
351 $res->{$tag}->{$subfield}->{link} = $link;
356 =head2 ($tagfield,$tagsubfield) = &MARCfind_marc_from_kohafield($dbh,$kohafield);
360 finds MARC tag and subfield for a given kohafield
361 kohafield is "table.field" where table= biblio|biblioitems|items, and field a field of the previous table
367 sub MARCfind_marc_from_kohafield {
368 my ( $dbh, $kohafield,$frameworkcode ) = @_;
369 return 0, 0 unless $kohafield;
370 $frameworkcode='' unless $frameworkcode;
371 my $relations = C4::Context->marcfromkohafield;
372 return ($relations->{$frameworkcode}->{$kohafield}->[0],$relations->{$frameworkcode}->{$kohafield}->[1]);
375 =head2 $MARCRecord = &MARCgetbiblio($dbh,$biblionumber);
379 Returns a MARC::Record for the biblio $biblionumber.
385 # Returns MARC::Record of the biblio passed in parameter.
386 my ( $dbh, $biblionumber ) = @_;
387 my $sth = $dbh->prepare('select marc from biblioitems where biblionumber=?');
388 $sth->execute($biblionumber);
389 my ($marc) = $sth->fetchrow;
390 my $record = MARC::Record::new_from_usmarc($marc);
394 =head2 $XML = &XMLgetbiblio($dbh,$biblionumber);
398 Returns a raw XML for the biblio $biblionumber.
404 # Returns MARC::Record of the biblio passed in parameter.
405 my ( $dbh, $biblionumber ) = @_;
406 my $sth = $dbh->prepare('select marcxml,marc from biblioitems where biblionumber=?');
407 $sth->execute($biblionumber);
408 my ($XML,$marc) = $sth->fetchrow;
409 # my $record =MARC::Record::new_from_usmarc($marc);
410 # warn "MARC : \n*-************************\n".$record->as_xml."\n*-************************\n";
414 =head2 $MARCrecord = &MARCgetitem($dbh,$biblionumber);
418 Returns a MARC::Record with all items of biblio # $biblionumber
426 my ( $dbh, $biblionumber, $itemnumber ) = @_;
427 my $frameworkcode=MARCfind_frameworkcode($dbh,$biblionumber);
428 # get the complete MARC record
429 my $sth = $dbh->prepare("select marc from biblioitems where biblionumber=?");
430 $sth->execute($biblionumber);
431 my ($rawmarc) = $sth->fetchrow;
432 my $record = MARC::File::USMARC::decode($rawmarc);
433 # now, find the relevant itemnumber
434 my ($itemnumberfield,$itemnumbersubfield) = MARCfind_marc_from_kohafield($dbh,'items.itemnumber',$frameworkcode);
435 # prepare the new item record
436 my $itemrecord = MARC::Record->new();
437 # parse all fields fields from the complete record
438 foreach ($record->field($itemnumberfield)) {
439 # when the item field is found, save it
440 if ($_->subfield($itemnumbersubfield) == $itemnumber) {
441 $itemrecord->append_fields($_);
448 =head2 sub find_biblioitemnumber($dbh,$biblionumber);
452 Returns the 1st biblioitemnumber related to $biblionumber. When MARC=ON we should have 1 biblionumber = 1 and only 1 biblioitemnumber
453 This sub is useless when MARC=OFF
458 sub find_biblioitemnumber {
459 my ( $dbh, $biblionumber ) = @_;
460 my $sth = $dbh->prepare("select biblioitemnumber from biblioitems where biblionumber=?");
461 $sth->execute($biblionumber);
462 my ($biblioitemnumber) = $sth->fetchrow;
463 return $biblioitemnumber;
466 =head2 $frameworkcode = MARCfind_frameworkcode($dbh,$biblionumber);
470 returns the framework of a given biblio
476 sub MARCfind_frameworkcode {
477 my ( $dbh, $biblionumber ) = @_;
478 my $sth = $dbh->prepare("select frameworkcode from biblio where biblionumber=?");
479 $sth->execute($biblionumber);
480 my ($frameworkcode) = $sth->fetchrow;
481 return $frameworkcode;
484 =head2 $MARCRecord = &MARCkoha2marcBiblio($dbh,$bibliohash);
488 MARCkoha2marcBiblio is a wrapper between old-DB and MARC-DB. It returns a MARC::Record builded with old-DB biblio/biblioitem :
489 all entries of the hash are transformed into their matching MARC field/subfield.
495 sub MARCkoha2marcBiblio {
497 # this function builds partial MARC::Record from the old koha-DB fields
498 my ( $dbh, $bibliohash ) = @_;
499 # we don't have biblio entries in the hash, so we add them first
500 my $sth = $dbh->prepare("select * from biblio where biblionumber=?");
501 $sth->execute($bibliohash->{biblionumber});
502 my $biblio = $sth->fetchrow_hashref;
503 foreach (keys %$biblio) {
504 $bibliohash->{$_}=$biblio->{$_};
506 $sth = $dbh->prepare("select tagfield,tagsubfield from marc_subfield_structure where frameworkcode=? and kohafield=?");
507 my $record = MARC::Record->new();
508 foreach ( keys %$bibliohash ) {
509 &MARCkoha2marcOnefield( $sth, $record, "biblio." . $_, $bibliohash->{$_}, '') if $bibliohash->{$_};
510 &MARCkoha2marcOnefield( $sth, $record, "biblioitems." . $_, $bibliohash->{$_}, '') if $bibliohash->{$_};
513 # other fields => additional authors, subjects, subtitles
514 my $sth2 = $dbh->prepare(" SELECT author FROM additionalauthors WHERE biblionumber=?");
515 $sth2->execute($bibliohash->{biblionumber});
516 while ( my $row = $sth2->fetchrow_hashref ) {
517 &MARCkoha2marcOnefield( $sth, $record, "additionalauthors.author", $bibliohash->{'author'},'' );
519 $sth2 = $dbh->prepare(" SELECT subject FROM bibliosubject WHERE biblionumber=?");
520 $sth2->execute($bibliohash->{biblionumber});
521 while ( my $row = $sth2->fetchrow_hashref ) {
522 &MARCkoha2marcOnefield( $sth, $record, "bibliosubject.subject", $row->{'subject'},'' );
524 $sth2 = $dbh->prepare(" SELECT subtitle FROM bibliosubtitle WHERE biblionumber=?");
525 $sth2->execute($bibliohash->{biblionumber});
526 while ( my $row = $sth2->fetchrow_hashref ) {
527 &MARCkoha2marcOnefield( $sth, $record, "bibliosubtitle.subtitle", $row->{'subtitle'},'' );
533 =head2 $MARCRecord = &MARCkoha2marcItem($dbh,$biblionumber,itemnumber);
535 MARCkoha2marcItem is a wrapper between old-DB and MARC-DB. It returns a MARC::Record builded with old-DB items :
536 all entries of the hash are transformed into their matching MARC field/subfield.
544 sub MARCkoha2marcItem {
546 # this function builds partial MARC::Record from the old koha-DB fields
547 my ( $dbh, $item ) = @_;
549 # my $dbh=&C4Connect;
550 my $sth = $dbh->prepare("select tagfield,tagsubfield from marc_subfield_structure where frameworkcode=? and kohafield=?");
551 my $record = MARC::Record->new();
553 foreach( keys %$item ) {
555 &MARCkoha2marcOnefield( $sth, $record, "items." . $_,
562 =head2 MARCkoha2marcOnefield
566 This sub is for internal use only, used by koha2marcBiblio & koha2marcItem
572 sub MARCkoha2marcOnefield {
573 my ( $sth, $record, $kohafieldname, $value,$frameworkcode ) = @_;
576 $sth->execute($frameworkcode,$kohafieldname);
577 if ( ( $tagfield, $tagsubfield ) = $sth->fetchrow ) {
578 if ( $record->field($tagfield) ) {
579 my $tag = $record->field($tagfield);
581 $tag->add_subfields( $tagsubfield, $value );
582 $record->delete_field($tag);
583 $record->add_fields($tag);
587 $record->add_fields( $tagfield, " ", " ", $tagsubfield => $value );
593 =head2 $MARCrecord = MARChtml2marc($dbh,$rtags,$rsubfields,$rvalues,%indicators);
597 transforms the parameters (coming from HTML form) into a MARC::Record
598 parameters with r are references to arrays.
600 FIXME : should be improved for 3.0, to avoid having 4 differents arrays
607 my ($dbh,$rtags,$rsubfields,$rvalues,%indicators) = @_;
609 my $record = MARC::Record->new();
610 # my %subfieldlist=();
611 my $prevvalue; # if tag <10
612 my $field; # if tag >=10
613 for (my $i=0; $i< @$rtags; $i++) {
614 next unless @$rvalues[$i];
615 # rebuild MARC::Record
616 # warn "0=>".@$rtags[$i].@$rsubfields[$i]." = ".@$rvalues[$i].": ";
617 if (@$rtags[$i] ne $prevtag) {
620 if ($prevtag ne '000') {
621 $record->add_fields((sprintf "%03s",$prevtag),$prevvalue);
623 $record->leader($prevvalue);
628 $record->add_fields($field);
631 $indicators{@$rtags[$i]}.=' ';
632 if (@$rtags[$i] <10) {
633 $prevvalue= @$rvalues[$i];
637 $field = MARC::Field->new( (sprintf "%03s",@$rtags[$i]), substr($indicators{@$rtags[$i]},0,1),substr($indicators{@$rtags[$i]},1,1), @$rsubfields[$i] => @$rvalues[$i]);
638 # warn "1=>".@$rtags[$i].@$rsubfields[$i]." = ".@$rvalues[$i].": ".$field->as_formatted;
640 $prevtag = @$rtags[$i];
642 if (@$rtags[$i] <10) {
643 $prevvalue=@$rvalues[$i];
645 if (length(@$rvalues[$i])>0) {
646 $field->add_subfields(@$rsubfields[$i] => @$rvalues[$i]);
647 # warn "2=>".@$rtags[$i].@$rsubfields[$i]." = ".@$rvalues[$i].": ".$field->as_formatted;
650 $prevtag= @$rtags[$i];
653 # the last has not been included inside the loop... do it now !
654 $record->add_fields($field) if $field;
655 # warn "HTML2MARC=".$record->as_formatted;
660 =head2 $hash = &MARCmarc2koha($dbh,$MARCRecord);
664 builds a hash with old-db datas from a MARC::Record
671 my ($dbh,$record,$frameworkcode) = @_;
672 my $sth=$dbh->prepare("select tagfield,tagsubfield from marc_subfield_structure where frameworkcode=? and kohafield=?");
674 my $sth2=$dbh->prepare("SHOW COLUMNS from biblio");
677 while (($field)=$sth2->fetchrow) {
678 # warn "biblio.".$field;
679 $result=&MARCmarc2kohaOneField($sth,"biblio",$field,$record,$result,$frameworkcode);
681 $sth2=$dbh->prepare("SHOW COLUMNS from biblioitems");
683 while (($field)=$sth2->fetchrow) {
684 if ($field eq 'notes') { $field = 'bnotes'; }
685 # warn "biblioitems".$field;
686 $result=&MARCmarc2kohaOneField($sth,"biblioitems",$field,$record,$result,$frameworkcode);
688 $sth2=$dbh->prepare("SHOW COLUMNS from items");
690 while (($field)=$sth2->fetchrow) {
691 # warn "items".$field;
692 $result=&MARCmarc2kohaOneField($sth,"items",$field,$record,$result,$frameworkcode);
694 # additional authors : specific
695 $result = &MARCmarc2kohaOneField($sth,"bibliosubtitle","subtitle",$record,$result,$frameworkcode);
696 $result = &MARCmarc2kohaOneField($sth,"additionalauthors","additionalauthors",$record,$result,$frameworkcode);
697 # modify copyrightdate to keep only the 1st year found
698 my $temp = $result->{'copyrightdate'};
700 $temp =~ m/c(\d\d\d\d)/; # search cYYYY first
702 $result->{'copyrightdate'} = $1;
703 } else { # if no cYYYY, get the 1st date.
704 $temp =~ m/(\d\d\d\d)/;
705 $result->{'copyrightdate'} = $1;
708 # modify publicationyear to keep only the 1st year found
709 $temp = $result->{'publicationyear'};
710 $temp =~ m/c(\d\d\d\d)/; # search cYYYY first
712 $result->{'publicationyear'} = $1;
713 } else { # if no cYYYY, get the 1st date.
714 $temp =~ m/(\d\d\d\d)/;
715 $result->{'publicationyear'} = $1;
720 sub MARCmarc2kohaOneField {
722 # FIXME ? if a field has a repeatable subfield that is used in old-db, only the 1st will be retrieved...
723 my ( $sth, $kohatable, $kohafield, $record, $result,$frameworkcode ) = @_;
724 # warn "kohatable / $kohafield / $result / ";
728 ( $tagfield, $subfield ) = MARCfind_marc_from_kohafield("",$kohatable.".".$kohafield,$frameworkcode);
729 foreach my $field ( $record->field($tagfield) ) {
730 if ($field->tag()<10) {
731 if ($result->{$kohafield}) {
732 # Reverse array filled with elements from repeated subfields
733 # from first to last to avoid last to first concatenation of
734 # elements in Koha DB. -- thd.
735 $result->{$kohafield} .= " | ".reverse($field->data());
737 $result->{$kohafield} = $field->data();
740 if ( $field->subfields ) {
741 my @subfields = $field->subfields();
742 foreach my $subfieldcount ( 0 .. $#subfields ) {
743 if ($subfields[$subfieldcount][0] eq $subfield) {
744 if ( $result->{$kohafield} ) {
745 $result->{$kohafield} .= " | " . $subfields[$subfieldcount][1];
748 $result->{$kohafield} = $subfields[$subfieldcount][1];
755 # warn "OneField for $kohatable.$kohafield and $frameworkcode=> $tagfield, $subfield";
759 =head2 ($biblionumber,$biblioitemnumber) = NEWnewbibilio($dbh,$MARCRecord,$frameworkcode);
763 creates a biblio from a MARC::Record.
770 my ( $dbh,$Zconn,$record,$frameworkcode ) = @_;
772 my $biblioitemnumber;
773 my $olddata = MARCmarc2koha( $dbh, $record,$frameworkcode );
774 $olddata->{frameworkcode} = $frameworkcode;
775 $biblionumber = REALnewbiblio( $dbh, $olddata );
776 $olddata->{biblionumber} = $biblionumber;
777 # add biblionumber into the MARC record (it's the ID for zebra)
778 my ( $tagfield, $tagsubfield ) =
779 MARCfind_marc_from_kohafield( $dbh, "biblio.biblionumber",$frameworkcode );
783 $newfield = MARC::Field->new(
784 $tagfield, $biblionumber,
787 $newfield = MARC::Field->new(
788 $tagfield, '', '', "$tagsubfield" => $biblionumber,
791 # drop old field (just in case it already exist and create new one...
792 my $old_field = $record->field($tagfield);
793 $record->delete_field($old_field);
794 $record->add_fields($newfield);
796 #create the marc entry, that stores the rax marc record in Koha 3.0
797 $olddata->{marc} = $record->as_usmarc();
798 $olddata->{marcxml} = $record->as_xml();
799 # and create biblioitem, that's all folks !
800 $biblioitemnumber = REALnewbiblioitem( $dbh, $Zconn, $olddata );
802 # search subtiles, addiauthors and subjects
803 ( $tagfield, $tagsubfield ) =
804 MARCfind_marc_from_kohafield( $dbh, "additionalauthors.author",$frameworkcode );
805 my @addiauthfields = $record->field($tagfield);
806 foreach my $addiauthfield (@addiauthfields) {
807 my @addiauthsubfields = $addiauthfield->subfield($tagsubfield);
808 foreach my $subfieldcount ( 0 .. $#addiauthsubfields ) {
809 REALmodaddauthor( $dbh, $biblionumber,
810 $addiauthsubfields[$subfieldcount] );
813 ( $tagfield, $tagsubfield ) =
814 MARCfind_marc_from_kohafield( $dbh, "bibliosubtitle.subtitle",$frameworkcode );
815 my @subtitlefields = $record->field($tagfield);
816 foreach my $subtitlefield (@subtitlefields) {
817 my @subtitlesubfields = $subtitlefield->subfield($tagsubfield);
818 foreach my $subfieldcount ( 0 .. $#subtitlesubfields ) {
819 REALnewsubtitle( $dbh, $biblionumber,
820 $subtitlesubfields[$subfieldcount] );
823 ( $tagfield, $tagsubfield ) =
824 MARCfind_marc_from_kohafield( $dbh, "bibliosubject.subject",$frameworkcode );
825 my @subj = $record->field($tagfield);
827 foreach my $subject (@subj) {
828 my @subjsubfield = $subject->subfield($tagsubfield);
829 foreach my $subfieldcount ( 0 .. $#subjsubfield ) {
830 push @subjects, $subjsubfield[$subfieldcount];
833 REALmodsubject( $dbh, $biblionumber, 1, @subjects );
834 return ( $biblionumber, $biblioitemnumber );
837 =head2 NEWmodbilbioframework($dbh,$biblionumber,$frameworkcode);
841 modify the framework of a biblio
847 sub NEWmodbiblioframework {
848 my ($dbh,$biblionumber,$frameworkcode) =@_;
849 my $sth = $dbh->prepare("Update biblio SET frameworkcode=? WHERE biblionumber=?");
850 $sth->execute($frameworkcode,$biblionumber);
854 =head2 NEWmodbiblio($dbh,$Zconn,$MARCrecord,$biblionumber,$frameworkcode);
858 modify a biblio (MARC=ON)
865 my ($dbh,$Zconn,$record,$biblionumber,$frameworkcode) =@_;
866 $frameworkcode="" unless $frameworkcode;
867 # &MARCmodbiblio($dbh,$bibid,$record,$frameworkcode,0);
868 my $oldbiblio = MARCmarc2koha($dbh,$record,$frameworkcode);
870 $oldbiblio->{frameworkcode} = $frameworkcode;
871 #create the marc entry, that stores the rax marc record in Koha 3.0
872 $oldbiblio->{biblionumber} = $biblionumber unless $oldbiblio->{biblionumber};
873 $oldbiblio->{marc} = $record->as_usmarc();
874 $oldbiblio->{marcxml} = $record->as_xml();
875 warn "dans NEWmodbiblio $biblionumber = ".$oldbiblio->{biblionumber}." = ".$oldbiblio->{marcxml};
876 REALmodbiblio($dbh,$oldbiblio);
877 REALmodbiblioitem($dbh,$Zconn,$oldbiblio);
878 # now, modify addi authors, subject, addititles.
879 my ($tagfield,$tagsubfield) = MARCfind_marc_from_kohafield($dbh,"additionalauthors.author",$frameworkcode);
880 my @addiauthfields = $record->field($tagfield);
881 foreach my $addiauthfield (@addiauthfields) {
882 my @addiauthsubfields = $addiauthfield->subfield($tagsubfield);
883 $dbh->do("delete from additionalauthors where biblionumber=$biblionumber");
884 foreach my $subfieldcount (0..$#addiauthsubfields) {
885 REALmodaddauthor($dbh,$biblionumber,$addiauthsubfields[$subfieldcount]);
888 ($tagfield,$tagsubfield) = MARCfind_marc_from_kohafield($dbh,"bibliosubtitle.subtitle",$frameworkcode);
889 my @subtitlefields = $record->field($tagfield);
890 foreach my $subtitlefield (@subtitlefields) {
891 my @subtitlesubfields = $subtitlefield->subfield($tagsubfield);
892 # delete & create subtitle again because REALmodsubtitle can't handle new subtitles
894 $dbh->do("delete from bibliosubtitle where biblionumber=$biblionumber");
895 foreach my $subfieldcount (0..$#subtitlesubfields) {
896 foreach my $subtit(split /\||#/,$subtitlesubfields[$subfieldcount]) {
897 REALnewsubtitle($dbh,$biblionumber,$subtit);
901 ($tagfield,$tagsubfield) = MARCfind_marc_from_kohafield($dbh,"bibliosubject.subject",$frameworkcode);
902 my @subj = $record->field($tagfield);
904 foreach my $subject (@subj) {
905 my @subjsubfield = $subject->subfield($tagsubfield);
906 foreach my $subfieldcount (0..$#subjsubfield) {
907 push @subjects,$subjsubfield[$subfieldcount];
910 REALmodsubject($dbh,$biblionumber,1,@subjects);
914 =head2 NEWmodbilbioframework($dbh,$biblionumber,$frameworkcode);
925 my ( $dbh, $bibid ) = @_;
926 my $biblio = &MARCfind_oldbiblionumber_from_MARCbibid( $dbh, $bibid );
927 &REALdelbiblio( $dbh, $biblio );
930 "select biblioitemnumber from biblioitems where biblionumber=?");
931 $sth->execute($biblio);
932 while ( my ($biblioitemnumber) = $sth->fetchrow ) {
933 REALdelbiblioitem( $dbh, $biblioitemnumber );
935 &MARCdelbiblio( $dbh, $bibid, 0 );
938 =head2 $itemnumber = NEWnewitem($dbh, $Zconn, $record, $biblionumber, $biblioitemnumber);
942 creates an item from a MARC::Record
949 my ( $dbh,$Zconn,$record,$biblionumber,$biblioitemnumber ) = @_;
952 my $frameworkcode=MARCfind_frameworkcode($dbh,$biblionumber);
953 my $item = &MARCmarc2koha( $dbh,$record,$frameworkcode );
954 # needs old biblionumber and biblioitemnumber
955 $item->{'biblionumber'} = $biblionumber;
956 $item->{'biblioitemnumber'}=$biblioitemnumber;
957 $item->{marc} = $record->as_usmarc();
959 my ( $itemnumber, $error ) = &REALnewitems( $dbh, $Zconn, $item, $item->{barcode} );
964 =head2 $itemnumber = NEWmoditem($dbh, $Zconn, $record, $biblionumber, $biblioitemnumber,$itemnumber);
975 my ( $dbh, $Zconn, $record, $biblionumber, $biblioitemnumber, $itemnumber) = @_;
977 my $frameworkcode=MARCfind_frameworkcode($dbh,$biblionumber);
978 my $olditem = MARCmarc2koha( $dbh, $record,$frameworkcode );
980 $olditem->{marc} = $record->as_usmarc();
981 $olditem->{biblionumber} = $biblionumber;
982 $olditem->{biblioitemnumber} = $biblioitemnumber;
984 REALmoditem( $dbh, $Zconn, $olditem );
988 =head2 $itemnumber = NEWdelitem($dbh, $biblionumber, $biblioitemnumber, $itemnumber);
999 my ( $dbh, $bibid, $itemnumber ) = @_;
1000 my $biblio = &MARCfind_oldbiblionumber_from_MARCbibid( $dbh, $bibid );
1001 &REALdelitem( $dbh, $itemnumber );
1002 &MARCdelitem( $dbh, $bibid, $itemnumber );
1006 =head2 $biblionumber = REALnewbiblio($dbh,$biblio);
1010 adds a record in biblio table. Datas are in the hash $biblio.
1017 my ( $dbh, $biblio ) = @_;
1019 $dbh->do('lock tables biblio WRITE');
1020 my $sth = $dbh->prepare("Select max(biblionumber) from biblio");
1022 my $data = $sth->fetchrow_arrayref;
1023 my $bibnum = $$data[0] + 1;
1026 if ( $biblio->{'seriestitle'} ) { $series = 1 }
1029 $dbh->prepare("insert into biblio set biblionumber=?, title=?, author=?, copyrightdate=?,
1030 serial=?, seriestitle=?, notes=?, abstract=?,
1034 $bibnum, $biblio->{'title'},
1035 $biblio->{'author'}, $biblio->{'copyrightdate'},
1036 $biblio->{'serial'}, $biblio->{'seriestitle'},
1037 $biblio->{'notes'}, $biblio->{'abstract'},
1038 $biblio->{'unititle'}
1042 $dbh->do('unlock tables');
1046 =head2 $biblionumber = REALmodbiblio($dbh,$biblio);
1050 modify a record in biblio table. Datas are in the hash $biblio.
1057 my ( $dbh, $biblio ) = @_;
1058 my $sth = $dbh->prepare("Update biblio set title=?, author=?, abstract=?, copyrightdate=?,
1059 seriestitle=?, serial=?, unititle=?, notes=?, frameworkcode=?
1060 where biblionumber = ?"
1063 $biblio->{'title'}, $biblio->{'author'},
1064 $biblio->{'abstract'}, $biblio->{'copyrightdate'},
1065 $biblio->{'seriestitle'}, $biblio->{'serial'},
1066 $biblio->{'unititle'}, $biblio->{'notes'},
1067 $biblio->{frameworkcode},
1068 $biblio->{'biblionumber'}
1071 return ( $biblio->{'biblionumber'} );
1074 =head2 REALmodsubtitle($dbh,$bibnum,$subtitle);
1078 modify subtitles in bibliosubtitle table.
1084 sub REALmodsubtitle {
1085 my ( $dbh, $bibnum, $subtitle ) = @_;
1088 "update bibliosubtitle set subtitle = ? where biblionumber = ?");
1089 $sth->execute( $subtitle, $bibnum );
1093 =head2 REALmodaddauthor($dbh,$bibnum,$author);
1097 adds or modify additional authors
1098 NOTE : Strange sub : seems to delete MANY and add only ONE author... maybe buggy ?
1104 sub REALmodaddauthor {
1105 my ( $dbh, $bibnum, @authors ) = @_;
1107 # my $dbh = C4Connect;
1109 $dbh->prepare("Delete from additionalauthors where biblionumber = ?");
1111 $sth->execute($bibnum);
1113 foreach my $author (@authors) {
1114 if ( $author ne '' ) {
1117 "Insert into additionalauthors set author = ?, biblionumber = ?"
1120 $sth->execute( $author, $bibnum );
1125 } # sub modaddauthor
1127 =head2 $errors = REALmodsubject($dbh,$bibnum, $force, @subject);
1131 modify/adds subjects
1136 sub REALmodsubject {
1137 my ( $dbh, $bibnum, $force, @subject ) = @_;
1139 # my $dbh = C4Connect;
1140 my $count = @subject;
1142 for ( my $i = 0 ; $i < $count ; $i++ ) {
1143 $subject[$i] =~ s/^ //g;
1144 $subject[$i] =~ s/ $//g;
1147 "select * from catalogueentry where entrytype = 's' and catalogueentry = ?"
1149 $sth->execute( $subject[$i] );
1151 if ( my $data = $sth->fetchrow_hashref ) {
1154 if ( $force eq $subject[$i] || $force == 1 ) {
1156 # subject not in aut, chosen to force anway
1157 # so insert into cataloguentry so its in auth file
1160 "Insert into catalogueentry (entrytype,catalogueentry) values ('s',?)"
1163 $sth2->execute( $subject[$i] ) if ( $subject[$i] );
1168 "$subject[$i]\n does not exist in the subject authority file";
1171 "Select * from catalogueentry where entrytype = 's' and (catalogueentry like ? or catalogueentry like ? or catalogueentry like ?)"
1173 $sth2->execute( "$subject[$i] %", "% $subject[$i] %",
1175 while ( my $data = $sth2->fetchrow_hashref ) {
1176 $error .= "<br>$data->{'catalogueentry'}";
1185 $dbh->prepare("Delete from bibliosubject where biblionumber = ?");
1186 $sth->execute($bibnum);
1190 "Insert into bibliosubject (subject,biblionumber) values (?,?)");
1192 foreach $query (@subject) {
1193 $sth->execute( $query, $bibnum ) if ( $query && $bibnum );
1202 =head2 REALmodbiblioitem($dbh, $biblioitem);
1211 sub REALmodbiblioitem {
1212 my ( $dbh, $Zconn, $biblioitem ) = @_;
1215 my $sth = $dbh->prepare("update biblioitems set number=?,volume=?, volumedate=?, lccn=?,
1216 itemtype=?, url=?, isbn=?, issn=?,
1217 publishercode=?, publicationyear=?, classification=?, dewey=?,
1218 subclass=?, illus=?, pages=?, volumeddesc=?,
1219 notes=?, size=?, place=?, marc=?,
1221 where biblioitemnumber=?");
1222 $sth->execute( $biblioitem->{number}, $biblioitem->{volume}, $biblioitem->{volumedate}, $biblioitem->{lccn},
1223 $biblioitem->{itemtype}, $biblioitem->{url}, $biblioitem->{isbn}, $biblioitem->{issn},
1224 $biblioitem->{publishercode}, $biblioitem->{publicationyear}, $biblioitem->{classification}, $biblioitem->{dewey},
1225 $biblioitem->{subclass}, $biblioitem->{illus}, $biblioitem->{pages}, $biblioitem->{volumeddesc},
1226 $biblioitem->{bnotes}, $biblioitem->{size}, $biblioitem->{place}, $biblioitem->{marc},
1227 $biblioitem->{marcxml}, $biblioitem->{biblioitemnumber});
1228 my $record = MARC::File::USMARC::decode($biblioitem->{marc});
1230 #my $Zconn = C4::Context->Zconn or die "unable to set Zconn";
1231 z3950_extended_services($Zconn,'update',set_service_options('update'),$record);
1232 #z3950_extended_services($Zconn,'commit',set_service_options('commit'));
1235 # warn "MOD : $biblioitem->{biblioitemnumber} = ".$biblioitem->{marc};
1238 =head2 REALnewbiblioitem($dbh,$Zconn,$biblioitem);
1242 adds a biblioitem ($biblioitem is a hash with the values)
1248 sub REALnewbiblioitem {
1249 my ( $dbh, $Zconn, $biblioitem ) = @_;
1251 $dbh->do("lock tables biblioitems WRITE, biblio WRITE, marc_subfield_structure READ");
1252 my $sth = $dbh->prepare("Select max(biblioitemnumber) from biblioitems");
1254 my $biblioitemnumber;
1257 $data = $sth->fetchrow_arrayref;
1258 $biblioitemnumber = $$data[0] + 1;
1260 # Insert biblioitemnumber in MARC record, we need it to manage items later...
1261 my $frameworkcode=MARCfind_frameworkcode($dbh,$biblioitem->{biblionumber});
1262 my ($biblioitemnumberfield,$biblioitemnumbersubfield) = MARCfind_marc_from_kohafield($dbh,'biblioitems.biblioitemnumber',$frameworkcode);
1263 my $record = MARC::File::USMARC::decode($biblioitem->{marc});
1264 my $field=$record->field($biblioitemnumberfield);
1265 $field->update($biblioitemnumbersubfield => "$biblioitemnumber");
1266 $biblioitem->{marc} = $record->as_usmarc();
1267 $biblioitem->{marcxml} = $record->as_xml();
1269 $sth = $dbh->prepare( "insert into biblioitems set
1270 biblioitemnumber = ?, biblionumber = ?,
1271 volume = ?, number = ?,
1272 classification = ?, itemtype = ?,
1274 issn = ?, dewey = ?,
1275 subclass = ?, publicationyear = ?,
1276 publishercode = ?, volumedate = ?,
1277 volumeddesc = ?, illus = ?,
1278 pages = ?, notes = ?,
1280 marc = ?, place = ?,
1284 $biblioitemnumber, $biblioitem->{'biblionumber'},
1285 $biblioitem->{'volume'}, $biblioitem->{'number'},
1286 $biblioitem->{'classification'}, $biblioitem->{'itemtype'},
1287 $biblioitem->{'url'}, $biblioitem->{'isbn'},
1288 $biblioitem->{'issn'}, $biblioitem->{'dewey'},
1289 $biblioitem->{'subclass'}, $biblioitem->{'publicationyear'},
1290 $biblioitem->{'publishercode'}, $biblioitem->{'volumedate'},
1291 $biblioitem->{'volumeddesc'}, $biblioitem->{'illus'},
1292 $biblioitem->{'pages'}, $biblioitem->{'bnotes'},
1293 $biblioitem->{'size'}, $biblioitem->{'lccn'},
1294 $biblioitem->{'marc'}, $biblioitem->{'place'},
1295 $biblioitem->{marcxml},
1297 $dbh->do("unlock tables");
1298 #my $Zconn = C4::Context->Zconn or die "unable to set Zconn";
1299 z3950_extended_services($Zconn,'update',set_service_options('update'),$record);
1300 #z3950_extended_services($Zconn,'commit',set_service_options('commit'));
1301 #zebra_create($biblioitem->{biblionumber}, $record);
1302 return ($biblioitemnumber);
1305 =head2 REALnewsubtitle($dbh,$bibnum,$subtitle);
1309 create a new subtitle
1314 sub REALnewsubtitle {
1315 my ( $dbh, $bibnum, $subtitle ) = @_;
1318 "insert into bibliosubtitle set biblionumber = ?, subtitle = ?");
1319 $sth->execute( $bibnum, $subtitle ) if $subtitle;
1323 =head2 ($itemnumber,$errors)= REALnewitems($dbh,$Zconn,$item,$barcode);
1327 create a item. $item is a hash and $barcode the barcode.
1334 my ( $dbh, $Zconn,$item, $barcode ) = @_;
1336 # warn "OLDNEWITEMS";
1338 $dbh->do('lock tables items WRITE, biblio WRITE,biblioitems WRITE,marc_subfield_structure WRITE');
1339 my $sth = $dbh->prepare("Select max(itemnumber) from items");
1344 $data = $sth->fetchrow_hashref;
1345 $itemnumber = $data->{'max(itemnumber)'} + 1;
1347 # FIXME the "notforloan" field seems to be named "loan" in some places. workaround bugfix.
1348 if ( $item->{'loan'} ) {
1349 $item->{'notforloan'} = $item->{'loan'};
1351 $item->{'biblioitemnumber'} = 1;
1352 # if dateaccessioned is provided, use it. Otherwise, set to NOW()
1353 if ( $item->{'dateaccessioned'} ) {
1354 $sth = $dbh->prepare( "Insert into items set
1355 itemnumber = ?, biblionumber = ?,
1356 multivolumepart = ?,
1357 biblioitemnumber = ?, barcode = ?,
1358 booksellerid = ?, dateaccessioned = ?,
1359 homebranch = ?, holdingbranch = ?,
1360 price = ?, replacementprice = ?,
1361 replacementpricedate = NOW(), datelastseen = NOW(),
1362 multivolume = ?, stack = ?,
1363 itemlost = ?, wthdrawn = ?,
1364 paidfor = ?, itemnotes = ?,
1365 itemcallnumber =?, notforloan = ?,
1370 $itemnumber, $item->{'biblionumber'},
1371 $item->{'multivolumepart'},
1372 $item->{'biblioitemnumber'},$item->{barcode},
1373 $item->{'booksellerid'}, $item->{'dateaccessioned'},
1374 $item->{'homebranch'}, $item->{'holdingbranch'},
1375 $item->{'price'}, $item->{'replacementprice'},
1376 $item->{multivolume}, $item->{stack},
1377 $item->{itemlost}, $item->{wthdrawn},
1378 $item->{paidfor}, $item->{'itemnotes'},
1379 $item->{'itemcallnumber'}, $item->{'notforloan'},
1382 if ( defined $sth->errstr ) {
1383 $error .= $sth->errstr;
1387 $sth = $dbh->prepare( "Insert into items set
1388 itemnumber = ?, biblionumber = ?,
1389 multivolumepart = ?,
1390 biblioitemnumber = ?, barcode = ?,
1391 booksellerid = ?, dateaccessioned = NOW(),
1392 homebranch = ?, holdingbranch = ?,
1393 price = ?, replacementprice = ?,
1394 replacementpricedate = NOW(), datelastseen = NOW(),
1395 multivolume = ?, stack = ?,
1396 itemlost = ?, wthdrawn = ?,
1397 paidfor = ?, itemnotes = ?,
1398 itemcallnumber =?, notforloan = ?,
1403 $itemnumber, $item->{'biblionumber'},
1404 $item->{'multivolumepart'},
1405 $item->{'biblioitemnumber'},$item->{barcode},
1406 $item->{'booksellerid'},
1407 $item->{'homebranch'}, $item->{'holdingbranch'},
1408 $item->{'price'}, $item->{'replacementprice'},
1409 $item->{multivolume}, $item->{stack},
1410 $item->{itemlost}, $item->{wthdrawn},
1411 $item->{paidfor}, $item->{'itemnotes'},
1412 $item->{'itemcallnumber'}, $item->{'notforloan'},
1415 if ( defined $sth->errstr ) {
1416 $error .= $sth->errstr;
1419 # item stored, now, deal with the marc part...
1420 $sth = $dbh->prepare("select biblioitems.marc,biblio.frameworkcode from biblioitems,biblio
1421 where biblio.biblionumber=biblioitems.biblionumber and
1422 biblio.biblionumber=?");
1423 $sth->execute($item->{biblionumber});
1424 if ( defined $sth->errstr ) {
1425 $error .= $sth->errstr;
1427 my ($rawmarc,$frameworkcode) = $sth->fetchrow;
1428 warn "ERROR IN REALnewitem, MARC record not found FOR $item->{biblionumber} => $rawmarc <=" unless $rawmarc;
1429 my $record = MARC::File::USMARC::decode($rawmarc);
1430 # ok, we have the marc record, add item number to the item field (in {marc}, and add the field to the record)
1431 my ($itemnumberfield,$itemnumbersubfield) = MARCfind_marc_from_kohafield($dbh,'items.itemnumber',$frameworkcode);
1432 my $itemrecord = MARC::Record->new_from_usmarc($item->{marc});
1434 warn $itemnumberfield;
1435 warn $itemrecord->field($itemnumberfield);
1436 my $itemfield = $itemrecord->field($itemnumberfield);
1437 $itemfield->add_subfields($itemnumbersubfield => "$itemnumber");
1438 $record->insert_grouped_field($itemfield);
1439 # save the record into biblioitem
1440 $sth=$dbh->prepare("update biblioitems set marc=?,marcxml=? where biblionumber=?");
1441 $sth->execute($record->as_usmarc(),$record->as_xml(),$item->{biblionumber});
1442 if ( defined $sth->errstr ) {
1443 $error .= $sth->errstr;
1445 #my $Zconn = C4::Context->Zconn or die "unable to set Zconn";
1446 z3950_extended_services($Zconn,'update',set_service_options('update'),$record);
1447 # z3950_extended_services($Zconn,'commit',set_service_options('commit'));
1448 #zebra_create($item->{biblionumber},$record);
1449 $dbh->do('unlock tables');
1450 return ( $itemnumber, $error );
1453 =head2 REALmoditem($dbh,$Zconn,$item);
1464 my ( $dbh, $Zconn, $item ) = @_;
1465 $item->{'bibitemnum'} = 1;
1467 $dbh->do('lock tables items WRITE, biblio WRITE,biblioitems WRITE');
1468 $item->{'itemnum'} = $item->{'itemnumber'} unless $item->{'itemnum'};
1469 my $query = "update items set barcode=?,itemnotes=?,itemcallnumber=?,notforloan=?,location=?,multivolumepart=?,multivolume=?,stack=?,wthdrawn=?";
1471 $item->{'barcode'}, $item->{'itemnotes'},
1472 $item->{'itemcallnumber'}, $item->{'notforloan'},
1473 $item->{'location'}, $item->{multivolumepart},
1474 $item->{multivolume}, $item->{stack},
1477 if ( $item->{'lost'} ne '' ) {
1478 $query = "update items set biblioitemnumber=?,barcode=?,itemnotes=?,homebranch=?,
1479 itemlost=?,wthdrawn=?,itemcallnumber=?,notforloan=?,
1480 location=?,multivolumepart=?,multivolume=?,stack=?,wthdrawn=?";
1482 $item->{'bibitemnum'}, $item->{'barcode'},
1483 $item->{'itemnotes'}, $item->{'homebranch'},
1484 $item->{'lost'}, $item->{'wthdrawn'},
1485 $item->{'itemcallnumber'}, $item->{'notforloan'},
1486 $item->{'location'}, $item->{multivolumepart},
1487 $item->{multivolume}, $item->{stack},
1490 if ($item->{homebranch}) {
1491 $query.=",homebranch=?";
1492 push @bind, $item->{homebranch};
1494 if ($item->{holdingbranch}) {
1495 $query.=",holdingbranch=?";
1496 push @bind, $item->{holdingbranch};
1499 $query.=" where itemnumber=?";
1500 push @bind,$item->{'itemnum'};
1501 if ( $item->{'replacement'} ne '' ) {
1502 $query =~ s/ where/,replacementprice='$item->{'replacement'}' where/;
1504 my $sth = $dbh->prepare($query);
1505 $sth->execute(@bind);
1507 # item stored, now, deal with the marc part...
1508 $sth = $dbh->prepare("select biblioitems.marc,biblio.frameworkcode from biblioitems,biblio
1509 where biblio.biblionumber=biblioitems.biblionumber and
1510 biblio.biblionumber=? and
1511 biblioitems.biblioitemnumber=?");
1512 $sth->execute($item->{biblionumber},$item->{biblioitemnumber});
1513 if ( defined $sth->errstr ) {
1514 $error .= $sth->errstr;
1516 my ($rawmarc,$frameworkcode) = $sth->fetchrow;
1517 warn "ERROR IN REALmoditem, MARC record not found" unless $rawmarc;
1518 my $record = MARC::File::USMARC::decode($rawmarc);
1519 # ok, we have the marc record, find the previous item record for this itemnumber and delete it
1520 my ($itemnumberfield,$itemnumbersubfield) = MARCfind_marc_from_kohafield($dbh,'items.itemnumber',$frameworkcode);
1521 # prepare the new item record
1522 my $itemrecord = MARC::File::USMARC::decode($item->{marc});
1523 my $itemfield = $itemrecord->field($itemnumberfield);
1524 $itemfield->add_subfields($itemnumbersubfield => '$itemnumber');
1525 # parse all fields fields from the complete record
1526 foreach ($record->field($itemnumberfield)) {
1527 # when the previous field is found, replace by the new one
1528 if ($_->subfield($itemnumbersubfield) == $item->{itemnum}) {
1529 $_->replace_with($itemfield);
1532 # $record->insert_grouped_field($itemfield);
1533 # save the record into biblioitem
1534 $sth=$dbh->prepare("update biblioitems set marc=?,marcxml=? where biblionumber=? and biblioitemnumber=?");
1535 $sth->execute($record->as_usmarc(),$record->as_xml(),$item->{biblionumber},$item->{biblioitemnumber});
1536 #my $Zconn = C4::Context->Zconn or die "unable to set Zconn";
1537 z3950_extended_services($Zconn,'update',set_service_options('update'),$record);
1538 # z3950_extended_services($Zconn,'commit',set_service_options('commit'));
1539 #zebra_create($item->biblionumber,$record);
1540 if ( defined $sth->errstr ) {
1541 $error .= $sth->errstr;
1543 $dbh->do('unlock tables');
1548 =head2 REALdelitem($dbh,$itemnum);
1559 my ( $dbh, $itemnum ) = @_;
1561 # my $dbh=C4Connect;
1562 my $sth = $dbh->prepare("select * from items where itemnumber=?");
1563 $sth->execute($itemnum);
1564 my $data = $sth->fetchrow_hashref;
1566 my $query = "Insert into deleteditems set ";
1568 foreach my $temp ( keys %$data ) {
1569 $query .= "$temp = ?,";
1570 push ( @bind, $data->{$temp} );
1575 $sth = $dbh->prepare($query);
1576 $sth->execute(@bind);
1578 $sth = $dbh->prepare("Delete from items where itemnumber=?");
1579 $sth->execute($itemnum);
1585 =head2 REALdelbiblioitem($dbh,$biblioitemnumber);
1589 deletes a biblioitem
1590 NOTE : not standard sub name. Should be REALdelbiblioitem()
1596 sub REALdelbiblioitem {
1597 my ( $dbh, $biblioitemnumber ) = @_;
1599 # my $dbh = C4Connect;
1600 my $sth = $dbh->prepare( "Select * from biblioitems
1601 where biblioitemnumber = ?"
1605 $sth->execute($biblioitemnumber);
1607 if ( $results = $sth->fetchrow_hashref ) {
1611 "Insert into deletedbiblioitems (biblioitemnumber, biblionumber, volume, number, classification, itemtype,
1612 isbn, issn ,dewey ,subclass ,publicationyear ,publishercode ,volumedate ,volumeddesc ,timestamp ,illus ,
1613 pages ,notes ,size ,url ,lccn ) values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"
1617 $results->{biblioitemnumber}, $results->{biblionumber},
1618 $results->{volume}, $results->{number},
1619 $results->{classification}, $results->{itemtype},
1620 $results->{isbn}, $results->{issn},
1621 $results->{dewey}, $results->{subclass},
1622 $results->{publicationyear}, $results->{publishercode},
1623 $results->{volumedate}, $results->{volumeddesc},
1624 $results->{timestamp}, $results->{illus},
1625 $results->{pages}, $results->{notes},
1626 $results->{size}, $results->{url},
1630 $dbh->prepare("Delete from biblioitems where biblioitemnumber = ?");
1631 $sth2->execute($biblioitemnumber);
1636 # Now delete all the items attached to the biblioitem
1637 $sth = $dbh->prepare("Select * from items where biblioitemnumber = ?");
1638 $sth->execute($biblioitemnumber);
1640 while ( my $data = $sth->fetchrow_hashref ) {
1641 my $query = "Insert into deleteditems set ";
1643 foreach my $temp ( keys %$data ) {
1644 $query .= "$temp = ?,";
1645 push ( @bind, $data->{$temp} );
1648 my $sth2 = $dbh->prepare($query);
1649 $sth2->execute(@bind);
1652 $sth = $dbh->prepare("Delete from items where biblioitemnumber = ?");
1653 $sth->execute($biblioitemnumber);
1657 } # sub deletebiblioitem
1659 =head2 REALdelbiblio($dbh,$biblio);
1670 my ( $dbh, $biblio ) = @_;
1671 my $sth = $dbh->prepare("select * from biblio where biblionumber=?");
1672 $sth->execute($biblio);
1673 if ( my $data = $sth->fetchrow_hashref ) {
1675 my $query = "Insert into deletedbiblio set ";
1677 foreach my $temp ( keys %$data ) {
1678 $query .= "$temp = ?,";
1679 push ( @bind, $data->{$temp} );
1682 #replacing the last , by ",?)"
1684 $sth = $dbh->prepare($query);
1685 $sth->execute(@bind);
1687 $sth = $dbh->prepare("Delete from biblio where biblionumber=?");
1688 $sth->execute($biblio);
1694 =head2 $number = itemcount($biblio);
1698 returns the number of items attached to a biblio
1706 my $dbh = C4::Context->dbh;
1709 my $sth = $dbh->prepare("Select count(*) from items where biblionumber=?");
1710 $sth->execute($biblio);
1711 my $data = $sth->fetchrow_hashref;
1713 return ( $data->{'count(*)'} );
1716 =head2 $biblionumber = newbiblio($biblio);
1720 create a biblio. The parameter is a hash
1728 my $dbh = C4::Context->dbh;
1729 my $bibnum = REALnewbiblio( $dbh, $biblio );
1730 # finds new (MARC bibid
1731 # my $bibid = &MARCfind_MARCbibid_from_oldbiblionumber($dbh,$bibnum);
1732 # my $record = &MARCkoha2marcBiblio( $dbh, $bibnum );
1733 # MARCaddbiblio( $dbh, $record, $bibnum,'' );
1737 =head2 $biblionumber = &modbiblio($biblio);
1741 Update a biblio record.
1743 C<$biblio> is a reference-to-hash whose keys are the fields in the
1744 biblio table in the Koha database. All fields must be present, not
1745 just the ones you wish to change.
1747 C<&modbiblio> updates the record defined by
1748 C<$biblio-E<gt>{biblionumber}> with the values in C<$biblio>.
1750 C<&modbiblio> returns C<$biblio-E<gt>{biblionumber}> whether it was
1759 my $dbh = C4::Context->dbh;
1760 my $biblionumber=REALmodbiblio($dbh,$biblio);
1761 my $record = MARCkoha2marcBiblio($dbh,$biblionumber,$biblionumber);
1762 # finds new (MARC bibid
1763 my $bibid = &MARCfind_MARCbibid_from_oldbiblionumber($dbh,$biblionumber);
1764 MARCmodbiblio($dbh,$bibid,$record,"",0);
1765 return($biblionumber);
1768 =head2 &modsubtitle($biblionumber, $subtitle);
1772 Sets the subtitle of a book.
1774 C<$biblionumber> is the biblionumber of the book to modify.
1776 C<$subtitle> is the new subtitle.
1783 my ( $bibnum, $subtitle ) = @_;
1784 my $dbh = C4::Context->dbh;
1785 &REALmodsubtitle( $dbh, $bibnum, $subtitle );
1788 =head2 &modaddauthor($biblionumber, $author);
1792 Replaces all additional authors for the book with biblio number
1793 C<$biblionumber> with C<$author>. If C<$author> is the empty string,
1794 C<&modaddauthor> deletes all additional authors.
1801 my ( $bibnum, @authors ) = @_;
1802 my $dbh = C4::Context->dbh;
1803 &REALmodaddauthor( $dbh, $bibnum, @authors );
1804 } # sub modaddauthor
1806 =head2 $error = &modsubject($biblionumber, $force, @subjects);
1810 $force - a subject to force
1811 $error - Error message, or undef if successful.
1818 my ( $bibnum, $force, @subject ) = @_;
1819 my $dbh = C4::Context->dbh;
1820 my $error = &REALmodsubject( $dbh, $bibnum, $force, @subject );
1822 # When MARC is off, ensures that the MARC biblio table gets updated with new
1823 # subjects, of course, it deletes the biblio in marc, and then recreates.
1824 # This check is to ensure that no MARC data exists to lose.
1825 # if (C4::Context->preference("MARC") eq '0'){
1826 # warn "in modSUBJECT";
1827 # my $MARCRecord = &MARCkoha2marcBiblio($dbh,$bibnum);
1828 # my $bibid = &MARCfind_MARCbibid_from_oldbiblionumber($dbh,$bibnum);
1829 # &MARCmodbiblio($dbh,$bibid, $MARCRecord);
1835 =head2 modbibitem($dbh, $Zconn,$biblioitem);
1839 modify a biblioitem. The parameter is a hash
1846 my ($dbh, $Zconn, $biblioitem) = @_;
1847 #my $dbh = C4::Context->dbh;
1848 &REALmodbiblioitem( $dbh, $Zconn, $biblioitem );
1851 =head2 $biblioitemnumber = newbiblioitem($biblioitem)
1855 create a biblioitem, the parameter is a hash
1862 my ($dbh, $Zconn, $biblioitem) = @_;
1863 #my $dbh = C4::Context->dbh;
1864 # add biblio information to the hash
1865 my $MARCbiblio = MARCkoha2marcBiblio( $dbh, $biblioitem );
1866 $biblioitem->{marc} = $MARCbiblio->as_usmarc();
1867 my $bibitemnum = &REALnewbiblioitem( $dbh, $Zconn, $biblioitem );
1868 return ($bibitemnum);
1871 =head2 newsubtitle($biblionumber,$subtitle);
1875 insert a subtitle for $biblionumber biblio
1883 my ( $bibnum, $subtitle ) = @_;
1884 my $dbh = C4::Context->dbh;
1885 &REALnewsubtitle( $dbh, $bibnum, $subtitle );
1888 =head2 $errors = newitems($dbh, $Zconn, $item, @barcodes);
1892 insert items ($item is a hash)
1900 my ( $dbh, $Zconn, $item, @barcodes ) = @_;
1901 #my $dbh = C4::Context->dbh;
1905 foreach my $barcode (@barcodes) {
1906 # add items, one by one for each barcode.
1908 $oneitem->{barcode}= $barcode;
1909 my $MARCitem = &MARCkoha2marcItem( $dbh, $oneitem);
1910 $oneitem->{marc} = $MARCitem->as_usmarc;
1911 ( $itemnumber, $error ) = &REALnewitems( $dbh,$Zconn,$oneitem);
1912 # $errors .= $error;
1913 # &MARCadditem( $dbh, $MARCitem, $item->{biblionumber} );
1918 =head2 moditem($dbh,$Zconn,$item);
1922 modify an item ($item is a hash with all item informations)
1930 my ($dbh,$Zconn,$item) = @_;
1931 #my $dbh = C4::Context->dbh;
1932 &REALmoditem( $dbh, $Zconn, $item );
1934 &MARCkoha2marcItem( $dbh, $item->{'biblionumber'}, $item->{'itemnum'} );
1936 &MARCfind_MARCbibid_from_oldbiblionumber( $dbh, $item->{biblionumber} );
1937 &MARCmoditem( $dbh, $MARCitem, $bibid, $item->{itemnum}, 0 );
1940 =head2 $error = checkitems($count,@barcodes);
1944 check for each @barcode entry that the barcode is not a duplicate
1951 my ( $count, @barcodes ) = @_;
1952 my $dbh = C4::Context->dbh;
1954 my $sth = $dbh->prepare("Select * from items where barcode=?");
1955 for ( my $i = 0 ; $i < $count ; $i++ ) {
1956 $barcodes[$i] = uc $barcodes[$i];
1957 $sth->execute( $barcodes[$i] );
1958 if ( my $data = $sth->fetchrow_hashref ) {
1959 $error .= " Duplicate Barcode: $barcodes[$i]";
1966 =head2 $delitem($itemnum);
1970 delete item $itemnum being the item number to delete
1978 my $dbh = C4::Context->dbh;
1979 &REALdelitem( $dbh, $itemnum );
1982 =head2 deletebiblioitem($biblioitemnumber);
1986 delete the biblioitem $biblioitemnumber
1992 sub deletebiblioitem {
1993 my ($biblioitemnumber) = @_;
1994 my $dbh = C4::Context->dbh;
1995 &REALdelbiblioitem( $dbh, $biblioitemnumber );
1996 } # sub deletebiblioitem
1998 =head2 delbiblio($biblionumber)
2002 delete biblio $biblionumber
2010 my $dbh = C4::Context->dbh;
2011 &REALdelbiblio( $dbh, $biblio );
2012 my $bibid = &MARCfind_MARCbibid_from_oldbiblionumber( $dbh, $biblio );
2013 &MARCdelbiblio( $dbh, $bibid, 0 );
2016 =head2 ($count,@results) = getbiblio($biblionumber);
2020 return an array with hash of biblios.
2022 FIXME : biblionumber being the primary key, this sub will always return only 1 result, API should be modified...
2029 my ($biblionumber) = @_;
2030 my $dbh = C4::Context->dbh;
2031 my $sth = $dbh->prepare("Select * from biblio where biblionumber = ?");
2033 # || die "Cannot prepare $query\n" . $dbh->errstr;
2037 $sth->execute($biblionumber);
2039 # || die "Cannot execute $query\n" . $sth->errstr;
2040 while ( my $data = $sth->fetchrow_hashref ) {
2041 $results[$count] = $data;
2046 return ( $count, @results );
2051 $data = &bibdata($biblionumber, $type);
2053 Returns information about the book with the given biblionumber.
2055 C<$type> is ignored.
2057 C<&bibdata> returns a reference-to-hash. The keys are the fields in
2058 the C<biblio>, C<biblioitems>, and C<bibliosubtitle> tables in the
2061 In addition, C<$data-E<gt>{subject}> is the list of the book's
2062 subjects, separated by C<" , "> (space, comma, space).
2064 If there are multiple biblioitems with the given biblionumber, only
2065 the first one is considered.
2070 my ($bibnum, $type) = @_;
2071 my $dbh = C4::Context->dbh;
2072 my $sth = $dbh->prepare("Select *, biblioitems.notes AS bnotes, biblio.notes
2074 left join biblioitems on biblioitems.biblionumber = biblio.biblionumber
2075 left join bibliosubtitle on
2076 biblio.biblionumber = bibliosubtitle.biblionumber
2077 left join itemtypes on biblioitems.itemtype=itemtypes.itemtype
2078 where biblio.biblionumber = ?
2080 $sth->execute($bibnum);
2082 $data = $sth->fetchrow_hashref;
2084 # handle management of repeated subtitle
2085 $sth = $dbh->prepare("Select * from bibliosubtitle where biblionumber = ?");
2086 $sth->execute($bibnum);
2088 while (my $dat = $sth->fetchrow_hashref){
2090 $line{subtitle} = $dat->{subtitle};
2091 push @subtitles, \%line;
2093 $data->{subtitles} = \@subtitles;
2095 $sth = $dbh->prepare("Select * from bibliosubject where biblionumber = ?");
2096 $sth->execute($bibnum);
2098 while (my $dat = $sth->fetchrow_hashref){
2100 $line{subject} = $dat->{'subject'};
2101 push @subjects, \%line;
2103 $data->{subjects} = \@subjects;
2105 $sth = $dbh->prepare("Select * from additionalauthors where biblionumber = ?");
2106 $sth->execute($bibnum);
2107 while (my $dat = $sth->fetchrow_hashref){
2108 $data->{'additionalauthors'} .= "$dat->{'author'} - ";
2110 chop $data->{'additionalauthors'};
2111 chop $data->{'additionalauthors'};
2112 chop $data->{'additionalauthors'};
2117 =head2 ($count,@results) = getbiblioitem($biblioitemnumber);
2121 return an array with hash of biblioitemss.
2123 FIXME : biblioitemnumber being unique, this sub will always return only 1 result, API should be modified...
2130 my ($biblioitemnum) = @_;
2131 my $dbh = C4::Context->dbh;
2132 my $sth = $dbh->prepare( "Select * from biblioitems where
2133 biblioitemnumber = ?"
2138 $sth->execute($biblioitemnum);
2140 while ( my $data = $sth->fetchrow_hashref ) {
2141 $results[$count] = $data;
2146 return ( $count, @results );
2147 } # sub getbiblioitem
2149 =head2 ($count,@results) = getbiblioitembybiblionumber($biblionumber);
2153 return an array with hash of biblioitems for the given biblionumber.
2159 sub getbiblioitembybiblionumber {
2160 my ($biblionumber) = @_;
2161 my $dbh = C4::Context->dbh;
2162 my $sth = $dbh->prepare("Select * from biblioitems where biblionumber = ?");
2166 $sth->execute($biblionumber);
2168 while ( my $data = $sth->fetchrow_hashref ) {
2169 $results[$count] = $data;
2174 return ( $count, @results );
2177 =head2 ($count,@results) = getitemsbybiblioitem($biblionumber);
2181 returns an array with hash of items
2187 sub getitemsbybiblioitem {
2188 my ($biblioitemnum) = @_;
2189 my $dbh = C4::Context->dbh;
2190 my $sth = $dbh->prepare( "Select * from items, biblio where
2191 biblio.biblionumber = items.biblionumber and biblioitemnumber
2195 # || die "Cannot prepare $query\n" . $dbh->errstr;
2199 $sth->execute($biblioitemnum);
2201 # || die "Cannot execute $query\n" . $sth->errstr;
2202 while ( my $data = $sth->fetchrow_hashref ) {
2203 $results[$count] = $data;
2208 return ( $count, @results );
2209 } # sub getitemsbybiblioitem
2213 @results = &ItemInfo($env, $biblionumber, $type);
2215 Returns information about books with the given biblionumber.
2217 C<$type> may be either C<intra> or anything else. If it is not set to
2218 C<intra>, then the search will exclude lost, very overdue, and
2223 C<&ItemInfo> returns a list of references-to-hash. Each element
2224 contains a number of keys. Most of them are table items from the
2225 C<biblio>, C<biblioitems>, C<items>, and C<itemtypes> tables in the
2226 Koha database. Other keys include:
2230 =item C<$data-E<gt>{branchname}>
2232 The name (not the code) of the branch to which the book belongs.
2234 =item C<$data-E<gt>{datelastseen}>
2236 This is simply C<items.datelastseen>, except that while the date is
2237 stored in YYYY-MM-DD format in the database, here it is converted to
2238 DD/MM/YYYY format. A NULL date is returned as C<//>.
2240 =item C<$data-E<gt>{datedue}>
2242 =item C<$data-E<gt>{class}>
2244 This is the concatenation of C<biblioitems.classification>, the book's
2245 Dewey code, and C<biblioitems.subclass>.
2247 =item C<$data-E<gt>{ocount}>
2249 I think this is the number of copies of the book available.
2251 =item C<$data-E<gt>{order}>
2253 If this is set, it is set to C<One Order>.
2260 my ($env,$biblionumber,$type) = @_;
2261 my $dbh = C4::Context->dbh;
2262 my $query = "SELECT *,items.notforloan as itemnotforloan FROM items, biblio, biblioitems
2263 left join itemtypes on biblioitems.itemtype = itemtypes.itemtype
2264 WHERE items.biblionumber = ?
2265 AND biblioitems.biblioitemnumber = items.biblioitemnumber
2266 AND biblio.biblionumber = items.biblionumber";
2267 $query .= " order by items.dateaccessioned desc";
2268 my $sth=$dbh->prepare($query);
2269 $sth->execute($biblionumber);
2272 while (my $data=$sth->fetchrow_hashref){
2274 my $isth=$dbh->prepare("Select issues.*,borrowers.cardnumber from issues,borrowers where itemnumber = ? and returndate is null and issues.borrowernumber=borrowers.borrowernumber");
2275 $isth->execute($data->{'itemnumber'});
2276 if (my $idata=$isth->fetchrow_hashref){
2277 $data->{borrowernumber} = $idata->{borrowernumber};
2278 $data->{cardnumber} = $idata->{cardnumber};
2279 $datedue = format_date($idata->{'date_due'});
2281 if ($datedue eq ''){
2282 my ($restype,$reserves)=C4::Reserves2::CheckReserves($data->{'itemnumber'});
2288 #get branch information.....
2289 my $bsth=$dbh->prepare("SELECT * FROM branches WHERE branchcode = ?");
2290 $bsth->execute($data->{'holdingbranch'});
2291 if (my $bdata=$bsth->fetchrow_hashref){
2292 $data->{'branchname'} = $bdata->{'branchname'};
2294 my $date=format_date($data->{'datelastseen'});
2295 $data->{'datelastseen'}=$date;
2296 $data->{'datedue'}=$datedue;
2297 # get notforloan complete status if applicable
2298 my $sthnflstatus = $dbh->prepare('select authorised_value from marc_subfield_structure where kohafield="items.notforloan"');
2299 $sthnflstatus->execute;
2300 my ($authorised_valuecode) = $sthnflstatus->fetchrow;
2301 if ($authorised_valuecode) {
2302 $sthnflstatus = $dbh->prepare("select lib from authorised_values where category=? and authorised_value=?");
2303 $sthnflstatus->execute($authorised_valuecode,$data->{itemnotforloan});
2304 my ($lib) = $sthnflstatus->fetchrow;
2305 $data->{notforloan} = $lib;
2316 ($count, @results) = &bibitems($biblionumber);
2318 Given the biblionumber for a book, C<&bibitems> looks up that book's
2319 biblioitems (different publications of the same book, the audio book
2320 and film versions, etc.).
2322 C<$count> is the number of elements in C<@results>.
2324 C<@results> is an array of references-to-hash; the keys are the fields
2325 of the C<biblioitems> and C<itemtypes> tables of the Koha database. In
2326 addition, C<itemlost> indicates the availability of the item: if it is
2327 "2", then all copies of the item are long overdue; if it is "1", then
2328 all copies are lost; otherwise, there is at least one copy available.
2334 my $dbh = C4::Context->dbh;
2335 my $sth = $dbh->prepare("SELECT biblioitems.*,
2337 MIN(items.itemlost) as itemlost,
2338 MIN(items.dateaccessioned) as dateaccessioned
2339 FROM biblioitems, itemtypes, items
2340 WHERE biblioitems.biblionumber = ?
2341 AND biblioitems.itemtype = itemtypes.itemtype
2342 AND biblioitems.biblioitemnumber = items.biblioitemnumber
2343 GROUP BY items.biblioitemnumber");
2346 $sth->execute($bibnum);
2347 while (my $data = $sth->fetchrow_hashref) {
2348 $results[$count] = $data;
2352 return($count, @results);
2358 $itemdata = &bibitemdata($biblioitemnumber);
2360 Looks up the biblioitem with the given biblioitemnumber. Returns a
2361 reference-to-hash. The keys are the fields from the C<biblio>,
2362 C<biblioitems>, and C<itemtypes> tables in the Koha database, except
2363 that C<biblioitems.notes> is given as C<$itemdata-E<gt>{bnotes}>.
2369 my $dbh = C4::Context->dbh;
2370 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");
2373 $sth->execute($bibitem);
2375 $data = $sth->fetchrow_hashref;
2382 =item getbibliofromitemnumber
2384 $item = &getbibliofromitemnumber($env, $dbh, $itemnumber);
2386 Looks up the item with the given itemnumber.
2388 C<$env> and C<$dbh> are ignored.
2390 C<&itemnodata> returns a reference-to-hash whose keys are the fields
2391 from the C<biblio>, C<biblioitems>, and C<items> tables in the Koha
2396 sub getbibliofromitemnumber {
2397 my ($env,$dbh,$itemnumber) = @_;
2398 $dbh = C4::Context->dbh;
2399 my $sth=$dbh->prepare("Select * from biblio,items,biblioitems
2400 where items.itemnumber = ?
2401 and biblio.biblionumber = items.biblionumber
2402 and biblioitems.biblioitemnumber = items.biblioitemnumber");
2404 $sth->execute($itemnumber);
2405 my $data=$sth->fetchrow_hashref;
2412 @barcodes = &barcodes($biblioitemnumber);
2414 Given a biblioitemnumber, looks up the corresponding items.
2416 Returns an array of references-to-hash; the keys are C<barcode> and
2419 The returned items include very overdue items, but not lost ones.
2424 #called from request.pl
2425 my ($biblioitemnumber)=@_;
2426 my $dbh = C4::Context->dbh;
2427 my $sth=$dbh->prepare("SELECT barcode, itemlost, holdingbranch FROM items
2428 WHERE biblioitemnumber = ?
2429 AND (wthdrawn <> 1 OR wthdrawn IS NULL)");
2430 $sth->execute($biblioitemnumber);
2433 while (my $data=$sth->fetchrow_hashref){
2434 $barcodes[$i]=$data;
2444 $item = &itemdata($barcode);
2446 Looks up the item with the given barcode, and returns a
2447 reference-to-hash containing information about that item. The keys of
2448 the hash are the fields from the C<items> and C<biblioitems> tables in
2453 sub get_item_from_barcode {
2455 my $dbh = C4::Context->dbh;
2456 my $sth=$dbh->prepare("Select * from items,biblioitems where barcode=?
2457 and items.biblioitemnumber=biblioitems.biblioitemnumber");
2458 $sth->execute($barcode);
2459 my $data=$sth->fetchrow_hashref;
2467 @issues = &itemissues($biblioitemnumber, $biblio);
2469 Looks up information about who has borrowed the bookZ<>(s) with the
2470 given biblioitemnumber.
2472 C<$biblio> is ignored.
2474 C<&itemissues> returns an array of references-to-hash. The keys
2475 include the fields from the C<items> table in the Koha database.
2476 Additional keys include:
2482 If the item is currently on loan, this gives the due date.
2484 If the item is not on loan, then this is either "Available" or
2485 "Cancelled", if the item has been withdrawn.
2489 If the item is currently on loan, this gives the card number of the
2490 patron who currently has the item.
2492 =item C<timestamp0>, C<timestamp1>, C<timestamp2>
2494 These give the timestamp for the last three times the item was
2497 =item C<card0>, C<card1>, C<card2>
2499 The card number of the last three patrons who borrowed this item.
2501 =item C<borrower0>, C<borrower1>, C<borrower2>
2503 The borrower number of the last three patrons who borrowed this item.
2510 my ($bibitem, $biblio)=@_;
2511 my $dbh = C4::Context->dbh;
2512 # FIXME - If this function die()s, the script will abort, and the
2513 # user won't get anything; depending on how far the script has
2514 # gotten, the user might get a blank page. It would be much better
2515 # to at least print an error message. The easiest way to do this
2516 # is to set $SIG{__DIE__}.
2517 my $sth = $dbh->prepare("Select * from items where
2518 items.biblioitemnumber = ?")
2519 || die $dbh->errstr;
2523 $sth->execute($bibitem)
2524 || die $sth->errstr;
2526 while (my $data = $sth->fetchrow_hashref) {
2527 # Find out who currently has this item.
2528 # FIXME - Wouldn't it be better to do this as a left join of
2529 # some sort? Currently, this code assumes that if
2530 # fetchrow_hashref() fails, then the book is on the shelf.
2531 # fetchrow_hashref() can fail for any number of reasons (e.g.,
2532 # database server crash), not just because no items match the
2534 my $sth2 = $dbh->prepare("select * from issues,borrowers
2535 where itemnumber = ?
2536 and returndate is NULL
2537 and issues.borrowernumber = borrowers.borrowernumber");
2539 $sth2->execute($data->{'itemnumber'});
2540 if (my $data2 = $sth2->fetchrow_hashref) {
2541 $data->{'date_due'} = $data2->{'date_due'};
2542 $data->{'card'} = $data2->{'cardnumber'};
2543 $data->{'borrower'} = $data2->{'borrowernumber'};
2545 if ($data->{'wthdrawn'} eq '1') {
2546 $data->{'date_due'} = 'Cancelled';
2548 $data->{'date_due'} = 'Available';
2554 # Find the last 3 people who borrowed this item.
2555 $sth2 = $dbh->prepare("select * from issues, borrowers
2556 where itemnumber = ?
2557 and issues.borrowernumber = borrowers.borrowernumber
2558 and returndate is not NULL
2559 order by returndate desc,timestamp desc") || die $dbh->errstr;
2560 $sth2->execute($data->{'itemnumber'}) || die $sth2->errstr;
2561 for (my $i2 = 0; $i2 < 2; $i2++) { # FIXME : error if there is less than 3 pple borrowing this item
2562 if (my $data2 = $sth2->fetchrow_hashref) {
2563 $data->{"timestamp$i2"} = $data2->{'timestamp'};
2564 $data->{"card$i2"} = $data2->{'cardnumber'};
2565 $data->{"borrower$i2"} = $data2->{'borrowernumber'};
2570 $results[$i] = $data;
2580 ($count, $subjects) = &getsubject($biblionumber);
2582 Looks up the subjects of the book with the given biblionumber. Returns
2583 a two-element list. C<$subjects> is a reference-to-array, where each
2584 element is a subject of the book, and C<$count> is the number of
2585 elements in C<$subjects>.
2591 my $dbh = C4::Context->dbh;
2592 my $sth=$dbh->prepare("Select * from bibliosubject where biblionumber=?");
2593 $sth->execute($bibnum);
2596 while (my $data=$sth->fetchrow_hashref){
2601 return($i,\@results);
2606 ($count, $authors) = &getaddauthor($biblionumber);
2608 Looks up the additional authors for the book with the given
2611 Returns a two-element list. C<$authors> is a reference-to-array, where
2612 each element is an additional author, and C<$count> is the number of
2613 elements in C<$authors>.
2619 my $dbh = C4::Context->dbh;
2620 my $sth=$dbh->prepare("Select * from additionalauthors where biblionumber=?");
2621 $sth->execute($bibnum);
2624 while (my $data=$sth->fetchrow_hashref){
2629 return($i,\@results);
2635 ($count, $subtitles) = &getsubtitle($biblionumber);
2637 Looks up the subtitles for the book with the given biblionumber.
2639 Returns a two-element list. C<$subtitles> is a reference-to-array,
2640 where each element is a subtitle, and C<$count> is the number of
2641 elements in C<$subtitles>.
2647 my $dbh = C4::Context->dbh;
2648 my $sth=$dbh->prepare("Select * from bibliosubtitle where biblionumber=?");
2649 $sth->execute($bibnum);
2652 while (my $data=$sth->fetchrow_hashref){
2657 return($i,\@results);
2663 ($count, @websites) = &getwebsites($biblionumber);
2665 Looks up the web sites pertaining to the book with the given
2668 C<$count> is the number of elements in C<@websites>.
2670 C<@websites> is an array of references-to-hash; the keys are the
2671 fields from the C<websites> table in the Koha database.
2674 #FIXME : could maybe be deleted. Otherwise, would be better in a Websites.pm package
2675 #(with add / modify / delete subs)
2678 my ($biblionumber) = @_;
2679 my $dbh = C4::Context->dbh;
2680 my $sth = $dbh->prepare("Select * from websites where biblionumber = ?");
2684 $sth->execute($biblionumber);
2685 while (my $data = $sth->fetchrow_hashref) {
2686 # FIXME - The URL scheme shouldn't be stripped off, at least
2687 # not here, since it's part of the URL, and will be useful in
2688 # constructing a link to the site. If you don't want the user
2689 # to see the "http://" part, strip that off when building the
2691 $data->{'url'} =~ s/^http:\/\///; # FIXME - Leaning toothpick
2693 $results[$count] = $data;
2698 return($count, @results);
2701 =item getwebbiblioitems
2703 ($count, @results) = &getwebbiblioitems($biblionumber);
2705 Given a book's biblionumber, looks up the web versions of the book
2706 (biblioitems with itemtype C<WEB>).
2708 C<$count> is the number of items in C<@results>. C<@results> is an
2709 array of references-to-hash; the keys are the items from the
2710 C<biblioitems> table of the Koha database.
2714 sub getwebbiblioitems {
2715 my ($biblionumber) = @_;
2716 my $dbh = C4::Context->dbh;
2717 my $sth = $dbh->prepare("Select * from biblioitems where biblionumber = ?
2718 and itemtype = 'WEB'");
2722 $sth->execute($biblionumber);
2723 while (my $data = $sth->fetchrow_hashref) {
2724 $data->{'url'} =~ s/^http:\/\///;
2725 $results[$count] = $data;
2730 return($count, @results);
2731 } # sub getwebbiblioitems
2734 my $NSB = '\x88'; # NSB : begin Non Sorting Block
2735 my $NSE = '\x89'; # NSE : Non Sorting Block end
2736 # handles non sorting blocks
2740 s/[ ]{0,1}$NSE/) /gm;
2747 my $dbh = C4::Context->dbh;
2748 my $result = MARCmarc2koha($dbh,$record,'');
2750 my ($biblionumber,$bibid,$title);
2751 # search duplicate on ISBN, easy and fast...
2752 if ($result->{isbn}) {
2753 $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=?");
2754 $sth->execute($result->{'isbn'});
2755 ($biblionumber,$bibid,$title) = $sth->fetchrow;
2756 return $biblionumber,$bibid,$title if ($biblionumber);
2758 # a more complex search : build a request for SearchMarc::catalogsearch()
2759 my (@tags, @and_or, @excluding, @operator, @value, $offset,$length);
2760 # search on biblio.title
2761 my ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblio.title","");
2762 if ($record->field($tag)) {
2763 if ($record->field($tag)->subfields($subfield)) {
2764 push @tags, "'".$tag.$subfield."'";
2765 push @and_or, "and";
2766 push @excluding, "";
2767 push @operator, "contains";
2768 push @value, $record->field($tag)->subfield($subfield);
2769 # warn "for title, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
2772 # ... and on biblio.author
2773 ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblio.author","");
2774 if ($record->field($tag)) {
2775 if ($record->field($tag)->subfields($subfield)) {
2776 push @tags, "'".$tag.$subfield."'";
2777 push @and_or, "and";
2778 push @excluding, "";
2779 push @operator, "contains";
2780 push @value, $record->field($tag)->subfield($subfield);
2781 # warn "for author, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
2784 # ... and on publicationyear.
2785 ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblioitems.publicationyear","");
2786 if ($record->field($tag)) {
2787 if ($record->field($tag)->subfields($subfield)) {
2788 push @tags, "'".$tag.$subfield."'";
2789 push @and_or, "and";
2790 push @excluding, "";
2791 push @operator, "=";
2792 push @value, $record->field($tag)->subfield($subfield);
2793 # warn "for publicationyear, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
2797 ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblioitems.size","");
2798 if ($record->field($tag)) {
2799 if ($record->field($tag)->subfields($subfield)) {
2800 push @tags, "'".$tag.$subfield."'";
2801 push @and_or, "and";
2802 push @excluding, "";
2803 push @operator, "=";
2804 push @value, $record->field($tag)->subfield($subfield);
2805 # warn "for size, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
2808 # ... and on publisher.
2809 ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblioitems.publishercode","");
2810 if ($record->field($tag)) {
2811 if ($record->field($tag)->subfields($subfield)) {
2812 push @tags, "'".$tag.$subfield."'";
2813 push @and_or, "and";
2814 push @excluding, "";
2815 push @operator, "=";
2816 push @value, $record->field($tag)->subfield($subfield);
2817 # warn "for publishercode, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
2820 # ... and on volume.
2821 ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblioitems.volume","");
2822 if ($record->field($tag)) {
2823 if ($record->field($tag)->subfields($subfield)) {
2824 push @tags, "'".$tag.$subfield."'";
2825 push @and_or, "and";
2826 push @excluding, "";
2827 push @operator, "=";
2828 push @value, $record->field($tag)->subfield($subfield);
2829 # warn "for volume, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
2833 my ($finalresult,$nbresult) = C4::SearchMarc::catalogsearch($dbh,\@tags,\@and_or,\@excluding,\@operator,\@value,0,10);
2834 # there is at least 1 result => return the 1st one
2836 # warn "$nbresult => ".@$finalresult[0]->{biblionumber},@$finalresult[0]->{bibid},@$finalresult[0]->{title};
2837 return @$finalresult[0]->{biblionumber},@$finalresult[0]->{bibid},@$finalresult[0]->{title};
2839 # no result, returns nothing
2846 if(substr($isbn, 0, 1) <=7) {
2847 $seg1 = substr($isbn, 0, 1);
2848 } elsif(substr($isbn, 0, 2) <= 94) {
2849 $seg1 = substr($isbn, 0, 2);
2850 } elsif(substr($isbn, 0, 3) <= 995) {
2851 $seg1 = substr($isbn, 0, 3);
2852 } elsif(substr($isbn, 0, 4) <= 9989) {
2853 $seg1 = substr($isbn, 0, 4);
2855 $seg1 = substr($isbn, 0, 5);
2857 my $x = substr($isbn, length($seg1));
2859 if(substr($x, 0, 2) <= 19) {
2860 # if(sTmp2 < 10) sTmp2 = "0" sTmp2;
2861 $seg2 = substr($x, 0, 2);
2862 } elsif(substr($x, 0, 3) <= 699) {
2863 $seg2 = substr($x, 0, 3);
2864 } elsif(substr($x, 0, 4) <= 8399) {
2865 $seg2 = substr($x, 0, 4);
2866 } elsif(substr($x, 0, 5) <= 89999) {
2867 $seg2 = substr($x, 0, 5);
2868 } elsif(substr($x, 0, 6) <= 9499999) {
2869 $seg2 = substr($x, 0, 6);
2871 $seg2 = substr($x, 0, 7);
2873 my $seg3=substr($x,length($seg2));
2874 $seg3=substr($seg3,0,length($seg3)-1) ;
2875 my $seg4 = substr($x, -1, 1);
2876 return "$seg1-$seg2-$seg3-$seg4";
2880 END { } # module clean-up code here (global destructor)
2886 Koha Developement team <info@koha.org>
2888 Paul POULAIN paul.poulain@free.fr
2894 # Revision 1.149 2006/02/25 20:30:32 kados
2895 # IMPORTANT: Paul, I've removed the decode_char routine because it's no
2896 # longer necessary. If we need to convert from MARC-8 for display, we should:
2899 # 2. do it with MARC::Charset
2901 # If you still need it, let me know and I'll put it back in.
2903 # Revision 1.148 2006/02/25 19:23:01 kados
2904 # cleaning up POD docs, deleting zebra_create as it's no longer used (
2905 # replaced by z3950_extended_services).
2907 # Revision 1.147 2006/02/25 19:09:59 kados
2908 # readding some lost subs
2910 # Revision 1.145 2006/02/22 01:02:39 kados
2911 # Replacing all calls to zebra_update with calls to
2912 # z3950_extended_services. More work coming, but it's
2915 # Revision 1.144 2006/02/20 14:22:38 kados
2918 # Revision 1.143 2006/02/20 13:26:11 kados
2919 # A new subroutine to handle Z39.50 extended services. You pass it a
2920 # connection object, service type, service options, and a record, and
2921 # it performs the service and handles any exception found.
2923 # Revision 1.142 2006/02/16 20:49:56 kados
2924 # destroy a connection after we're done -- we really should just have one
2925 # connection object and not destroy it until the whole transaction is
2926 # finished -- but this will do for now
2928 # Revision 1.141 2006/02/16 19:47:22 rangi
2929 # Trying to error trap a little more.
2931 # Revision 1.140 2006/02/14 21:36:03 kados
2932 # adding a 'use ZOOM' to biblio.pm, needed for non-mod_perl install.
2933 # also adding diagnostic error if not able to connect to Zebra
2935 # Revision 1.139 2006/02/14 19:53:25 rangi
2936 # Just a little missing my
2938 # Seems to be working great Paul, and I like what you did with zebradb
2940 # Revision 1.138 2006/02/14 11:25:22 tipaul
2941 # road to 3.0 : updating a biblio in zebra seems to work. Still working on it, there are probably some bugs !
2943 # Revision 1.137 2006/02/13 16:34:26 tipaul
2944 # fixing some warnings (perl -w should be quiet)
2946 # Revision 1.136 2006/01/10 17:01:29 tipaul
2947 # adding a XMLgetbiblio in Biblio.pm (1st draft, to use with zebra)
2949 # Revision 1.135 2006/01/06 16:39:37 tipaul
2950 # synch'ing head and rel_2_2 (from 2.2.5, including npl templates)
2951 # Seems not to break too many things, but i'm probably wrong here.
2952 # at least, new features/bugfixes from 2.2.5 are here (tested on some features on my head local copy)
2954 # - removing useless directories (koha-html and koha-plucene)
2956 # Revision 1.134 2006/01/04 15:54:55 tipaul
2957 # utf8 is a : go for beta test in HEAD.
2958 # some explanations :
2959 # - 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.
2960 # - *-top.inc will show the pages in utf8
2961 # - 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.
2962 # - using marcxml field and no more the iso2709 raw marc biblioitems.marc field.
2964 # Revision 1.133 2005/12/12 14:25:51 thd
2967 # Reverse array filled with elements from repeated subfields
2968 # to avoid last to first concatenation of elements in Koha DB.-
2970 # Revision 1.132 2005-10-26 09:12:33 tipaul
2971 # big commit, still breaking things...
2973 # * synch with rel_2_2. Probably the last non manual synch, as rel_2_2 should not be modified deeply.
2974 # * code cleaning (cleaning warnings from perl -w) continued
2976 # Revision 1.131 2005/09/22 10:01:45 tipaul
2977 # see mail on koha-devel : code cleaning on Search.pm + normalizing API + use of biblionumber everywhere (instead of bn, biblio, ...)
2979 # Revision 1.130 2005/09/02 14:34:14 tipaul
2980 # continuing the work to move to zebra. Begin of work for MARC=OFF support.
2981 # IMPORTANT NOTE : the MARCkoha2marc sub API has been modified. Instead of biblionumber & biblioitemnumber, it now gets a hash.
2982 # The sub is used only in Biblio.pm, so the API change should be harmless (except for me, but i'm aware ;-) )
2984 # Revision 1.129 2005/08/12 13:50:31 tipaul
2985 # removing useless sub declarations
2987 # Revision 1.128 2005/08/11 16:12:47 tipaul
2988 # Playing with the zebra...
2990 # * go to koha cvs home directory
2991 # * in misc/zebra there is a unimarc directory. I suggest that marc21 libraries create a marc21 directory
2992 # * put your zebra.cfg files here & create your database.
2993 # * from koha cvs home directory, ln -s misc/zebra/marc21 zebra (I mean create a symbolic link to YOUR zebra directory)
2994 # * now, everytime you add/modify a biblio/item your zebra DB is updated correctly.
2997 # * this uses a system call in perl. CPU consumming, but we are waiting for indexdata Perl/zoom
2998 # * deletion still not work
2999 # * UNIMARC zebra config files are provided in misc/zebra/unimarc directory. The most important line being :
3001 # recordId: (bib1,Local-number)
3005 # elm 090 Local-number -
3006 # elm 090/? Local-number -
3007 # elm 090/?/9 Local-number !:w
3009 # (090$9 being the field mapped to biblio.biblionumber in Koha)
3011 # Revision 1.127 2005/08/11 14:37:32 tipaul
3013 # * removing useless subs
3014 # * removing some subs that are also elsewhere
3015 # * 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)
3017 # Revision 1.126 2005/08/11 09:13:28 tipaul
3018 # just removing useless subs (a lot !!!) for code cleaning
3020 # Revision 1.125 2005/08/11 09:00:07 tipaul
3021 # Ok guys, this time, it seems that item add and modif begin working as expected...
3022 # Still a lot of bugs to fix, of course
3024 # Revision 1.124 2005/08/10 10:21:15 tipaul
3025 # continuing the road to zebra :
3026 # - the biblio add begins to work.
3027 # - the biblio modif begins to work.
3029 # (still without doing anything on zebra)
3030 # (no new change in updatedatabase)
3032 # Revision 1.123 2005/08/09 14:10:28 tipaul
3033 # 1st commit to go to zebra.
3034 # don't update your cvs if you want to have a working head...
3036 # this commit contains :
3037 # * 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...
3038 # * 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.
3039 # * other files : get rid of bibid and use biblionumber instead.
3042 # * does not do anything on zebra yet.
3043 # * if you rename marc_subfield_table, you can't search anymore.
3044 # * you can view a biblio & bibliodetails, go to MARC editor, but NOT save any modif.
3045 # * 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 ;-) )
3047 # 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
3048 # 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.
3050 # tipaul cutted previous commit notes