item rework: replaced AddBiblioAndItems
[koha.git] / C4 / Biblio.pm
old mode 100644 (file)
new mode 100755 (executable)
index 95d5a31..3871b12
@@ -27,20 +27,23 @@ use MARC::File::USMARC;
 use MARC::File::XML;
 use ZOOM;
 use C4::Koha;
-use C4::Date;
+use C4::Branch;
+use C4::Dates qw/format_date/;
 use C4::Log; # logaction
-
+use C4::ClassSource;
 use vars qw($VERSION @ISA @EXPORT);
 
-# set the version for version checking
-$VERSION = do { my @v = '$Revision$' =~ /\d+/g; shift(@v).".".join( "_", map { sprintf "%03d", $_ } @v ); };
+# TODO: fix version
+# $VERSION = ?;
 
 @ISA = qw( Exporter );
 
 # EXPORTED FUNCTIONS.
 
-# to add biblios or items
-push @EXPORT, qw( &AddBiblio &AddItem );
+# to add biblios
+push @EXPORT, qw( 
+  &AddBiblio
+);
 
 # to get something
 push @EXPORT, qw(
@@ -51,26 +54,14 @@ push @EXPORT, qw(
   &GetBiblioItemByBiblioNumber
   &GetBiblioFromItemNumber
   
-  &GetMarcItem
-  &GetItem
-  &GetItemInfosOf
-  &GetItemStatus
-  &GetItemLocation
-  &GetLostItems
-  &GetItemsForInventory
-  &GetItemsCount
-
   &GetMarcNotes
   &GetMarcSubjects
   &GetMarcBiblio
   &GetMarcAuthors
   &GetMarcSeries
+  GetMarcUrls
   &GetUsedMarcStructure
 
-  &GetItemsInfo
-  &GetItemsByBiblioitemnumber
-  &GetItemnumberFromBarcode
-  &get_itemnumbers_of
   &GetXmlBiblio
 
   &GetAuthorisedValueDesc
@@ -84,19 +75,13 @@ push @EXPORT, qw(
 # To modify something
 push @EXPORT, qw(
   &ModBiblio
-  &ModItem
-  &ModItemTransfer
   &ModBiblioframework
   &ModZebra
-  &ModItemInMarc
-  &ModItemInMarconefield
-  &ModDateLastSeen
 );
 
 # To delete something
 push @EXPORT, qw(
   &DelBiblio
-  &DelItem
 );
 
 # Internal functions
@@ -105,9 +90,6 @@ push @EXPORT, qw(
 # but don't use them unless you're a core developer ;-)
 push @EXPORT, qw(
   &ModBiblioMarc
-  &AddItemInMarc
-  &calculatelc
-  &itemcalculator
 );
 
 # Others functions
@@ -200,81 +182,49 @@ When modifying a biblio or an item, the behaviour is quite similar.
 =over 4
 
 ($biblionumber,$biblioitemnumber) = AddBiblio($record,$frameworkcode);
-Exported function (core API) for adding a new biblio to koha.
 
 =back
 
+Exported function (core API) for adding a new biblio to koha.
+
+The first argument is a C<MARC::Record> object containing the
+bib to add, while the second argument is the desired MARC
+framework code.
+
+This function also accepts a third, optional argument: a hashref
+to additional options.  The only defined option is C<defer_marc_save>,
+which if present and mapped to a true value, causes C<AddBiblio>
+to omit the call to save the MARC in C<bibilioitems.marc>
+and C<biblioitems.marcxml>  This option is provided B<only>
+for the use of scripts such as C<bulkmarcimport.pl> that may need
+to do some manipulation of the MARC record for item parsing before
+saving it and which cannot afford the performance hit of saving
+the MARC record twice.  Consequently, do not use that option
+unless you can guarantee that C<ModBiblioMarc> will be called.
+
 =cut
 
 sub AddBiblio {
-    my ( $record, $frameworkcode ) = @_;
-    my $biblionumber;
-    my $biblioitemnumber;
+    my $record = shift;
+    my $frameworkcode = shift;
+    my $options = @_ ? shift : undef;
+    my $defer_marc_save = 0;
+    if (defined $options and exists $options->{'defer_marc_save'} and $options->{'defer_marc_save'}) {
+        $defer_marc_save = 1;
+    }
+
+    my ($biblionumber,$biblioitemnumber,$error);
     my $dbh = C4::Context->dbh;
     # transform the data into koha-table style data
     my $olddata = TransformMarcToKoha( $dbh, $record, $frameworkcode );
-    $biblionumber = _koha_add_biblio( $dbh, $olddata, $frameworkcode );
+    ($biblionumber,$error) = _koha_add_biblio( $dbh, $olddata, $frameworkcode );
     $olddata->{'biblionumber'} = $biblionumber;
-    $biblioitemnumber = _koha_add_biblioitem( $dbh, $olddata );
+    ($biblioitemnumber,$error) = _koha_add_biblioitem( $dbh, $olddata );
 
-    # we must add bibnum and bibitemnum in MARC::Record...
-    # we build the new field with biblionumber and biblioitemnumber
-    # we drop the original field
-    # we add the new builded field.
-    ( my $biblio_tag, my $biblio_subfield ) = GetMarcFromKohaField("biblio.biblionumber",$frameworkcode);
-    ( my $biblioitem_tag, my $biblioitem_subfield ) = GetMarcFromKohaField("biblioitems.biblioitemnumber",$frameworkcode);
-
-    my $newfield;
-
-    # biblionumber & biblioitemnumber are in different fields
-    if ( $biblio_tag != $biblioitem_tag ) {
-
-        # deal with biblionumber
-        if ( $biblio_tag < 10 ) {
-            $newfield = MARC::Field->new( $biblio_tag, $biblionumber );
-        }
-        else {
-            $newfield =
-              MARC::Field->new( $biblio_tag, '', '',
-                "$biblio_subfield" => $biblionumber );
-        }
-
-        # drop old field and create new one...
-        my $old_field = $record->field($biblio_tag);
-        $record->delete_field($old_field);
-        $record->append_fields($newfield);
-
-        # deal with biblioitemnumber
-        if ( $biblioitem_tag < 10 ) {
-            $newfield = MARC::Field->new( $biblioitem_tag, $biblioitemnumber, );
-        }
-        else {
-            $newfield =
-              MARC::Field->new( $biblioitem_tag, '', '',
-                "$biblioitem_subfield" => $biblioitemnumber, );
-        }
-        # drop old field and create new one...
-        $old_field = $record->field($biblioitem_tag);
-        $record->delete_field($old_field);
-        $record->insert_fields_ordered($newfield);
-
-# biblionumber & biblioitemnumber are in the same field (can't be <10 as fields <10 have only 1 value)
-    }
-    else {
-        my $newfield = MARC::Field->new(
-            $biblio_tag, '', '',
-            "$biblio_subfield" => $biblionumber,
-            "$biblioitem_subfield" => $biblioitemnumber
-        );
-
-        # drop old field and create new one...
-        my $old_field = $record->field($biblio_tag);
-        $record->delete_field($old_field);
-        $record->insert_fields_ordered($newfield);
-    }
+    _koha_marc_update_bib_ids($record, $frameworkcode, $biblionumber, $biblioitemnumber);
 
     # now add the record
-    $biblionumber = ModBiblioMarc( $record, $biblionumber, $frameworkcode );
+    $biblionumber = ModBiblioMarc( $record, $biblionumber, $frameworkcode ) unless $defer_marc_save;
       
     &logaction(C4::Context->userenv->{'number'},"CATALOGUING","ADD",$biblionumber,"biblio") 
         if C4::Context->preference("CataloguingLog");
@@ -282,75 +232,6 @@ sub AddBiblio {
     return ( $biblionumber, $biblioitemnumber );
 }
 
-=head2 AddItem
-
-=over 2
-
-    $biblionumber = AddItem( $record, $biblionumber)
-    Exported function (core API) for adding a new item to Koha
-
-=back
-
-=cut
-
-sub AddItem {
-    my ( $record, $biblionumber ) = @_;
-    my $dbh = C4::Context->dbh;
-    
-    # add item in old-DB
-    my $frameworkcode = GetFrameworkCode( $biblionumber );
-    my $item = &TransformMarcToKoha( $dbh, $record, $frameworkcode );
-
-    # needs old biblionumber and biblioitemnumber
-    $item->{'biblionumber'} = $biblionumber;
-    my $sth =
-      $dbh->prepare(
-        "select biblioitemnumber,itemtype from biblioitems where biblionumber=?"
-      );
-    $sth->execute( $item->{'biblionumber'} );
-    my $itemtype;
-    ( $item->{'biblioitemnumber'}, $itemtype ) = $sth->fetchrow;
-    $sth =
-      $dbh->prepare(
-        "select notforloan from itemtypes where itemtype='$itemtype'");
-    $sth->execute();
-    my $notforloan = $sth->fetchrow;
-    ##Change the notforloan field if $notforloan found
-    if ( $notforloan > 0 ) {
-        $item->{'notforloan'} = $notforloan;
-        &MARCitemchange( $record, "items.notforloan", $notforloan );
-    }
-    if ( !$item->{'dateaccessioned'} || $item->{'dateaccessioned'} eq '' ) {
-
-        # find today's date
-        my ( $sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst ) =
-          localtime(time);
-        $year += 1900;
-        $mon  += 1;
-        my $date =
-          "$year-" . sprintf( "%0.2d", $mon ) . "-" . sprintf( "%0.2d", $mday );
-        $item->{'dateaccessioned'} = $date;
-        &MARCitemchange( $record, "items.dateaccessioned", $date );
-    }
-    my ( $itemnumber, $error ) =
-      &_koha_new_items( $dbh, $item, $item->{barcode} );
-
-    # add itemnumber to MARC::Record before adding the item.
-    $sth = $dbh->prepare(
-"select tagfield,tagsubfield from marc_subfield_structure where frameworkcode=? and kohafield=?"
-      );
-    &TransformKohaToMarcOneField( $sth, $record, "items.itemnumber", $itemnumber,
-        $frameworkcode );
-
-    # add the item
-    &AddItemInMarc( $record, $item->{'biblionumber'},$frameworkcode );
-    
-    &logaction(C4::Context->userenv->{'number'},"CATALOGUING","ADD",$itemnumber,"item") 
-        if C4::Context->preference("CataloguingLog");
-    
-    return ($item->{biblionumber}, $item->{biblioitemnumber},$itemnumber);
-}
-
 =head2 ModBiblio
 
     ModBiblio( $record,$biblionumber,$frameworkcode);
@@ -391,14 +272,15 @@ sub ModBiblio {
         $record->append_fields($field);
     }
     
-    # adding biblionumber
-    my ($tag_biblionumber, $subfield_biblionumber) = GetMarcFromKohaField('biblio.biblionumber',$frameworkcode);
-    $record->append_fields(
-           MARC::Field->new(
-                   $tag_biblionumber,'','',$subfield_biblionumber => $biblionumber
-           )
-    ) unless ($record->subfield($tag_biblionumber,$subfield_biblionumber));
-    
+    # update biblionumber and biblioitemnumber in MARC
+    # FIXME - this is assuming a 1 to 1 relationship between
+    # biblios and biblioitems
+    my $sth =  $dbh->prepare("select biblioitemnumber from biblioitems where biblionumber=?");
+    $sth->execute($biblionumber);
+    my ($biblioitemnumber) = $sth->fetchrow;
+    $sth->finish();
+    _koha_marc_update_bib_ids($record, $frameworkcode, $biblionumber, $biblioitemnumber);
+
     # update the MARC record (that now contains biblio and items) with the new record data
     &ModBiblioMarc( $record, $biblionumber, $frameworkcode );
     
@@ -406,75 +288,11 @@ sub ModBiblio {
     my $oldbiblio = TransformMarcToKoha( $dbh, $record, $frameworkcode );
 
     # modify the other koha tables
-    _koha_modify_biblio( $dbh, $oldbiblio );
-    _koha_modify_biblioitem( $dbh, $oldbiblio );
+    _koha_modify_biblio( $dbh, $oldbiblio, $frameworkcode );
+    _koha_modify_biblioitem_nonmarc( $dbh, $oldbiblio );
     return 1;
 }
 
-=head2 ModItem
-
-=over 2
-
-Exported function (core API) for modifying an item in Koha.
-
-=back
-
-=cut
-
-sub ModItem {
-    my ( $record, $biblionumber, $itemnumber, $delete, $new_item_hashref )
-      = @_;
-    
-    #logging
-    &logaction(C4::Context->userenv->{'number'},"CATALOGUING","MODIFY",$itemnumber,$record->as_formatted) 
-        if C4::Context->preference("CataloguingLog");
-      
-    my $dbh = C4::Context->dbh;
-    
-    # if we have a MARC record, we're coming from cataloging and so
-    # we do the whole routine: update the MARC and zebra, then update the koha
-    # tables
-    if ($record) {
-        my $frameworkcode = GetFrameworkCode( $biblionumber );
-        ModItemInMarc( $record, $biblionumber, $itemnumber, $frameworkcode );
-        my $olditem       = TransformMarcToKoha( $dbh, $record, $frameworkcode );
-        _koha_modify_item( $dbh, $olditem );
-        return $biblionumber;
-    }
-
-    # otherwise, we're just looking to modify something quickly
-    # (like a status) so we just update the koha tables
-    elsif ($new_item_hashref) {
-        _koha_modify_item( $dbh, $new_item_hashref );
-    }
-}
-
-sub ModItemTransfer {
-    my ( $itemnumber, $frombranch, $tobranch ) = @_;
-    
-    my $dbh = C4::Context->dbh;
-    
-    #new entry in branchtransfers....
-    my $sth = $dbh->prepare(
-        "INSERT INTO branchtransfers (itemnumber, frombranch, datesent, tobranch)
-        VALUES (?, ?, now(), ?)");
-    $sth->execute($itemnumber, $frombranch, $tobranch);
-    #update holdingbranch in items .....
-     $sth= $dbh->prepare(
-          "UPDATE items set holdingbranch = ? WHERE items.itemnumber = ?");
-    $sth->execute($tobranch,$itemnumber);
-    &ModDateLastSeen($itemnumber);
-    $sth = $dbh->prepare(
-        "SELECT biblionumber FROM items WHERE itemnumber=?"
-      );
-    $sth->execute($itemnumber);
-    while ( my ( $biblionumber ) = $sth->fetchrow ) {
-        &ModItemInMarconefield( $biblionumber, $itemnumber,
-            'items.holdingbranch', $tobranch );
-    }
-    return;
-}
-
 =head2 ModBiblioframework
 
     ModBiblioframework($biblionumber,$frameworkcode);
@@ -486,94 +304,12 @@ sub ModBiblioframework {
     my ( $biblionumber, $frameworkcode ) = @_;
     my $dbh = C4::Context->dbh;
     my $sth = $dbh->prepare(
-        "UPDATE biblio SET frameworkcode=? WHERE biblionumber=$biblionumber"
+        "UPDATE biblio SET frameworkcode=? WHERE biblionumber=?"
     );
-    $sth->execute($frameworkcode);
+    $sth->execute($frameworkcode, $biblionumber);
     return 1;
 }
 
-=head2 ModItemInMarconefield
-
-=over
-
-modify only 1 field in a MARC item (mainly used for holdingbranch, but could also be used for status modif - moving a book to "lost" on a long overdu for example)
-&ModItemInMarconefield( $biblionumber, $itemnumber, $itemfield, $newvalue )
-
-=back
-
-=cut
-
-sub ModItemInMarconefield {
-    my ( $biblionumber, $itemnumber, $itemfield, $newvalue ) = @_;
-    my $dbh = C4::Context->dbh;
-    if ( !defined $newvalue ) {
-        $newvalue = "";
-    }
-
-    my $record = GetMarcItem( $biblionumber, $itemnumber );
-    my ($tagfield, $tagsubfield) = GetMarcFromKohaField( $itemfield,'');
-    if ($tagfield && $tagsubfield) {
-        my $tag = $record->field($tagfield);
-        if ($tag) {
-#             my $tagsubs = $record->field($tagfield)->subfield($tagsubfield);
-            $tag->update( $tagsubfield => $newvalue );
-            $record->delete_field($tag);
-            $record->insert_fields_ordered($tag);
-            &ModItemInMarc( $record, $biblionumber, $itemnumber, 0 );
-        }
-    }
-}
-
-=head2 ModItemInMarc
-
-=over
-
-&ModItemInMarc( $record, $biblionumber, $itemnumber )
-
-=back
-
-=cut
-
-sub ModItemInMarc {
-    my ( $ItemRecord, $biblionumber, $itemnumber, $frameworkcode) = @_;
-    my $dbh = C4::Context->dbh;
-    
-    # get complete MARC record & replace the item field by the new one
-    my $completeRecord = GetMarcBiblio($biblionumber);
-    my ($itemtag,$itemsubfield) = GetMarcFromKohaField("items.itemnumber",$frameworkcode);
-    my $itemField = $ItemRecord->field($itemtag);
-    my @items = $completeRecord->field($itemtag);
-    foreach (@items) {
-        if ($_->subfield($itemsubfield) eq $itemnumber) {
-#             $completeRecord->delete_field($_);
-            $_->replace_with($itemField);
-        }
-    }
-    # save the record
-    my $sth = $dbh->prepare("update biblioitems set marc=?,marcxml=?  where biblionumber=?");
-    $sth->execute( $completeRecord->as_usmarc(), $completeRecord->as_xml_record(),$biblionumber );
-    $sth->finish;
-    ModZebra($biblionumber,"specialUpdate","biblioserver",$completeRecord);
-}
-
-=head2 ModDateLastSeen
-
-&ModDateLastSeen($itemnum)
-Mark item as seen. Is called when an item is issued, returned or manually marked during inventory/stocktaking
-C<$itemnum> is the item number
-
-=cut
-
-sub ModDateLastSeen {
-    my ($itemnum) = @_;
-    my $dbh       = C4::Context->dbh;
-    my $sth       =
-      $dbh->prepare(
-          "update items set itemlost=0, datelastseen  = now() where items.itemnumber = ?"
-      );
-    $sth->execute($itemnum);
-    return;
-}
 =head2 DelBiblio
 
 =over
@@ -594,26 +330,15 @@ sub DelBiblio {
     my ( $biblionumber ) = @_;
     my $dbh = C4::Context->dbh;
     my $error;    # for error handling
-
-    # First make sure there are no items with issues are still attached
-    my $sth =
-      $dbh->prepare(
-        "SELECT itemnumber FROM items WHERE biblionumber=?");
+    
+    # First make sure this biblio has no items attached
+    my $sth = $dbh->prepare("SELECT itemnumber FROM items WHERE biblionumber=?");
     $sth->execute($biblionumber);
-    while ( my $itemnumber = $sth->fetchrow ) {
-        my $issues = GetItemIssues($itemnumber);
-        foreach my $issue (@$issues) {
-            if (   ( $issue->{date_due} )
-                && ( $issue->{date_due} ne "Available" ) )
-            {
-
-#FIXME: we need a status system in Biblio like in Circ to return standard codes and messages
-# instead of hard-coded strings
-                $error .=
-"Item is checked out to a patron -- you must return it before deleting the Biblio";
-            }
-        }
+    if (my $itemnumber = $sth->fetchrow){
+        # Fix this to use a status the template can understand
+        $error .= "This Biblio has items attached, please delete them first before deleting this biblio ";
     }
+
     return $error if $error;
 
     # Delete in Zebra. Be careful NOT to move this line after _koha_delete_biblio
@@ -621,10 +346,7 @@ sub DelBiblio {
     # - we need to read the biblio if NoZebra is set (to remove it from the indexes
     # - if something goes wrong, the biblio may be deleted from Koha but not from zebra
     #   and we would have no way to remove it (except manually in zebra, but I bet it would be very hard to handle the problem)
-    ModZebra($biblionumber, "delete_record", "biblioserver", undef);
-
-    # delete biblio from Koha tables and save in deletedbiblio
-    $error = &_koha_delete_biblio( $dbh, $biblionumber );
+    ModZebra($biblionumber, "recordDelete", "biblioserver", undef);
 
     # delete biblioitems and items from Koha tables and save in deletedbiblioitems,deleteditems
     $sth =
@@ -634,60 +356,19 @@ sub DelBiblio {
     while ( my $biblioitemnumber = $sth->fetchrow ) {
 
         # delete this biblioitem
-        $error = &_koha_delete_biblioitems( $dbh, $biblioitemnumber );
+        $error = _koha_delete_biblioitems( $dbh, $biblioitemnumber );
         return $error if $error;
-
-        # delete items
-        my $items_sth =
-          $dbh->prepare(
-            "SELECT itemnumber FROM items WHERE biblioitemnumber=?");
-        $items_sth->execute($biblioitemnumber);
-        while ( my $itemnumber = $items_sth->fetchrow ) {
-            $error = &_koha_delete_item( $dbh, $itemnumber );
-            return $error if $error;
-        }
     }
-    &logaction(C4::Context->userenv->{'number'},"CATALOGUING","DELETE",$biblionumber,"") 
-        if C4::Context->preference("CataloguingLog");
-    return;
-}
-
-=head2 DelItem
-
-=over
-
-DelItem( $biblionumber, $itemnumber );
-Exported function (core API) for deleting an item record in Koha.
-
-=back
-
-=cut
 
-sub DelItem {
-    my ( $biblionumber, $itemnumber ) = @_;
-    my $dbh = C4::Context->dbh;
-    &_koha_delete_item( $dbh, $itemnumber );
-    # get the MARC record
-    my $record = GetMarcBiblio($biblionumber);
-    my $frameworkcode = GetFrameworkCode($biblionumber);
-
-    # backup the record
-    my $copy2deleted =
-      $dbh->prepare("UPDATE deleteditems SET marc=? WHERE itemnumber=?");
-    $copy2deleted->execute( $record->as_usmarc(), $itemnumber );
+    # delete biblio from Koha tables and save in deletedbiblio
+    # must do this *after* _koha_delete_biblioitems, otherwise
+    # delete cascade will prevent deletedbiblioitems rows
+    # from being generated by _koha_delete_biblioitems
+    $error = _koha_delete_biblio( $dbh, $biblionumber );
 
-    #search item field code
-    my ( $itemtag, $itemsubfield ) = GetMarcFromKohaField("items.itemnumber",$frameworkcode);
-    my @fields = $record->field($itemtag);
-    # delete the item specified
-    foreach my $field (@fields) {
-        if ( $field->subfield($itemsubfield) eq $itemnumber ) {
-            $record->delete_field($field);
-        }
-    }
-    &ModBiblioMarc( $record, $biblionumber, $frameworkcode );
-    &logaction(C4::Context->userenv->{'number'},"CATALOGUING","DELETE",$itemnumber,"item") 
+    &logaction(C4::Context->userenv->{'number'},"CATALOGUING","DELETE",$biblionumber,"") 
         if C4::Context->preference("CataloguingLog");
+    return;
 }
 
 =head2 GetBiblioData
@@ -712,14 +393,21 @@ sub GetBiblioData {
     my ( $bibnum ) = @_;
     my $dbh = C4::Context->dbh;
 
-    my $query = "
-        SELECT * , biblioitems.notes AS bnotes, biblio.notes
-        FROM biblio
+  #  my $query =  C4::Context->preference('item-level_itypes') ? 
+    #   " SELECT * , biblioitems.notes AS bnotes, biblio.notes
+    #       FROM biblio
+    #        LEFT JOIN biblioitems ON biblio.biblionumber = biblioitems.biblionumber
+    #       WHERE biblio.biblionumber = ?
+    #        AND biblioitems.biblionumber = biblio.biblionumber
+    #";
+    
+    my $query = " SELECT * , biblioitems.notes AS bnotes, itemtypes.notforloan as bi_notforloan, biblio.notes
+            FROM biblio
             LEFT JOIN biblioitems ON biblio.biblionumber = biblioitems.biblionumber
             LEFT JOIN itemtypes ON biblioitems.itemtype = itemtypes.itemtype
-        WHERE biblio.biblionumber = ?
-            AND biblioitems.biblionumber = biblio.biblionumber
-    ";
+            WHERE biblio.biblionumber = ?
+            AND biblioitems.biblionumber = biblio.biblionumber ";
+         
     my $sth = $dbh->prepare($query);
     $sth->execute($bibnum);
     my $data;
@@ -729,437 +417,6 @@ sub GetBiblioData {
     return ($data);
 }    # sub GetBiblioData
 
-
-=head2 GetItemsInfo
-
-=over 4
-
-  @results = &GetItemsInfo($biblionumber, $type);
-
-Returns information about books with the given biblionumber.
-
-C<$type> may be either C<intra> or anything else. If it is not set to
-C<intra>, then the search will exclude lost, very overdue, and
-withdrawn items.
-
-C<&GetItemsInfo> returns a list of references-to-hash. Each element
-contains a number of keys. Most of them are table items from the
-C<biblio>, C<biblioitems>, C<items>, and C<itemtypes> tables in the
-Koha database. Other keys include:
-
-=over 4
-
-=item C<$data-E<gt>{branchname}>
-
-The name (not the code) of the branch to which the book belongs.
-
-=item C<$data-E<gt>{datelastseen}>
-
-This is simply C<items.datelastseen>, except that while the date is
-stored in YYYY-MM-DD format in the database, here it is converted to
-DD/MM/YYYY format. A NULL date is returned as C<//>.
-
-=item C<$data-E<gt>{datedue}>
-
-=item C<$data-E<gt>{class}>
-
-This is the concatenation of C<biblioitems.classification>, the book's
-Dewey code, and C<biblioitems.subclass>.
-
-=item C<$data-E<gt>{ocount}>
-
-I think this is the number of copies of the book available.
-
-=item C<$data-E<gt>{order}>
-
-If this is set, it is set to C<One Order>.
-
-=back
-
-=back
-
-=cut
-
-sub GetItemsInfo {
-    my ( $biblionumber, $type ) = @_;
-    my $dbh   = C4::Context->dbh;
-    my $query = "SELECT *,items.notforloan as itemnotforloan
-                 FROM items 
-                 LEFT JOIN biblio ON biblio.biblionumber = items.biblionumber
-                 LEFT JOIN biblioitems ON biblioitems.biblioitemnumber = items.biblioitemnumber
-                 LEFT JOIN itemtypes on biblioitems.itemtype = itemtypes.itemtype
-                WHERE items.biblionumber = ?
-                ORDER BY items.dateaccessioned desc
-                 ";
-    my $sth = $dbh->prepare($query);
-    $sth->execute($biblionumber);
-    my $i = 0;
-    my @results;
-    my ( $date_due, $count_reserves );
-
-    while ( my $data = $sth->fetchrow_hashref ) {
-        my $datedue = '';
-        my $isth    = $dbh->prepare(
-            "SELECT issues.*,borrowers.cardnumber,borrowers.surname,borrowers.firstname
-            FROM   issues LEFT JOIN borrowers ON issues.borrowernumber=borrowers.borrowernumber
-            WHERE  itemnumber = ?
-                AND returndate IS NULL"
-        );
-        $isth->execute( $data->{'itemnumber'} );
-        if ( my $idata = $isth->fetchrow_hashref ) {
-            $data->{borrowernumber} = $idata->{borrowernumber};
-            $data->{cardnumber}     = $idata->{cardnumber};
-            $data->{surname}     = $idata->{surname};
-            $data->{firstname}     = $idata->{firstname};
-            $datedue                = format_date( $idata->{'date_due'} );
-        }
-        if ( $datedue eq '' ) {
-            #$datedue="Available";
-            my ( $restype, $reserves ) =
-              C4::Reserves::CheckReserves( $data->{'itemnumber'} );
-            if ($restype) {
-
-                #$datedue=$restype;
-                $count_reserves = $restype;
-            }
-        }
-        $isth->finish;
-
-        #get branch information.....
-        my $bsth = $dbh->prepare(
-            "SELECT * FROM branches WHERE branchcode = ?
-        "
-        );
-        $bsth->execute( $data->{'holdingbranch'} );
-        if ( my $bdata = $bsth->fetchrow_hashref ) {
-            $data->{'branchname'} = $bdata->{'branchname'};
-        }
-        my $date = format_date( $data->{'datelastseen'} );
-        $data->{'datelastseen'}   = $date;
-        $data->{'datedue'}        = $datedue;
-        $data->{'count_reserves'} = $count_reserves;
-
-        # get notforloan complete status if applicable
-        my $sthnflstatus = $dbh->prepare(
-            'SELECT authorised_value
-            FROM   marc_subfield_structure
-            WHERE  kohafield="items.notforloan"
-        '
-        );
-
-        $sthnflstatus->execute;
-        my ($authorised_valuecode) = $sthnflstatus->fetchrow;
-        if ($authorised_valuecode) {
-            $sthnflstatus = $dbh->prepare(
-                "SELECT lib FROM authorised_values
-                 WHERE  category=?
-                 AND authorised_value=?"
-            );
-            $sthnflstatus->execute( $authorised_valuecode,
-                $data->{itemnotforloan} );
-            my ($lib) = $sthnflstatus->fetchrow;
-            $data->{notforloan} = $lib;
-        }
-
-        # my stack procedures
-        my $stackstatus = $dbh->prepare(
-            'SELECT authorised_value
-             FROM   marc_subfield_structure
-             WHERE  kohafield="items.stack"
-        '
-        );
-        $stackstatus->execute;
-
-        ($authorised_valuecode) = $stackstatus->fetchrow;
-        if ($authorised_valuecode) {
-            $stackstatus = $dbh->prepare(
-                "SELECT lib
-                 FROM   authorised_values
-                 WHERE  category=?
-                 AND    authorised_value=?
-            "
-            );
-            $stackstatus->execute( $authorised_valuecode, $data->{stack} );
-            my ($lib) = $stackstatus->fetchrow;
-            $data->{stack} = $lib;
-        }
-        $results[$i] = $data;
-        $i++;
-    }
-    $sth->finish;
-
-    return (@results);
-}
-
-=head2 getitemstatus
-
-=over 4
-
-$itemstatushash = &getitemstatus($fwkcode);
-returns information about status.
-Can be MARC dependant.
-fwkcode is optional.
-But basically could be can be loan or not
-Create a status selector with the following code
-
-=head3 in PERL SCRIPT
-
-my $itemstatushash = getitemstatus;
-my @itemstatusloop;
-foreach my $thisstatus (keys %$itemstatushash) {
-    my %row =(value => $thisstatus,
-                statusname => $itemstatushash->{$thisstatus}->{'statusname'},
-            );
-    push @itemstatusloop, \%row;
-}
-$template->param(statusloop=>\@itemstatusloop);
-
-
-=head3 in TEMPLATE
-
-            <select name="statusloop">
-                <option value="">Default</option>
-            <!-- TMPL_LOOP name="statusloop" -->
-                <option value="<!-- TMPL_VAR name="value" -->" <!-- TMPL_IF name="selected" -->selected<!-- /TMPL_IF -->><!-- TMPL_VAR name="statusname" --></option>
-            <!-- /TMPL_LOOP -->
-            </select>
-
-=cut
-
-sub GetItemStatus {
-
-    # returns a reference to a hash of references to status...
-    my ($fwk) = @_;
-    my %itemstatus;
-    my $dbh = C4::Context->dbh;
-    my $sth;
-    $fwk = '' unless ($fwk);
-    my ( $tag, $subfield ) =
-      GetMarcFromKohaField( "items.notforloan", $fwk );
-    if ( $tag and $subfield ) {
-        my $sth =
-          $dbh->prepare(
-"select authorised_value from marc_subfield_structure where tagfield=? and tagsubfield=? and frameworkcode=?"
-          );
-        $sth->execute( $tag, $subfield, $fwk );
-        if ( my ($authorisedvaluecat) = $sth->fetchrow ) {
-            my $authvalsth =
-              $dbh->prepare(
-"select authorised_value, lib from authorised_values where category=? order by lib"
-              );
-            $authvalsth->execute($authorisedvaluecat);
-            while ( my ( $authorisedvalue, $lib ) = $authvalsth->fetchrow ) {
-                $itemstatus{$authorisedvalue} = $lib;
-            }
-            $authvalsth->finish;
-            return \%itemstatus;
-            exit 1;
-        }
-        else {
-
-            #No authvalue list
-            # build default
-        }
-        $sth->finish;
-    }
-
-    #No authvalue list
-    #build default
-    $itemstatus{"1"} = "Not For Loan";
-    return \%itemstatus;
-}
-
-=head2 getitemlocation
-
-=over 4
-
-$itemlochash = &getitemlocation($fwk);
-returns informations about location.
-where fwk stands for an optional framework code.
-Create a location selector with the following code
-
-=head3 in PERL SCRIPT
-
-my $itemlochash = getitemlocation;
-my @itemlocloop;
-foreach my $thisloc (keys %$itemlochash) {
-    my $selected = 1 if $thisbranch eq $branch;
-    my %row =(locval => $thisloc,
-                selected => $selected,
-                locname => $itemlochash->{$thisloc},
-            );
-    push @itemlocloop, \%row;
-}
-$template->param(itemlocationloop => \@itemlocloop);
-
-=head3 in TEMPLATE
-
-<select name="location">
-    <option value="">Default</option>
-<!-- TMPL_LOOP name="itemlocationloop" -->
-    <option value="<!-- TMPL_VAR name="locval" -->" <!-- TMPL_IF name="selected" -->selected<!-- /TMPL_IF -->><!-- TMPL_VAR name="locname" --></option>
-<!-- /TMPL_LOOP -->
-</select>
-
-=back
-
-=cut
-
-sub GetItemLocation {
-
-    # returns a reference to a hash of references to location...
-    my ($fwk) = @_;
-    my %itemlocation;
-    my $dbh = C4::Context->dbh;
-    my $sth;
-    $fwk = '' unless ($fwk);
-    my ( $tag, $subfield ) =
-      GetMarcFromKohaField( "items.location", $fwk );
-    if ( $tag and $subfield ) {
-        my $sth =
-          $dbh->prepare(
-"select authorised_value from marc_subfield_structure where tagfield=? and tagsubfield=? and frameworkcode=?"
-          );
-        $sth->execute( $tag, $subfield, $fwk );
-        if ( my ($authorisedvaluecat) = $sth->fetchrow ) {
-            my $authvalsth =
-              $dbh->prepare(
-"select authorised_value, lib from authorised_values where category=? order by lib"
-              );
-            $authvalsth->execute($authorisedvaluecat);
-            while ( my ( $authorisedvalue, $lib ) = $authvalsth->fetchrow ) {
-                $itemlocation{$authorisedvalue} = $lib;
-            }
-            $authvalsth->finish;
-            return \%itemlocation;
-            exit 1;
-        }
-        else {
-
-            #No authvalue list
-            # build default
-        }
-        $sth->finish;
-    }
-
-    #No authvalue list
-    #build default
-    $itemlocation{"1"} = "Not For Loan";
-    return \%itemlocation;
-}
-
-=head2 GetLostItems
-
-$items = GetLostItems($where,$orderby);
-
-This function get the items lost into C<$items>.
-
-=over 2
-
-=item input:
-C<$where> is a hashref. it containts a field of the items table as key
-and the value to match as value.
-C<$orderby> is a field of the items table.
-
-=item return:
-C<$items> is a reference to an array full of hasref which keys are items' table column.
-
-=item usage in the perl script:
-
-my %where;
-$where{barcode} = 0001548;
-my $items = GetLostItems( \%where, "homebranch" );
-$template->param(itemsloop => $items);
-
-=back
-
-=cut
-
-sub GetLostItems {
-    # Getting input args.
-    my $where   = shift;
-    my $orderby = shift;
-    my $dbh     = C4::Context->dbh;
-
-    my $query   = "
-        SELECT *
-        FROM   items
-        WHERE  itemlost IS NOT NULL
-          AND  itemlost <> 0
-    ";
-    foreach my $key (keys %$where) {
-        $query .= " AND " . $key . " LIKE '%" . $where->{$key} . "%'";
-    }
-    $query .= " ORDER BY ".$orderby if defined $orderby;
-
-    my $sth = $dbh->prepare($query);
-    $sth->execute;
-    my @items;
-    while ( my $row = $sth->fetchrow_hashref ){
-        push @items, $row;
-    }
-    return \@items;
-}
-
-=head2 GetItemsForInventory
-
-$itemlist = GetItemsForInventory($minlocation,$maxlocation,$datelastseen,$offset,$size)
-
-Retrieve a list of title/authors/barcode/callnumber, for biblio inventory.
-
-The sub returns a list of hashes, containing itemnumber, author, title, barcode & item callnumber.
-It is ordered by callnumber,title.
-
-The minlocation & maxlocation parameters are used to specify a range of item callnumbers
-the datelastseen can be used to specify that you want to see items not seen since a past date only.
-offset & size can be used to retrieve only a part of the whole listing (defaut behaviour)
-
-=cut
-
-sub GetItemsForInventory {
-    my ( $minlocation, $maxlocation,$location, $datelastseen, $branch, $offset, $size ) = @_;
-    my $dbh = C4::Context->dbh;
-    my $sth;
-    if ($datelastseen) {
-        $datelastseen=format_date_in_iso($datelastseen);  
-        my $query =
-                "SELECT itemnumber,barcode,itemcallnumber,title,author,biblio.biblionumber,datelastseen
-                 FROM items
-                   LEFT JOIN biblio ON items.biblionumber=biblio.biblionumber 
-                 WHERE itemcallnumber>= ?
-                   AND itemcallnumber <=?
-                   AND (datelastseen< ? OR datelastseen IS NULL)";
-        $query.= " AND items.location=".$dbh->quote($location) if $location;
-        $query.= " AND items.homebranch=".$dbh->quote($branch) if $branch;
-        $query .= " ORDER BY itemcallnumber,title";
-        $sth = $dbh->prepare($query);
-        $sth->execute( $minlocation, $maxlocation, $datelastseen );
-    }
-    else {
-        my $query ="
-                SELECT itemnumber,barcode,itemcallnumber,biblio.biblionumber,title,author,datelastseen
-                FROM items 
-                  LEFT JOIN biblio ON items.biblionumber=biblio.biblionumber 
-                WHERE itemcallnumber>= ?
-                  AND itemcallnumber <=?";
-        $query.= " AND items.location=".$dbh->quote($location) if $location;
-        $query.= " AND items.homebranch=".$dbh->quote($branch) if $branch;
-        $query .= " ORDER BY itemcallnumber,title";
-        $sth = $dbh->prepare($query);
-        $sth->execute( $minlocation, $maxlocation );
-    }
-    my @results;
-    while ( my $row = $sth->fetchrow_hashref ) {
-        $offset-- if ($offset);
-        $row->{datelastseen}=format_date($row->{datelastseen});
-        if ( ( !$offset ) && $size ) {
-            push @results, $row;
-            $size--;
-        }
-    }
-    return \@results;
-}
-
 =head2 &GetBiblioItemData
 
 =over 4
@@ -1177,43 +434,23 @@ that C<biblioitems.notes> is given as C<$itemdata-E<gt>{bnotes}>.
 
 #'
 sub GetBiblioItemData {
-    my ($bibitem) = @_;
+    my ($biblioitemnumber) = @_;
     my $dbh       = C4::Context->dbh;
-    my $sth       =
-      $dbh->prepare(
-"Select *,biblioitems.notes as bnotes from biblioitems, biblio,itemtypes where biblio.biblionumber = biblioitems.biblionumber and biblioitemnumber = ? and biblioitems.itemtype = itemtypes.itemtype"
-      );
+    my $query = "SELECT *,biblioitems.notes AS bnotes
+        FROM biblio, biblioitems ";
+    unless(C4::Context->preference('item-level_itypes')) { 
+        $query .= "LEFT JOIN itemtypes on biblioitems.itemtype=itemtypes.itemtype ";
+    }    
+    $query .= " WHERE biblio.biblionumber = biblioitems.biblionumber 
+        AND biblioitemnumber = ? ";
+    my $sth       =  $dbh->prepare($query);
     my $data;
-
-    $sth->execute($bibitem);
-
+    $sth->execute($biblioitemnumber);
     $data = $sth->fetchrow_hashref;
-
     $sth->finish;
     return ($data);
 }    # sub &GetBiblioItemData
 
-=head2 GetItemnumberFromBarcode
-
-=over 4
-
-$result = GetItemnumberFromBarcode($barcode);
-
-=back
-
-=cut
-
-sub GetItemnumberFromBarcode {
-    my ($barcode) = @_;
-    my $dbh = C4::Context->dbh;
-
-    my $rq =
-      $dbh->prepare("SELECT itemnumber from items where items.barcode=?");
-    $rq->execute($barcode);
-    my ($result) = $rq->fetchrow;
-    return ($result);
-}
-
 =head2 GetBiblioItemByBiblioNumber
 
 =over 4
@@ -1227,7 +464,7 @@ NOTE : This function has been copy/paste from C4/Biblio.pm from head before zebr
 sub GetBiblioItemByBiblioNumber {
     my ($biblionumber) = @_;
     my $dbh = C4::Context->dbh;
-    my $sth = $dbh->prepare("Select * from biblioitems where biblionumber = ?");
+    my $sth = $dbh->prepare("Select * FROM biblioitems WHERE biblionumber = ?");
     my $count = 0;
     my @results;
 
@@ -1245,9 +482,9 @@ sub GetBiblioItemByBiblioNumber {
 
 =over 4
 
-$item = &GetBiblioFromItemNumber($itemnumber);
+$item = &GetBiblioFromItemNumber($itemnumber,$barcode);
 
-Looks up the item with the given itemnumber.
+Looks up the item with the given itemnumber. if undef, try the barcode.
 
 C<&itemnodata> returns a reference-to-hash whose keys are the fields
 from the C<biblio>, C<biblioitems>, and C<items> tables in the Koha
@@ -1259,16 +496,22 @@ database.
 
 #'
 sub GetBiblioFromItemNumber {
-    my ( $itemnumber ) = @_;
+    my ( $itemnumber, $barcode ) = @_;
     my $dbh = C4::Context->dbh;
-    my $sth = $dbh->prepare(
-        "SELECT * FROM items 
-        LEFT JOIN biblio ON biblio.biblionumber = items.biblionumber
-        LEFT JOIN biblioitems ON biblioitems.biblioitemnumber = items.biblioitemnumber
-         WHERE items.itemnumber = ?"
-    );
-
-    $sth->execute($itemnumber);
+    my $sth;
+    if($itemnumber) {
+        $sth=$dbh->prepare(  "SELECT * FROM items 
+            LEFT JOIN biblio ON biblio.biblionumber = items.biblionumber
+            LEFT JOIN biblioitems ON biblioitems.biblioitemnumber = items.biblioitemnumber
+             WHERE items.itemnumber = ?") ; 
+        $sth->execute($itemnumber);
+    } else {
+        $sth=$dbh->prepare(  "SELECT * FROM items 
+            LEFT JOIN biblio ON biblio.biblionumber = items.biblionumber
+            LEFT JOIN biblioitems ON biblioitems.biblioitemnumber = items.biblioitemnumber
+             WHERE items.barcode = ?") ; 
+        $sth->execute($barcode);
+    }
     my $data = $sth->fetchrow_hashref;
     $sth->finish;
     return ($data);
@@ -1287,7 +530,7 @@ sub GetBiblioFromItemNumber {
 sub GetBiblio {
     my ($biblionumber) = @_;
     my $dbh = C4::Context->dbh;
-    my $sth = $dbh->prepare("Select * from biblio where biblionumber = ?");
+    my $sth = $dbh->prepare("SELECT * FROM biblio WHERE biblionumber = ?");
     my $count = 0;
     my @results;
     $sth->execute($biblionumber);
@@ -1299,161 +542,6 @@ sub GetBiblio {
     return ( $count, @results );
 }    # sub GetBiblio
 
-=head2 GetItem
-
-=over 4
-
-$data = &GetItem($itemnumber,$barcode);
-
-return Item information, for a given itemnumber or barcode
-
-=back
-
-=cut
-
-sub GetItem {
-    my ($itemnumber,$barcode) = @_;
-    my $dbh = C4::Context->dbh;
-    if ($itemnumber) {
-        my $sth = $dbh->prepare("
-            SELECT * FROM items 
-            WHERE itemnumber = ?");
-        $sth->execute($itemnumber);
-        my $data = $sth->fetchrow_hashref;
-        return $data;
-    } else {
-        my $sth = $dbh->prepare("
-            SELECT * FROM items 
-            WHERE barcode = ?"
-            );
-        $sth->execute($barcode);
-        my $data = $sth->fetchrow_hashref;
-        return $data;
-    }
-}    # sub GetItem
-
-=head2 get_itemnumbers_of
-
-=over 4
-
-my @itemnumbers_of = get_itemnumbers_of(@biblionumbers);
-
-Given a list of biblionumbers, return the list of corresponding itemnumbers
-for each biblionumber.
-
-Return a reference on a hash where keys are biblionumbers and values are
-references on array of itemnumbers.
-
-=back
-
-=cut
-
-sub get_itemnumbers_of {
-    my @biblionumbers = @_;
-
-    my $dbh = C4::Context->dbh;
-
-    my $query = '
-        SELECT itemnumber,
-            biblionumber
-        FROM items
-        WHERE biblionumber IN (?' . ( ',?' x scalar @biblionumbers - 1 ) . ')
-    ';
-    my $sth = $dbh->prepare($query);
-    $sth->execute(@biblionumbers);
-
-    my %itemnumbers_of;
-
-    while ( my ( $itemnumber, $biblionumber ) = $sth->fetchrow_array ) {
-        push @{ $itemnumbers_of{$biblionumber} }, $itemnumber;
-    }
-
-    return \%itemnumbers_of;
-}
-
-=head2 GetItemInfosOf
-
-=over 4
-
-GetItemInfosOf(@itemnumbers);
-
-=back
-
-=cut
-
-sub GetItemInfosOf {
-    my @itemnumbers = @_;
-
-    my $query = '
-        SELECT *
-        FROM items
-        WHERE itemnumber IN (' . join( ',', @itemnumbers ) . ')
-    ';
-    return get_infos_of( $query, 'itemnumber' );
-}
-
-=head2 GetItemsByBiblioitemnumber
-
-=over 4
-
-GetItemsByBiblioitemnumber($biblioitemnumber);
-
-Returns an arrayref of hashrefs suitable for use in a TMPL_LOOP
-Called by moredetail.pl
-
-=back
-
-=cut
-
-sub GetItemsByBiblioitemnumber {
-       my ( $bibitem ) = @_;
-       my $dbh = C4::Context->dbh;
-       my $sth = $dbh->prepare("SELECT * FROM items WHERE items.biblioitemnumber = ?") || die $dbh->errstr;
-       # Get all items attached to a biblioitem
-    my $i = 0;
-    my @results; 
-    $sth->execute($bibitem) || die $sth->errstr;
-    while ( my $data = $sth->fetchrow_hashref ) {  
-               # Foreach item, get circulation information
-               my $sth2 = $dbh->prepare( "SELECT * FROM issues,borrowers
-                                   WHERE itemnumber = ?
-                                   AND returndate is NULL
-                                   AND issues.borrowernumber = borrowers.borrowernumber"
-        );
-        $sth2->execute( $data->{'itemnumber'} );
-        if ( my $data2 = $sth2->fetchrow_hashref ) {
-                       # if item is out, set the due date and who it is out too
-                       $data->{'date_due'}   = $data2->{'date_due'};
-                       $data->{'cardnumber'} = $data2->{'cardnumber'};
-                       $data->{'borrowernumber'}   = $data2->{'borrowernumber'};
-               }
-        else {
-                       # set date_due to blank, so in the template we check itemlost, and wthdrawn 
-                       $data->{'date_due'} = '';                                                                                                         
-               }    # else         
-        $sth2->finish;
-        # Find the last 3 people who borrowed this item.                  
-        my $query2 = "SELECT * FROM issues, borrowers WHERE itemnumber = ?
-                      AND issues.borrowernumber = borrowers.borrowernumber
-                      AND returndate is not NULL
-                      ORDER BY returndate desc,timestamp desc LIMIT 3";
-        $sth2 = $dbh->prepare($query2) || die $dbh->errstr;
-        $sth2->execute( $data->{'itemnumber'} ) || die $sth2->errstr;
-        my $i2 = 0;
-        while ( my $data2 = $sth2->fetchrow_hashref ) {
-                       $data->{"timestamp$i2"} = $data2->{'timestamp'};
-                       $data->{"card$i2"}      = $data2->{'cardnumber'};
-                       $data->{"borrower$i2"}  = $data2->{'borrowernumber'};
-                       $i2++;
-               }
-        $sth2->finish;
-        push(@results,$data);
-    } 
-    $sth->finish;
-    return (\@results); 
-}
-
-
 =head2 GetBiblioItemInfosOf
 
 =over 4
@@ -1503,13 +591,16 @@ sub GetMarcStructure {
     # check that framework exists
     $sth =
       $dbh->prepare(
-        "select count(*) from marc_tag_structure where frameworkcode=?");
+        "SELECT COUNT(*) FROM marc_tag_structure WHERE frameworkcode=?");
     $sth->execute($frameworkcode);
     my ($total) = $sth->fetchrow;
     $frameworkcode = "" unless ( $total > 0 );
     $sth =
       $dbh->prepare(
-"select tagfield,liblibrarian,libopac,mandatory,repeatable from marc_tag_structure where frameworkcode=? order by tagfield"
+        "SELECT tagfield,liblibrarian,libopac,mandatory,repeatable 
+        FROM marc_tag_structure 
+        WHERE frameworkcode=? 
+        ORDER BY tagfield"
       );
     $sth->execute($frameworkcode);
     my ( $liblibrarian, $libopac, $tag, $res, $tab, $mandatory, $repeatable );
@@ -1519,16 +610,18 @@ sub GetMarcStructure {
     {
         $res->{$tag}->{lib} =
           ( $forlibrarian or !$libopac ) ? $liblibrarian : $libopac;
-          # why the hell do we need to explicitly decode utf8 ? 
-          # that's a good question, but we must do it...
-        $res->{$tab}->{tab}        = "";            # XXX
+        $res->{$tab}->{tab}        = "";
         $res->{$tag}->{mandatory}  = $mandatory;
         $res->{$tag}->{repeatable} = $repeatable;
     }
 
     $sth =
       $dbh->prepare(
-"select tagfield,tagsubfield,liblibrarian,libopac,tab, mandatory, repeatable,authorised_value,authtypecode,value_builder,kohafield,seealso,hidden,isurl,link,defaultvalue from marc_subfield_structure where frameworkcode=? order by tagfield,tagsubfield"
+            "SELECT tagfield,tagsubfield,liblibrarian,libopac,tab,mandatory,repeatable,authorised_value,authtypecode,value_builder,kohafield,seealso,hidden,isurl,link,defaultvalue 
+                FROM marc_subfield_structure 
+            WHERE frameworkcode=? 
+                ORDER BY tagfield,tagsubfield
+            "
     );
     
     $sth->execute($frameworkcode);
@@ -1643,7 +736,7 @@ sub GetMarcBiblio {
     my $biblionumber = shift;
     my $dbh          = C4::Context->dbh;
     my $sth          =
-      $dbh->prepare("select marcxml from biblioitems where biblionumber=? ");
+      $dbh->prepare("SELECT marcxml FROM biblioitems WHERE biblionumber=? ");
     $sth->execute($biblionumber);
      my ($marcxml) = $sth->fetchrow;
      MARC::File::XML->default_record_format(C4::Context->preference('marcflavour'));
@@ -1654,11 +747,14 @@ sub GetMarcBiblio {
      $marcxml =~ s/\x0c//g;  
 #   warn $marcxml;
     my $record = MARC::Record->new();
-     
-      $record = eval {MARC::Record::new_from_xml( $marcxml, "utf8",C4::Context->preference('marcflavour'))} if ($marcxml);
-     if ($@) {warn $@;}
+    if ($marcxml) {
+        $record = eval {MARC::Record::new_from_xml( $marcxml, "utf8", C4::Context->preference('marcflavour'))};
+        if ($@) {warn $@;}
 #      $record = MARC::Record::new_from_usmarc( $marc) if $marc;
-    return $record;
+        return $record;
+    } else {
+        return undef;
+    }
 }
 
 =head2 GetXmlBiblio
@@ -1678,7 +774,7 @@ sub GetXmlBiblio {
     my ( $biblionumber ) = @_;
     my $dbh = C4::Context->dbh;
     my $sth =
-      $dbh->prepare("select marcxml from biblioitems where biblionumber=? ");
+      $dbh->prepare("SELECT marcxml FROM biblioitems WHERE biblionumber=? ");
     $sth->execute($biblionumber);
     my ($marcxml) = $sth->fetchrow;
     return $marcxml;
@@ -1689,34 +785,41 @@ sub GetXmlBiblio {
 =over 4
 
 my $subfieldvalue =get_authorised_value_desc(
-    $tag, $subf[$i][0],$subf[$i][1], '', $taglib);
+    $tag, $subf[$i][0],$subf[$i][1], '', $taglib, $category);
 Retrieve the complete description for a given authorised value.
 
+Now takes $category and $value pair too.
+my $auth_value_desc =GetAuthorisedValueDesc(
+    '','', 'DVD' ,'','','CCODE');
+
 =back
 
 =cut
 
 sub GetAuthorisedValueDesc {
-    my ( $tag, $subfield, $value, $framework, $tagslib ) = @_;
+    my ( $tag, $subfield, $value, $framework, $tagslib, $category ) = @_;
     my $dbh = C4::Context->dbh;
-    
-    #---- branch
-    if ( $tagslib->{$tag}->{$subfield}->{'authorised_value'} eq "branches" ) {
-        return C4::Branch::GetBranchName($value);
-    }
 
-    #---- itemtypes
-    if ( $tagslib->{$tag}->{$subfield}->{'authorised_value'} eq "itemtypes" ) {
-        return getitemtypeinfo($value)->{description};
+    if (!$category) {
+#---- branch
+        if ( $tagslib->{$tag}->{$subfield}->{'authorised_value'} eq "branches" ) {
+            return C4::Branch::GetBranchName($value);
+        }
+
+#---- itemtypes
+        if ( $tagslib->{$tag}->{$subfield}->{'authorised_value'} eq "itemtypes" ) {
+            return getitemtypeinfo($value)->{description};
+        }
+
+#---- "true" authorized value
+        $category = $tagslib->{$tag}->{$subfield}->{'authorised_value'}
     }
 
-    #---- "true" authorized value
-    my $category = $tagslib->{$tag}->{$subfield}->{'authorised_value'};
     if ( $category ne "" ) {
         my $sth =
-          $dbh->prepare(
-            "select lib from authorised_values where category = ? and authorised_value = ?"
-          );
+            $dbh->prepare(
+                    "SELECT lib FROM authorised_values WHERE category = ? AND authorised_value = ?"
+                    );
         $sth->execute( $category, $value );
         my $data = $sth->fetchrow_hashref;
         return $data->{'lib'};
@@ -1726,39 +829,6 @@ sub GetAuthorisedValueDesc {
     }
 }
 
-=head2 GetMarcItem
-
-=over 4
-
-Returns MARC::Record of the item passed in parameter.
-
-=back
-
-=cut
-
-sub GetMarcItem {
-    my ( $biblionumber, $itemnumber ) = @_;
-    my $dbh = C4::Context->dbh;
-    my $newrecord = MARC::Record->new();
-    my $marcflavour = C4::Context->preference('marcflavour');
-    
-    my $marcxml = GetXmlBiblio($biblionumber);
-    my $record = MARC::Record->new();
-    $record = MARC::Record::new_from_xml( $marcxml, "utf8", $marcflavour );
-    # now, find where the itemnumber is stored & extract only the item
-    my ( $itemnumberfield, $itemnumbersubfield ) =
-      GetMarcFromKohaField( 'items.itemnumber', '' );
-    my @fields = $record->field($itemnumberfield);
-    foreach my $field (@fields) {
-        if ( $field->subfield($itemnumbersubfield) eq $itemnumber ) {
-            $newrecord->insert_fields_ordered($field);
-        }
-    }
-    return $newrecord;
-}
-
-
-
 =head2 GetMarcNotes
 
 =over 4
@@ -1826,48 +896,45 @@ sub GetMarcSubjects {
         $mintag = "600";
         $maxtag = "611";
     }
+    
+    my @marcsubjects;
+    my $subject = "";
+    my $subfield = "";
+    my $marcsubject;
 
-    my @marcsubjcts;
-
-    foreach my $field ( $record->fields ) {
+    foreach my $field ( $record->field('6..' )) {
         next unless $field->tag() >= $mintag && $field->tag() <= $maxtag;
+        my @subfields_loop;
         my @subfields = $field->subfields();
-        my $link = "su:";
-        my $label;
-        my $flag = 0;
-        my $authoritysep=C4::Context->preference("authoritysep");
-        for my $subject_subfield ( @subfields ) {
-            if (
-                $marcflavour ne 'MARC21'
-                and (
-                    ($subject_subfield->[0] eq '3') or
-                    ($subject_subfield->[0] eq '4') or
-                    ($subject_subfield->[0] eq '5')
-                )
-            )
-            {
-                next;
-            }
+        my $counter = 0;
+        my @link_loop;
+        # if there is an authority link, build the link with an= subfield9
+        my $subfield9 = $field->subfield('9');
+        for my $subject_subfield (@subfields ) {
+            # don't load unimarc subfields 3,4,5
+            next if (($marcflavour eq "UNIMARC") and ($subject_subfield->[0] =~ (3|4|5) ) );
             my $code = $subject_subfield->[0];
-            $label .= $subject_subfield->[1].$authoritysep unless ( $code == 9 );
-            $link  .= " and su-to:".$subject_subfield->[1]  unless ( $code == 9 );
-            if ( $code == 9 ) {
-                $link = "an:".$subject_subfield->[1];
-                $flag = 1;
-            }
-            elsif ( ! $flag ) {
-                $link =~ s/ and\ssu-to:$//;
+            my $value = $subject_subfield->[1];
+            my $linkvalue = $value;
+            $linkvalue =~ s/(\(|\))//g;
+            my $operator = " and " unless $counter==0;
+            if ($subfield9) {
+                @link_loop = ({'limit' => 'an' ,link => "$subfield9" });
+            } else {
+                push @link_loop, {'limit' => 'su', link => $linkvalue, operator => $operator };
             }
+            my $separator = C4::Context->preference("authoritysep") unless $counter==0;
+            # ignore $9
+            my @this_link_loop = @link_loop;
+            push @subfields_loop, {code => $code, value => $value, link_loop => \@this_link_loop, separator => $separator} unless ($subject_subfield->[0] == 9 );
+            $counter++;
         }
-         $label =~ s/$authoritysep$//;
-        push @marcsubjcts,
-          {
-            label => $label,
-            link  => $link
-          }
+                
+        push @marcsubjects, { MARCSUBJECT_SUBFIELDS_LOOP => \@subfields_loop };
+        
     }
-    return \@marcsubjcts;
-}    #end GetMarcSubjects
+        return \@marcsubjects;
+}  #end getMARCsubjects
 
 =head2 GetMarcAuthors
 
@@ -1887,63 +954,99 @@ sub GetMarcAuthors {
     # tagslib useful for UNIMARC author reponsabilities
     my $tagslib = &GetMarcStructure( 1, '' ); # FIXME : we don't have the framework available, we take the default framework. May be bugguy on some setups, will be usually correct.
     if ( $marcflavour eq "MARC21" ) {
-        $mintag = "100";
-        $maxtag = "111"; 
+        $mintag = "700";
+        $maxtag = "720"; 
     }
-    else {    # assume unimarc if not marc21
-        $mintag = "701";
+    elsif ( $marcflavour eq "UNIMARC" ) {    # assume unimarc if not marc21
+        $mintag = "700";
         $maxtag = "712";
     }
-
+    else {
+        return;
+    }
     my @marcauthors;
 
     foreach my $field ( $record->fields ) {
         next unless $field->tag() >= $mintag && $field->tag() <= $maxtag;
-        my %hash;
+        my @subfields_loop;
+        my @link_loop;
         my @subfields = $field->subfields();
         my $count_auth = 0;
-        my $and ;
+        # if there is an authority link, build the link with Koha-Auth-Number: subfield9
+        my $subfield9 = $field->subfield('9');
         for my $authors_subfield (@subfields) {
-            if (
-                $marcflavour ne 'MARC21'
-                and (
-                    ($authors_subfield->[0] eq '3') or
-                    ($authors_subfield->[0] eq '5')
-                )
-            )
-            {
-                next;
+            # don't load unimarc subfields 3, 5
+            next if ($marcflavour eq 'UNIMARC' and ($authors_subfield->[0] =~ (3|5) ) );
+            my $subfieldcode = $authors_subfield->[0];
+            my $value = $authors_subfield->[1];
+            my $linkvalue = $value;
+            $linkvalue =~ s/(\(|\))//g;
+            my $operator = " and " unless $count_auth==0;
+            # if we have an authority link, use that as the link, otherwise use standard searching
+            if ($subfield9) {
+                @link_loop = ({'limit' => 'Koha-Auth-Number' ,link => "$subfield9" });
             }
-            if ($count_auth ne '0'){
-                $and = " and au:";
+            else {
+                # reset $linkvalue if UNIMARC author responsibility
+                if ( $marcflavour eq 'UNIMARC' and ($authors_subfield->[0] eq '4')) {
+                    $linkvalue = "(".GetAuthorisedValueDesc( $field->tag(), $authors_subfield->[0], $authors_subfield->[1], '', $tagslib ).")";
+                }
+                push @link_loop, {'limit' => 'au', link => $linkvalue, operator => $operator };
             }
+            my @this_link_loop = @link_loop;
+            my $separator = C4::Context->preference("authoritysep") unless $count_auth==0;
+            push @subfields_loop, {code => $subfieldcode, value => $value, link_loop => \@this_link_loop, separator => $separator} unless ($authors_subfield->[0] == 9 );
             $count_auth++;
-            my $subfieldcode = $authors_subfield->[0];
-            my $value;
-            # deal with UNIMARC author responsibility
-            if (
-                $marcflavour ne 'MARC21'
-                and ($authors_subfield->[0] eq '4')
-            )
-            {
-                $value = "(".GetAuthorisedValueDesc( $field->tag(), $authors_subfield->[0], $authors_subfield->[1], '', $tagslib ).")";
-            } else {
-                $value        = $authors_subfield->[1];
-            }
-            $hash{tag}       = $field->tag;
-            $hash{value}    .= $value . " " if ($subfieldcode != 9) ;
-            $hash{link}     .= $value if ($subfieldcode eq 9);
         }
-        push @marcauthors, \%hash;
+        push @marcauthors, { MARCAUTHOR_SUBFIELDS_LOOP => \@subfields_loop };
     }
     return \@marcauthors;
 }
 
+=head2 GetMarcUrls
+
+=over 4
+
+$marcurls = GetMarcUrls($record,$marcflavour);
+Returns arrayref of URLs from MARC data, suitable to pass to tmpl loop.
+Assumes web resources (not uncommon in MARC21 to omit resource type ind) 
+
+=back
+
+=cut
+
+sub GetMarcUrls {
+    my ($record, $marcflavour) = @_;
+    my @marcurls;
+    my $marcurl;
+    for my $field ($record->field('856')) {
+        my $url = $field->subfield('u');
+        my @notes;
+        for my $note ( $field->subfield('z')) {
+            push @notes , {note => $note};
+        }        
+        $marcurl = {  MARCURL => $url,
+                      notes => \@notes,
+                    };
+        if($marcflavour eq 'MARC21') {
+            my $s3 = $field->subfield('3');
+            my $link = $field->subfield('y');
+            $marcurl->{'linktext'} = $link || $s3 || $url ;;
+            $marcurl->{'part'} = $s3 if($link);
+            $marcurl->{'toc'} = 1 if($s3 =~ /^[Tt]able/) ;
+        } else {
+            $marcurl->{'linktext'} = $url;
+        }
+        push @marcurls, $marcurl;    
+    }
+    return \@marcurls;
+}  #end GetMarcUrls
+
 =head2 GetMarcSeries
 
 =over 4
 
-$marcseriessarray = GetMarcSeries($record,$marcflavour);
+$marcseriesarray = GetMarcSeries($record,$marcflavour);
 Get all series from the MARC record and returns them in an array.
 The series are stored in differents places depending on MARC flavour
 
@@ -1976,12 +1079,12 @@ sub GetMarcSeries {
         my $counter = 0;
         my @link_loop;
         for my $series_subfield (@subfields) {
-                       my $volume_number;
-                       undef $volume_number;
-                       # see if this is an instance of a volume
-                       if ($series_subfield->[0] eq 'v') {
-                               $volume_number=1;
-                       }
+            my $volume_number;
+            undef $volume_number;
+            # see if this is an instance of a volume
+            if ($series_subfield->[0] eq 'v') {
+                $volume_number=1;
+            }
 
             my $code = $series_subfield->[0];
             my $value = $series_subfield->[1];
@@ -1990,12 +1093,12 @@ sub GetMarcSeries {
             my $operator = " and " unless $counter==0;
             push @link_loop, {link => $linkvalue, operator => $operator };
             my $separator = C4::Context->preference("authoritysep") unless $counter==0;
-                       if ($volume_number) {
-                       push @subfields_loop, {volumenum => $value};
-                       }
-                       else {
+            if ($volume_number) {
+            push @subfields_loop, {volumenum => $value};
+            }
+            else {
             push @subfields_loop, {code => $code, value => $value, link_loop => \@link_loop, separator => $separator, volumenum => $volume_number};
-                       }
+            }
             $counter++;
         }
         push @marcseries, { MARCSERIES_SUBFIELDS_LOOP => \@subfields_loop };
@@ -2021,7 +1124,7 @@ sub GetMarcSeries {
 sub GetFrameworkCode {
     my ( $biblionumber ) = @_;
     my $dbh = C4::Context->dbh;
-    my $sth = $dbh->prepare("select frameworkcode from biblio where biblionumber=?");
+    my $sth = $dbh->prepare("SELECT frameworkcode FROM biblio WHERE biblionumber=?");
     $sth->execute($biblionumber);
     my ($frameworkcode) = $sth->fetchrow;
     return $frameworkcode;
@@ -2076,7 +1179,7 @@ sub TransformKohaToMarc {
     my $dbh = C4::Context->dbh;
     my $sth =
     $dbh->prepare(
-        "select tagfield,tagsubfield from marc_subfield_structure where frameworkcode=? and kohafield=?"
+        "SELECT tagfield,tagsubfield FROM marc_subfield_structure WHERE frameworkcode=? AND kohafield=?"
     );
     my $record = MARC::Record->new();
     foreach (keys %{$hash}) {
@@ -2105,7 +1208,7 @@ sub TransformKohaToMarcOneField {
     if ( !defined $sth ) {
         my $dbh = C4::Context->dbh;
         $sth = $dbh->prepare(
-            "select tagfield,tagsubfield from marc_subfield_structure where frameworkcode=? and kohafield=?"
+            "SELECT tagfield,tagsubfield FROM marc_subfield_structure WHERE frameworkcode=? AND kohafield=?"
         );
     }
     $sth->execute( $frameworkcode, $kohafieldname );
@@ -2241,7 +1344,7 @@ sub TransformHtmlToXml {
         }
         $prevtag = @$tags[$i];
     }
-    if (C4::Context->preference('marcflavour') and !$unimarc_and_100_exist) {
+    if (C4::Context->preference('marcflavour') eq 'UNIMARC' and !$unimarc_and_100_exist) {
 #     warn "SETTING 100 for $auth_type";
         use POSIX qw(strftime);
         my $string = strftime( "%Y%m%d", localtime(time) );
@@ -2362,75 +1465,215 @@ sub TransformHtmlToMarc {
     return $record;
 }
 
+# cache inverted MARC field map
+our $inverted_field_map;
+
 =head2 TransformMarcToKoha
 
 =over 4
 
-       $result = TransformMarcToKoha( $dbh, $record, $frameworkcode )
+    $result = TransformMarcToKoha( $dbh, $record, $frameworkcode )
 
 =back
 
-=cut
+Extract data from a MARC bib record into a hashref representing
+Koha biblio, biblioitems, and items fields. 
 
+=cut
 sub TransformMarcToKoha {
-    my ( $dbh, $record, $frameworkcode ) = @_;
-    
-    #  FIXME :: This query is unused..
-    #    my $sth =
-    #      $dbh->prepare(
-    #"select tagfield,tagsubfield from marc_subfield_structure where frameworkcode=? and kohafield=?"
-    #      );
-    
+    my ( $dbh, $record, $frameworkcode, $limit_table ) = @_;
+
     my $result;
-    my $sth2 = $dbh->prepare("SHOW COLUMNS from biblio");
-    $sth2->execute;
-    my $field;
-    while ( ($field) = $sth2->fetchrow ) {
-        $result =
-          &TransformMarcToKohaOneField( "biblio", $field, $record, $result,
-            $frameworkcode );
-    }
-    my $sth2 = $dbh->prepare("SHOW COLUMNS from biblioitems");
-    $sth2->execute;
-    while ( ($field) = $sth2->fetchrow ) {
-        if ( $field eq 'notes' ) { $field = 'bnotes'; }
-        $result =
-          &TransformMarcToKohaOneField( "biblioitems", $field, $record, $result,
-            $frameworkcode );
+
+    unless (defined $inverted_field_map) {
+        $inverted_field_map = _get_inverted_marc_field_map();
     }
-    $sth2 = $dbh->prepare("SHOW COLUMNS from items");
-    $sth2->execute;
-    while ( ($field) = $sth2->fetchrow ) {
-        $result =
-          &TransformMarcToKohaOneField( "items", $field, $record, $result,
-            $frameworkcode );
+
+    my %tables = ();
+    if ($limit_table eq 'items') {
+        $tables{'items'} = 1;
+    } else {
+        $tables{'items'} = 1;
+        $tables{'biblio'} = 1;
+        $tables{'biblioitems'} = 1;
+    }
+
+    # traverse through record
+    MARCFIELD: foreach my $field ($record->fields()) {
+        my $tag = $field->tag();
+        next MARCFIELD unless exists $inverted_field_map->{$frameworkcode}->{$tag};
+        if ($field->is_control_field()) {
+            my $kohafields = $inverted_field_map->{$frameworkcode}->{$tag}->{list};
+            ENTRY: foreach my $entry (@{ $kohafields }) {
+                my ($subfield, $table, $column) = @{ $entry };
+                next ENTRY unless exists $tables{$table};
+                my $key = _disambiguate($table, $column);
+                if ($result->{$key}) {
+                    unless (($key eq "biblionumber" or $key eq "biblioitemnumber") and ($field->data() eq "")) {
+                        $result->{$key} .= " | " . $field->data();
+                    }
+                } else {
+                    $result->{$key} = $field->data();
+                }
+            }
+        } else {
+            # deal with subfields
+            MARCSUBFIELD: foreach my $sf ($field->subfields()) {
+                my $code = $sf->[0];
+                next MARCSUBFIELD unless exists $inverted_field_map->{$frameworkcode}->{$tag}->{sfs}->{$code};
+                my $value = $sf->[1];
+                SFENTRY: foreach my $entry (@{ $inverted_field_map->{$frameworkcode}->{$tag}->{sfs}->{$code} }) {
+                    my ($table, $column) = @{ $entry };
+                    next SFENTRY unless exists $tables{$table};
+                    my $key = _disambiguate($table, $column);
+                    if ($result->{$key}) {
+                        unless (($key eq "biblionumber" or $key eq "biblioitemnumber") and ($value eq "")) {
+                            $result->{$key} .= " | " . $value;
+                        }
+                    } else {
+                        $result->{$key} = $value;
+                    }
+                }
+            }
+        }
     }
 
-    #
     # modify copyrightdate to keep only the 1st year found
-    my $temp = $result->{'copyrightdate'};
-    $temp =~ m/c(\d\d\d\d)/;    # search cYYYY first
-    if ( $1 > 0 ) {
-        $result->{'copyrightdate'} = $1;
-    }
-    else {                      # if no cYYYY, get the 1st date.
-        $temp =~ m/(\d\d\d\d)/;
-        $result->{'copyrightdate'} = $1;
+    if (exists $result->{'copyrightdate'}) {
+        my $temp = $result->{'copyrightdate'};
+        $temp =~ m/c(\d\d\d\d)/;    # search cYYYY first
+        if ( $1 > 0 ) {
+            $result->{'copyrightdate'} = $1;
+        }
+        else {                      # if no cYYYY, get the 1st date.
+            $temp =~ m/(\d\d\d\d)/;
+            $result->{'copyrightdate'} = $1;
+        }
     }
 
     # modify publicationyear to keep only the 1st year found
-    $temp = $result->{'publicationyear'};
-    $temp =~ m/c(\d\d\d\d)/;    # search cYYYY first
-    if ( $1 > 0 ) {
-        $result->{'publicationyear'} = $1;
-    }
-    else {                      # if no cYYYY, get the 1st date.
-        $temp =~ m/(\d\d\d\d)/;
-        $result->{'publicationyear'} = $1;
+    if (exists $result->{'publicationyear'}) {
+        my $temp = $result->{'publicationyear'};
+        $temp =~ m/c(\d\d\d\d)/;    # search cYYYY first
+        if ( $1 > 0 ) {
+            $result->{'publicationyear'} = $1;
+        }
+        else {                      # if no cYYYY, get the 1st date.
+            $temp =~ m/(\d\d\d\d)/;
+            $result->{'publicationyear'} = $1;
+        }
     }
+
     return $result;
 }
 
+sub _get_inverted_marc_field_map {
+    my $field_map = {};
+    my $relations = C4::Context->marcfromkohafield;
+
+    foreach my $frameworkcode (keys %{ $relations }) {
+        foreach my $kohafield (keys %{ $relations->{$frameworkcode} }) {
+            my $tag = $relations->{$frameworkcode}->{$kohafield}->[0];
+            my $subfield = $relations->{$frameworkcode}->{$kohafield}->[1];
+            my ($table, $column) = split /[.]/, $kohafield, 2;
+            push @{ $field_map->{$frameworkcode}->{$tag}->{list} }, [ $subfield, $table, $column ];
+            push @{ $field_map->{$frameworkcode}->{$tag}->{sfs}->{$subfield} }, [ $table, $column ];
+        }
+    }
+    return $field_map;
+}
+
+=head2 _disambiguate
+
+=over 4
+
+$newkey = _disambiguate($table, $field);
+
+This is a temporary hack to distinguish between the
+following sets of columns when using TransformMarcToKoha.
+
+items.cn_source & biblioitems.cn_source
+items.cn_sort & biblioitems.cn_sort
+
+Columns that are currently NOT distinguished (FIXME
+due to lack of time to fully test) are:
+
+biblio.notes and biblioitems.notes
+biblionumber
+timestamp
+biblioitemnumber
+
+FIXME - this is necessary because prefixing each column
+name with the table name would require changing lots
+of code and templates, and exposing more of the DB
+structure than is good to the UI templates, particularly
+since biblio and bibloitems may well merge in a future
+version.  In the future, it would also be good to 
+separate DB access and UI presentation field names
+more.
+
+=back
+
+=cut
+
+sub _disambiguate {
+    my ($table, $column) = @_;
+    if ($column eq "cn_sort" or $column eq "cn_source") {
+        return $table . '.' . $column;
+    } else {
+        return $column;
+    }
+
+}
+
+=head2 get_koha_field_from_marc
+
+=over 4
+
+$result->{_disambiguate($table, $field)} = get_koha_field_from_marc($table,$field,$record,$frameworkcode);
+
+Internal function to map data from the MARC record to a specific non-MARC field.
+FIXME: this is meant to replace TransformMarcToKohaOneField after more testing.
+
+=back
+
+=cut
+
+sub get_koha_field_from_marc {
+    my ($koha_table,$koha_column,$record,$frameworkcode) = @_;
+    my ( $tagfield, $subfield ) = GetMarcFromKohaField( $koha_table.'.'.$koha_column, $frameworkcode );  
+    my $kohafield;
+    foreach my $field ( $record->field($tagfield) ) {
+        if ( $field->tag() < 10 ) {
+            if ( $kohafield ) {
+                $kohafield .= " | " . $field->data();
+            }
+            else {
+                $kohafield = $field->data();
+            }
+        }
+        else {
+            if ( $field->subfields ) {
+                my @subfields = $field->subfields();
+                foreach my $subfieldcount ( 0 .. $#subfields ) {
+                    if ( $subfields[$subfieldcount][0] eq $subfield ) {
+                        if ( $kohafield ) {
+                            $kohafield .=
+                              " | " . $subfields[$subfieldcount][1];
+                        }
+                        else {
+                            $kohafield =
+                              $subfields[$subfieldcount][1];
+                        }
+                    }
+                }
+            }
+        }
+    }
+    return $kohafield;
+} 
+
+
 =head2 TransformMarcToKohaOneField
 
 =over 4
@@ -2704,7 +1947,7 @@ sub PrepareItemrecordDisplay {
     my @loop_data;
     my $authorised_values_sth =
       $dbh->prepare(
-"select authorised_value,lib from authorised_values where category=? order by lib"
+"SELECT authorised_value,lib FROM authorised_values WHERE category=? ORDER BY lib"
       );
     foreach my $tag ( sort keys %{$tagslib} ) {
         my $previous_tag = '';
@@ -2766,7 +2009,7 @@ sub PrepareItemrecordDisplay {
                         {
                             my $sth =
                               $dbh->prepare(
-"select branchcode,branchname from branches where branchcode = ? order by branchname"
+                                "SELECT branchcode,branchname FROM branches WHERE branchcode = ? ORDER BY branchname"
                               );
                             $sth->execute( C4::Context->userenv->{branch} );
                             push @authorised_values, ""
@@ -2782,7 +2025,7 @@ sub PrepareItemrecordDisplay {
                         else {
                             my $sth =
                               $dbh->prepare(
-"select branchcode,branchname from branches order by branchname"
+                                "SELECT branchcode,branchname FROM branches ORDER BY branchname"
                               );
                             $sth->execute;
                             push @authorised_values, ""
@@ -2803,7 +2046,7 @@ sub PrepareItemrecordDisplay {
                     {
                         my $sth =
                           $dbh->prepare(
-"select itemtype,description from itemtypes order by description"
+                            "SELECT itemtype,description FROM itemtypes ORDER BY description"
                           );
                         $sth->execute;
                         push @authorised_values, ""
@@ -2944,8 +2187,10 @@ sub ModZebra {
         }
         if ($op eq 'specialUpdate') {
             # OK, we have to add or update the record
-            # 1st delete (virtually, in indexes) ...
-            %result = _DelBiblioNoZebra($biblionumber,$record,$server);
+            # 1st delete (virtually, in indexes), if record actually exists
+            if ($record) { 
+                %result = _DelBiblioNoZebra($biblionumber,$record,$server);
+            }
             # ... add the record
             %result=_AddBiblioNoZebra($biblionumber,$newRecord, $server, %result);
         } else {
@@ -2966,7 +2211,7 @@ sub ModZebra {
         #
         # we use zebra, just fill zebraqueue table
         #
-        my $sth=$dbh->prepare("insert into zebraqueue  (biblio_auth_number ,server,operation) values(?,?,?)");
+        my $sth=$dbh->prepare("INSERT INTO zebraqueue  (biblio_auth_number,server,operation) VALUES(?,?,?)");
         $sth->execute($biblionumber,$server,$op);
         $sth->finish;
     }
@@ -2987,8 +2232,10 @@ sub GetNoZebraIndexes {
         $line =~ /(.*)=>(.*)/;
         my $index = substr($1,1); # get the index, don't forget to remove initial ' or "
         my $fields = $2;
-        $index =~ s/'|"| //g;
-        $fields =~ s/'|"| //g;
+        $index =~ s/'|"|\s//g;
+
+
+        $fields =~ s/'|"|\s//g;
         $indexes{$index}=$fields;
     }
     return %indexes;
@@ -3213,125 +2460,184 @@ sub _AddBiblioNoZebra {
 }
 
 
-=head2 MARCitemchange
+=head2 _find_value
 
 =over 4
 
-&MARCitemchange( $record, $itemfield, $newvalue )
+($indicators, $value) = _find_value($tag, $subfield, $record,$encoding);
 
-Function to update a single value in an item field.
-Used twice, could probably be replaced by something else, but works well...
+Find the given $subfield in the given $tag in the given
+MARC::Record $record.  If the subfield is found, returns
+the (indicators, value) pair; otherwise, (undef, undef) is
+returned.
 
-=back
+PROPOSITION :
+Such a function is used in addbiblio AND additem and serial-edit and maybe could be used in Authorities.
+I suggest we export it from this module.
 
 =back
 
 =cut
 
-sub MARCitemchange {
-    my ( $record, $itemfield, $newvalue ) = @_;
-    my $dbh = C4::Context->dbh;
-    
-    my ( $tagfield, $tagsubfield ) =
-      GetMarcFromKohaField( $itemfield, "" );
-    if ( ($tagfield) && ($tagsubfield) ) {
-        my $tag = $record->field($tagfield);
-        if ($tag) {
-            $tag->update( $tagsubfield => $newvalue );
-            $record->delete_field($tag);
-            $record->insert_fields_ordered($tag);
+sub _find_value {
+    my ( $tagfield, $insubfield, $record, $encoding ) = @_;
+    my @result;
+    my $indicator;
+    if ( $tagfield < 10 ) {
+        if ( $record->field($tagfield) ) {
+            push @result, $record->field($tagfield)->data();
+        }
+        else {
+            push @result, "";
+        }
+    }
+    else {
+        foreach my $field ( $record->field($tagfield) ) {
+            my @subfields = $field->subfields();
+            foreach my $subfield (@subfields) {
+                if ( @$subfield[0] eq $insubfield ) {
+                    push @result, @$subfield[1];
+                    $indicator = $field->indicator(1) . $field->indicator(2);
+                }
+            }
         }
     }
+    return ( $indicator, @result );
 }
 
-=head2 _koha_add_biblio
+=head2 _koha_marc_update_bib_ids
 
 =over 4
 
-_koha_add_biblio($dbh,$biblioitem);
+_koha_marc_update_bib_ids($record, $frameworkcode, $biblionumber, $biblioitemnumber);
 
-Internal function to add a biblio ($biblio is a hash with the values)
+Internal function to add or update biblionumber and biblioitemnumber to
+the MARC XML.
 
 =back
 
 =cut
 
-sub _koha_add_biblio {
-    my ( $dbh, $biblio, $frameworkcode ) = @_;
-    my $sth = $dbh->prepare("Select max(biblionumber) from biblio");
-    $sth->execute;
-    my $data         = $sth->fetchrow_arrayref;
-    my $biblionumber = $$data[0] + 1;
-    my $series       = 0;
+sub _koha_marc_update_bib_ids {
+    my ($record, $frameworkcode, $biblionumber, $biblioitemnumber) = @_;
 
-    if ( $biblio->{'seriestitle'} ) { $series = 1 }
-    $sth->finish;
-    $sth = $dbh->prepare(
-        "INSERT INTO biblio
-    SET biblionumber  = ?, title = ?, author = ?, copyrightdate = ?, serial = ?, seriestitle = ?, notes = ?, abstract = ?, unititle = ?, frameworkcode = ? "
-    );
-    $sth->execute(
-        $biblionumber,         $biblio->{'title'},
-        $biblio->{'author'},   $biblio->{'copyrightdate'},
-        $biblio->{'serial'},   $biblio->{'seriestitle'},
-        $biblio->{'notes'},    $biblio->{'abstract'},
-        $biblio->{'unititle'}, $frameworkcode
-    );
+    # we must add bibnum and bibitemnum in MARC::Record...
+    # we build the new field with biblionumber and biblioitemnumber
+    # we drop the original field
+    # we add the new builded field.
+    my ($biblio_tag, $biblio_subfield ) = GetMarcFromKohaField("biblio.biblionumber",$frameworkcode);
+    my ($biblioitem_tag, $biblioitem_subfield ) = GetMarcFromKohaField("biblioitems.biblioitemnumber",$frameworkcode);
 
-    $sth->finish;
-    return ($biblionumber);
-}
+    if ($biblio_tag != $biblioitem_tag) {
+        # biblionumber & biblioitemnumber are in different fields
 
-=head2 _find_value
+        # deal with biblionumber
+        my ($new_field, $old_field);
+        if ($biblio_tag < 10) {
+            $new_field = MARC::Field->new( $biblio_tag, $biblionumber );
+        } else {
+            $new_field =
+              MARC::Field->new( $biblio_tag, '', '',
+                "$biblio_subfield" => $biblionumber );
+        }
 
-=over 4
+        # drop old field and create new one...
+        $old_field = $record->field($biblio_tag);
+        $record->delete_field($old_field);
+        $record->append_fields($new_field);
 
-($indicators, $value) = _find_value($tag, $subfield, $record,$encoding);
+        # deal with biblioitemnumber
+        if ($biblioitem_tag < 10) {
+            $new_field = MARC::Field->new( $biblioitem_tag, $biblioitemnumber, );
+        } else {
+            $new_field =
+              MARC::Field->new( $biblioitem_tag, '', '',
+                "$biblioitem_subfield" => $biblioitemnumber, );
+        }
+        # drop old field and create new one...
+        $old_field = $record->field($biblioitem_tag);
+        $record->delete_field($old_field);
+        $record->insert_fields_ordered($new_field);
 
-Find the given $subfield in the given $tag in the given
-MARC::Record $record.  If the subfield is found, returns
-the (indicators, value) pair; otherwise, (undef, undef) is
-returned.
+    } else {
+        # biblionumber & biblioitemnumber are in the same field (can't be <10 as fields <10 have only 1 value)
+        my $new_field = MARC::Field->new(
+            $biblio_tag, '', '',
+            "$biblio_subfield" => $biblionumber,
+            "$biblioitem_subfield" => $biblioitemnumber
+        );
 
-PROPOSITION :
-Such a function is used in addbiblio AND additem and serial-edit and maybe could be used in Authorities.
-I suggest we export it from this module.
+        # drop old field and create new one...
+        my $old_field = $record->field($biblio_tag);
+        $record->delete_field($old_field);
+        $record->insert_fields_ordered($new_field);
+    }
+}
+
+=head2 _koha_add_biblio
+
+=over 4
+
+my ($biblionumber,$error) = _koha_add_biblio($dbh,$biblioitem);
+
+Internal function to add a biblio ($biblio is a hash with the values)
 
 =back
 
 =cut
 
-sub _find_value {
-    my ( $tagfield, $insubfield, $record, $encoding ) = @_;
-    my @result;
-    my $indicator;
-    if ( $tagfield < 10 ) {
-        if ( $record->field($tagfield) ) {
-            push @result, $record->field($tagfield)->data();
-        }
-        else {
-            push @result, "";
-        }
-    }
-    else {
-        foreach my $field ( $record->field($tagfield) ) {
-            my @subfields = $field->subfields();
-            foreach my $subfield (@subfields) {
-                if ( @$subfield[0] eq $insubfield ) {
-                    push @result, @$subfield[1];
-                    $indicator = $field->indicator(1) . $field->indicator(2);
-                }
-            }
-        }
+sub _koha_add_biblio {
+    my ( $dbh, $biblio, $frameworkcode ) = @_;
+
+    my $error;
+
+    # set the series flag
+    my $serial = 0;
+    if ( $biblio->{'seriestitle'} ) { $serial = 1 };
+
+    my $query = 
+        "INSERT INTO biblio
+        SET frameworkcode = ?,
+            author = ?,
+            title = ?,
+            unititle =?,
+            notes = ?,
+            serial = ?,
+            seriestitle = ?,
+            copyrightdate = ?,
+            datecreated=NOW(),
+            abstract = ?
+        ";
+    my $sth = $dbh->prepare($query);
+    $sth->execute(
+        $frameworkcode,
+        $biblio->{'author'},
+        $biblio->{'title'},
+        $biblio->{'unititle'},
+        $biblio->{'notes'},
+        $serial,
+        $biblio->{'seriestitle'},
+        $biblio->{'copyrightdate'},
+        $biblio->{'abstract'}
+    );
+
+    my $biblionumber = $dbh->{'mysql_insertid'};
+    if ( $dbh->errstr ) {
+        $error.="ERROR in _koha_add_biblio $query".$dbh->errstr;
+        warn $error;
     }
-    return ( $indicator, @result );
+
+    $sth->finish();
+    #warn "LEAVING _koha_add_biblio: ".$biblionumber."\n";
+    return ($biblionumber,$error);
 }
 
 =head2 _koha_modify_biblio
 
 =over 4
 
-$biblionumber = _koha_modify_biblio($dbh,$biblio);
+my ($biblionumber,$error) == _koha_modify_biblio($dbh,$biblio,$frameworkcode);
+
 Internal function for updating the biblio table
 
 =back
@@ -3339,117 +2645,141 @@ Internal function for updating the biblio table
 =cut
 
 sub _koha_modify_biblio {
-    my ( $dbh, $biblio ) = @_;
-    # FIXME: this code could be made more portable by not hard-coding
-    #        the values that are supposed to be in biblio table
-    my $query = qq{
+    my ( $dbh, $biblio, $frameworkcode ) = @_;
+    my $error;
+
+    my $query = "
         UPDATE biblio
-        SET    title = ?,
+        SET    frameworkcode = ?,
                author = ?,
-               abstract = ?,
-               copyrightdate = ?,
-               seriestitle = ?,
-               serial = ?,
+               title = ?,
                unititle = ?,
-               notes = ?
+               notes = ?,
+               serial = ?,
+               seriestitle = ?,
+               copyrightdate = ?,
+               abstract = ?
         WHERE  biblionumber = ?
-    };
+        "
+    ;
     my $sth = $dbh->prepare($query);
     
     $sth->execute(
-        $biblio->{'title'},
+        $frameworkcode,
         $biblio->{'author'},
-        $biblio->{'abstract'},
-        $biblio->{'copyrightdate'},
-        $biblio->{'seriestitle'},
-        $biblio->{'serial'},
+        $biblio->{'title'},
         $biblio->{'unititle'},
         $biblio->{'notes'},
+        $biblio->{'serial'},
+        $biblio->{'seriestitle'},
+        $biblio->{'copyrightdate'},
+        $biblio->{'abstract'},
         $biblio->{'biblionumber'}
     ) if $biblio->{'biblionumber'};
-    
-    warn $sth->err if $sth->err;
-    warn "BIG ERROR :: No biblionumber for $biblio->{title}" if $biblio->{biblionumber} !~ /\d+/; # if it is not a number
-    return ( $biblio->{'biblionumber'} );
+
+    if ( $dbh->errstr || !$biblio->{'biblionumber'} ) {
+        $error.="ERROR in _koha_modify_biblio $query".$dbh->errstr;
+        warn $error;
+    }
+    return ( $biblio->{'biblionumber'},$error );
 }
 
-=head2 _koha_modify_biblioitem
+=head2 _koha_modify_biblioitem_nonmarc
 
 =over 4
 
-_koha_modify_biblioitem( $dbh, $biblioitem );
+my ($biblioitemnumber,$error) = _koha_modify_biblioitem_nonmarc( $dbh, $biblioitem );
+
+Updates biblioitems row except for marc and marcxml, which should be changed
+via ModBiblioMarc
 
 =back
 
 =cut
 
-sub _koha_modify_biblioitem {
+sub _koha_modify_biblioitem_nonmarc {
     my ( $dbh, $biblioitem ) = @_;
-    my $query;
-##Recalculate LC in case it changed --TG
-
-    $biblioitem->{'itemtype'}      = $dbh->quote( $biblioitem->{'itemtype'} );
-    $biblioitem->{'url'}           = $dbh->quote( $biblioitem->{'url'} );
-    $biblioitem->{'isbn'}          = $dbh->quote( $biblioitem->{'isbn'} );
-    $biblioitem->{'issn'}          = $dbh->quote( $biblioitem->{'issn'} );
-    $biblioitem->{'publishercode'} =
-      $dbh->quote( $biblioitem->{'publishercode'} );
-    $biblioitem->{'publicationyear'} =
-      $dbh->quote( $biblioitem->{'publicationyear'} );
-    $biblioitem->{'classification'} =
-      $dbh->quote( $biblioitem->{'classification'} );
-    $biblioitem->{'dewey'}        = $dbh->quote( $biblioitem->{'dewey'} );
-    $biblioitem->{'subclass'}     = $dbh->quote( $biblioitem->{'subclass'} );
-    $biblioitem->{'illus'}        = $dbh->quote( $biblioitem->{'illus'} );
-    $biblioitem->{'pages'}        = $dbh->quote( $biblioitem->{'pages'} );
-    $biblioitem->{'volumeddesc'}  = $dbh->quote( $biblioitem->{'volumeddesc'} );
-    $biblioitem->{'bnotes'}       = $dbh->quote( $biblioitem->{'bnotes'} );
-    $biblioitem->{'size'}         = $dbh->quote( $biblioitem->{'size'} );
-    $biblioitem->{'place'}        = $dbh->quote( $biblioitem->{'place'} );
-    $biblioitem->{'collectiontitle'}        = $dbh->quote( $biblioitem->{'collectiontitle'} );
-    $biblioitem->{'collectionissn'}         = $dbh->quote( $biblioitem->{'collectionissn'} );
-    $biblioitem->{'collectionvolume'}       = $dbh->quote( $biblioitem->{'collectionvolume'} );
-    $biblioitem->{'editionstatement'}       = $dbh->quote( $biblioitem->{'editionstatement'} );
-    $biblioitem->{'editionresponsibility'}  = $dbh->quote( $biblioitem->{'editionresponsibility'} );
-    $biblioitem->{'ccode'}        = $dbh->quote( $biblioitem->{'ccode'} );
-    $biblioitem->{'biblionumber'} =
-      $dbh->quote( $biblioitem->{'biblionumber'} );
-
-    $query = "UPDATE biblioitems SET
-        itemtype        = $biblioitem->{'itemtype'},
-        url             = $biblioitem->{'url'},
-        isbn            = $biblioitem->{'isbn'},
-        issn            = $biblioitem->{'issn'},
-        publishercode   = $biblioitem->{'publishercode'},
-        publicationyear = $biblioitem->{'publicationyear'},
-        classification  = $biblioitem->{'classification'},
-        dewey           = $biblioitem->{'dewey'},
-        subclass        = $biblioitem->{'subclass'},
-        illus           = $biblioitem->{'illus'},
-        pages           = $biblioitem->{'pages'},
-        volumeddesc     = $biblioitem->{'volumeddesc'},
-        notes           = $biblioitem->{'bnotes'},
-        size            = $biblioitem->{'size'},
-        place           = $biblioitem->{'place'},
-        collectiontitle = $biblioitem->{'collectiontitle'},
-        collectionissn  = $biblioitem->{'collectionissn'},
-        collectionvolume= $biblioitem->{'collectionvolume'},
-        editionstatement= $biblioitem->{'editionstatement'},
-        editionresponsibility= $biblioitem->{'editionresponsibility'},
-        ccode           = $biblioitem->{'ccode'}
-        where biblionumber = $biblioitem->{'biblionumber'}";
-
-    $dbh->do($query);
+    my $error;
+
+    # re-calculate the cn_sort, it may have changed
+    my ($cn_sort) = GetClassSort($biblioitem->{'biblioitems.cn_source'}, $biblioitem->{'cn_class'}, $biblioitem->{'cn_item'} );
+
+    my $query = 
+    "UPDATE biblioitems 
+    SET biblionumber    = ?,
+        volume          = ?,
+        number          = ?,
+        itemtype        = ?,
+        isbn            = ?,
+        issn            = ?,
+        publicationyear = ?,
+        publishercode   = ?,
+        volumedate      = ?,
+        volumedesc      = ?,
+        collectiontitle = ?,
+        collectionissn  = ?,
+        collectionvolume= ?,
+        editionstatement= ?,
+        editionresponsibility = ?,
+        illus           = ?,
+        pages           = ?,
+        notes           = ?,
+        size            = ?,
+        place           = ?,
+        lccn            = ?,
+        url             = ?,
+        cn_source       = ?,
+        cn_class        = ?,
+        cn_item         = ?,
+        cn_suffix       = ?,
+        cn_sort         = ?,
+        totalissues     = ?
+        where biblioitemnumber = ?
+        ";
+    my $sth = $dbh->prepare($query);
+    $sth->execute(
+        $biblioitem->{'biblionumber'},
+        $biblioitem->{'volume'},
+        $biblioitem->{'number'},
+        $biblioitem->{'itemtype'},
+        $biblioitem->{'isbn'},
+        $biblioitem->{'issn'},
+        $biblioitem->{'publicationyear'},
+        $biblioitem->{'publishercode'},
+        $biblioitem->{'volumedate'},
+        $biblioitem->{'volumedesc'},
+        $biblioitem->{'collectiontitle'},
+        $biblioitem->{'collectionissn'},
+        $biblioitem->{'collectionvolume'},
+        $biblioitem->{'editionstatement'},
+        $biblioitem->{'editionresponsibility'},
+        $biblioitem->{'illus'},
+        $biblioitem->{'pages'},
+        $biblioitem->{'bnotes'},
+        $biblioitem->{'size'},
+        $biblioitem->{'place'},
+        $biblioitem->{'lccn'},
+        $biblioitem->{'url'},
+        $biblioitem->{'biblioitems.cn_source'},
+        $biblioitem->{'cn_class'},
+        $biblioitem->{'cn_item'},
+        $biblioitem->{'cn_suffix'},
+        $cn_sort,
+        $biblioitem->{'totalissues'},
+        $biblioitem->{'biblioitemnumber'}
+    );
     if ( $dbh->errstr ) {
-        warn "ERROR in _koha_modify_biblioitem $query";
+        $error.="ERROR in _koha_modify_biblioitem_nonmarc $query".$dbh->errstr;
+        warn $error;
     }
+    return ($biblioitem->{'biblioitemnumber'},$error);
 }
 
 =head2 _koha_add_biblioitem
 
 =over 4
 
-_koha_add_biblioitem( $dbh, $biblioitem );
+my ($biblioitemnumber,$error) = _koha_add_biblioitem( $dbh, $biblioitem );
 
 Internal function to add a biblioitem
 
@@ -3459,242 +2789,80 @@ Internal function to add a biblioitem
 
 sub _koha_add_biblioitem {
     my ( $dbh, $biblioitem ) = @_;
-
-    #  my $dbh   = C4Connect;
-    my $sth = $dbh->prepare("SELECT max(biblioitemnumber) FROM biblioitems");
-    my $data;
-    my $bibitemnum;
-
-    $sth->execute;
-    $data       = $sth->fetchrow_arrayref;
-    $bibitemnum = $$data[0] + 1;
-
-    $sth->finish;
-
-    $sth = $dbh->prepare(
-        "INSERT INTO biblioitems SET
-            biblioitemnumber = ?, biblionumber    = ?,
-            volume           = ?, number          = ?,
-            classification   = ?, itemtype        = ?,
-            url              = ?, isbn            = ?,
-            issn             = ?, dewey           = ?,
-            subclass         = ?, publicationyear = ?,
-            publishercode    = ?, volumedate      = ?,
-            volumeddesc      = ?, illus           = ?,
-            pages            = ?, notes           = ?,
-            size             = ?, lccn            = ?,
-            marc             = ?, lcsort          = ?,
-            place            = ?, ccode           = ?,
-            collectiontitle  = ?, collectionissn  = ?,
-            collectionvolume = ?, editionstatement= ?,
-            editionresponsibility= ?
-          "
-    );
-    my ($lcsort) =
-      calculatelc( $biblioitem->{'classification'} )
-      . $biblioitem->{'subclass'};
+    my $error;
+
+    my ($cn_sort) = GetClassSort($biblioitem->{'biblioitems.cn_source'}, $biblioitem->{'cn_class'}, $biblioitem->{'cn_item'} );
+    my $query =
+    "INSERT INTO biblioitems SET
+        biblionumber    = ?,
+        volume          = ?,
+        number          = ?,
+        itemtype        = ?,
+        isbn            = ?,
+        issn            = ?,
+        publicationyear = ?,
+        publishercode   = ?,
+        volumedate      = ?,
+        volumedesc      = ?,
+        collectiontitle = ?,
+        collectionissn  = ?,
+        collectionvolume= ?,
+        editionstatement= ?,
+        editionresponsibility = ?,
+        illus           = ?,
+        pages           = ?,
+        notes           = ?,
+        size            = ?,
+        place           = ?,
+        lccn            = ?,
+        marc            = ?,
+        url             = ?,
+        cn_source       = ?,
+        cn_class        = ?,
+        cn_item         = ?,
+        cn_suffix       = ?,
+        cn_sort         = ?,
+        totalissues     = ?
+        ";
+    my $sth = $dbh->prepare($query);
     $sth->execute(
-        $bibitemnum,                     $biblioitem->{'biblionumber'},
-        $biblioitem->{'volume'},         $biblioitem->{'number'},
-        $biblioitem->{'classification'}, $biblioitem->{'itemtype'},
-        $biblioitem->{'url'},            $biblioitem->{'isbn'},
-        $biblioitem->{'issn'},           $biblioitem->{'dewey'},
-        $biblioitem->{'subclass'},       $biblioitem->{'publicationyear'},
-        $biblioitem->{'publishercode'},  $biblioitem->{'volumedate'},
-        $biblioitem->{'volumeddesc'},    $biblioitem->{'illus'},
-        $biblioitem->{'pages'},          $biblioitem->{'bnotes'},
-        $biblioitem->{'size'},           $biblioitem->{'lccn'},
-        $biblioitem->{'marc'},           $biblioitem->{'place'},
-        $lcsort,                         $biblioitem->{'ccode'},
-        $biblioitem->{'collectiontitle'},$biblioitem->{'collectionissn'},
-        $biblioitem->{'collectionvolume'},$biblioitem->{'editionstatement'},
-        $biblioitem->{'editionresponsibility'}
-    );
-    $sth->finish;
-    return ($bibitemnum);
-}
-
-=head2 _koha_new_items
-
-=over 4
-
-_koha_new_items( $dbh, $item, $barcode );
-
-=back
-
-=cut
-
-sub _koha_new_items {
-    my ( $dbh, $item, $barcode ) = @_;
-
-    #  my $dbh   = C4Connect;
-    my $sth = $dbh->prepare("Select max(itemnumber) from items");
-    my $data;
-    my $itemnumber;
-    my $error = "";
-
-    $sth->execute;
-    $data       = $sth->fetchrow_hashref;
-    $itemnumber = $data->{'max(itemnumber)'} + 1;
-    $sth->finish;
-## Now calculate lccalnumber
-    my ($cutterextra) = itemcalculator(
-        $dbh,
-        $item->{'biblioitemnumber'},
-        $item->{'itemcallnumber'}
-    );
-
-# FIXME the "notforloan" field seems to be named "loan" in some places. workaround bugfix.
-    if ( $item->{'loan'} ) {
-        $item->{'notforloan'} = $item->{'loan'};
-    }
-
-    # if dateaccessioned is provided, use it. Otherwise, set to NOW()
-    if ( $item->{'dateaccessioned'} eq '' || !$item->{'dateaccessioned'} ) {
-
-        $sth = $dbh->prepare(
-            "Insert into items set
-            itemnumber           = ?,     biblionumber     = ?,
-            multivolumepart      = ?,
-            biblioitemnumber     = ?,     barcode          = ?,
-            booksellerid         = ?,     dateaccessioned  = NOW(),
-            homebranch           = ?,     holdingbranch    = ?,
-            price                = ?,     replacementprice = ?,
-            replacementpricedate = NOW(), datelastseen     = NOW(),
-            multivolume          = ?,     stack            = ?,
-            itemlost             = ?,     wthdrawn         = ?,
-            paidfor              = ?,     itemnotes        = ?,
-            itemcallnumber       =?,      notforloan       = ?,
-            location             = ?,     Cutterextra      = ?
-          "
-        );
-        $sth->execute(
-            $itemnumber,                $item->{'biblionumber'},
-            $item->{'multivolumepart'}, $item->{'biblioitemnumber'},
-            $barcode,                   $item->{'booksellerid'},
-            $item->{'homebranch'},      $item->{'holdingbranch'},
-            $item->{'price'},           $item->{'replacementprice'},
-            $item->{multivolume},       $item->{stack},
-            $item->{itemlost},          $item->{wthdrawn},
-            $item->{paidfor},           $item->{'itemnotes'},
-            $item->{'itemcallnumber'},  $item->{'notforloan'},
-            $item->{'location'},        $cutterextra
-        );
-    }
-    else {
-        $sth = $dbh->prepare(
-            "INSERT INTO items SET
-            itemnumber           = ?,     biblionumber     = ?,
-            multivolumepart      = ?,
-            biblioitemnumber     = ?,     barcode          = ?,
-            booksellerid         = ?,     dateaccessioned  = ?,
-            homebranch           = ?,     holdingbranch    = ?,
-            price                = ?,     replacementprice = ?,
-            replacementpricedate = NOW(), datelastseen     = NOW(),
-            multivolume          = ?,     stack            = ?,
-            itemlost             = ?,     wthdrawn         = ?,
-            paidfor              = ?,     itemnotes        = ?,
-            itemcallnumber       = ?,     notforloan       = ?,
-            location             = ?,
-            Cutterextra          = ?
-                            "
-        );
-        $sth->execute(
-            $itemnumber,                 $item->{'biblionumber'},
-            $item->{'multivolumepart'},  $item->{'biblioitemnumber'},
-            $barcode,                    $item->{'booksellerid'},
-            $item->{'dateaccessioned'},  $item->{'homebranch'},
-            $item->{'holdingbranch'},    $item->{'price'},
-            $item->{'replacementprice'}, $item->{multivolume},
-            $item->{stack},              $item->{itemlost},
-            $item->{wthdrawn},           $item->{paidfor},
-            $item->{'itemnotes'},        $item->{'itemcallnumber'},
-            $item->{'notforloan'},       $item->{'location'},
-            $cutterextra
-        );
-    }
-    if ( defined $sth->errstr ) {
-        $error .= $sth->errstr;
-    }
-    return ( $itemnumber, $error );
-}
-
-=head2 _koha_modify_item
-
-=over 4
-
-_koha_modify_item( $dbh, $item, $op );
-
-=back
-
-=cut
-
-sub _koha_modify_item {
-    my ( $dbh, $item, $op ) = @_;
-    $item->{'itemnum'} = $item->{'itemnumber'} unless $item->{'itemnum'};
-
-    # if all we're doing is setting statuses, just update those and get out
-    if ( $op eq "setstatus" ) {
-        my $query =
-          "UPDATE items SET itemlost=?,wthdrawn=?,binding=? WHERE itemnumber=?";
-        my @bind = (
-            $item->{'itemlost'}, $item->{'wthdrawn'},
-            $item->{'binding'},  $item->{'itemnumber'}
-        );
-        my $sth = $dbh->prepare($query);
-        $sth->execute(@bind);
-        $sth->finish;
-        return undef;
-    }
-## Now calculate lccalnumber
-    my ($cutterextra) =
-      itemcalculator( $dbh, $item->{'bibitemnum'}, $item->{'itemcallnumber'} );
-
-    my $query = "UPDATE items SET
-barcode=?,itemnotes=?,itemcallnumber=?,notforloan=?,location=?,multivolumepart=?,multivolume=?,stack=?,wthdrawn=?,holdingbranch=?,homebranch=?,cutterextra=?, onloan=?, binding=?";
-
-    my @bind = (
-        $item->{'barcode'},        $item->{'notes'},
-        $item->{'itemcallnumber'}, $item->{'notforloan'},
-        $item->{'location'},       $item->{multivolumepart},
-        $item->{multivolume},      $item->{stack},
-        $item->{wthdrawn},         $item->{holdingbranch},
-        $item->{homebranch},       $cutterextra,
-        $item->{onloan},           $item->{binding}
+        $biblioitem->{'biblionumber'},
+        $biblioitem->{'volume'},
+        $biblioitem->{'number'},
+        $biblioitem->{'itemtype'},
+        $biblioitem->{'isbn'},
+        $biblioitem->{'issn'},
+        $biblioitem->{'publicationyear'},
+        $biblioitem->{'publishercode'},
+        $biblioitem->{'volumedate'},
+        $biblioitem->{'volumedesc'},
+        $biblioitem->{'collectiontitle'},
+        $biblioitem->{'collectionissn'},
+        $biblioitem->{'collectionvolume'},
+        $biblioitem->{'editionstatement'},
+        $biblioitem->{'editionresponsibility'},
+        $biblioitem->{'illus'},
+        $biblioitem->{'pages'},
+        $biblioitem->{'bnotes'},
+        $biblioitem->{'size'},
+        $biblioitem->{'place'},
+        $biblioitem->{'lccn'},
+        $biblioitem->{'marc'},
+        $biblioitem->{'url'},
+        $biblioitem->{'biblioitems.cn_source'},
+        $biblioitem->{'cn_class'},
+        $biblioitem->{'cn_item'},
+        $biblioitem->{'cn_suffix'},
+        $cn_sort,
+        $biblioitem->{'totalissues'}
     );
-    if ( $item->{'lost'} ne '' ) {
-        $query =
-"update items set biblioitemnumber=?,barcode=?,itemnotes=?,homebranch=?,
-                            itemlost=?,wthdrawn=?,itemcallnumber=?,notforloan=?,
-                             location=?,multivolumepart=?,multivolume=?,stack=?,wthdrawn=?,holdingbranch=?,cutterextra=?,onloan=?, binding=?";
-        @bind = (
-            $item->{'bibitemnum'},     $item->{'barcode'},
-            $item->{'notes'},          $item->{'homebranch'},
-            $item->{'lost'},           $item->{'wthdrawn'},
-            $item->{'itemcallnumber'}, $item->{'notforloan'},
-            $item->{'location'},       $item->{multivolumepart},
-            $item->{multivolume},      $item->{stack},
-            $item->{wthdrawn},         $item->{holdingbranch},
-            $cutterextra,              $item->{onloan},
-            $item->{binding}
-        );
-        if ( $item->{homebranch} ) {
-            $query .= ",homebranch=?";
-            push @bind, $item->{homebranch};
-        }
-        if ( $item->{holdingbranch} ) {
-            $query .= ",holdingbranch=?";
-            push @bind, $item->{holdingbranch};
-        }
-    }
-    $query .= " where itemnumber=?";
-    push @bind, $item->{'itemnum'};
-    if ( $item->{'replacement'} ne '' ) {
-        $query =~ s/ where/,replacementprice='$item->{'replacement'}' where/;
+    my $bibitemnum = $dbh->{'mysql_insertid'};
+    if ( $dbh->errstr ) {
+        $error.="ERROR in _koha_add_biblioitem $query".$dbh->errstr;
+        warn $error;
     }
-    my $sth = $dbh->prepare($query);
-    $sth->execute(@bind);
-    $sth->finish;
+    $sth->finish();
+    return ($bibitemnum,$error);
 }
 
 =head2 _koha_delete_biblio
@@ -3799,130 +2967,8 @@ sub _koha_delete_biblioitems {
     return undef;
 }
 
-=head2 _koha_delete_item
-
-=over 4
-
-_koha_delete_item( $dbh, $itemnum );
-
-Internal function to delete an item record from the koha tables
-
-=back
-
-=cut
-
-sub _koha_delete_item {
-    my ( $dbh, $itemnum ) = @_;
-
-    my $sth = $dbh->prepare("select * from items where itemnumber=?");
-    $sth->execute($itemnum);
-    my $data = $sth->fetchrow_hashref;
-    $sth->finish;
-    my $query = "Insert into deleteditems set ";
-    my @bind  = ();
-    foreach my $temp ( keys %$data ) {
-        $query .= "$temp = ?,";
-        push( @bind, $data->{$temp} );
-    }
-    $query =~ s/\,$//;
-
-    #  print $query;
-    $sth = $dbh->prepare($query);
-    $sth->execute(@bind);
-    $sth->finish;
-    $sth = $dbh->prepare("Delete from items where itemnumber=?");
-    $sth->execute($itemnum);
-    $sth->finish;
-}
-
 =head1 UNEXPORTED FUNCTIONS
 
-=over 4
-
-=head2 calculatelc
-
-$lc = calculatelc($classification);
-
-=back
-
-=cut
-
-sub calculatelc {
-    my ($classification) = @_;
-    $classification =~ s/^\s+|\s+$//g;
-    my $i = 0;
-    my $lc2;
-    my $lc1;
-
-    for ( $i = 0 ; $i < length($classification) ; $i++ ) {
-        my $c = ( substr( $classification, $i, 1 ) );
-        if ( $c ge '0' && $c le '9' ) {
-
-            $lc2 = substr( $classification, $i );
-            last;
-        }
-        else {
-            $lc1 .= substr( $classification, $i, 1 );
-
-        }
-    }    #while
-
-    my $other = length($lc1);
-    if ( !$lc1 ) {
-        $other = 0;
-    }
-
-    my $extras;
-    if ( $other < 4 ) {
-        for ( 1 .. ( 4 - $other ) ) {
-            $extras .= "0";
-        }
-    }
-    $lc1 .= $extras;
-    $lc2 =~ s/^ //g;
-
-    $lc2 =~ s/ //g;
-    $extras = "";
-    ##Find the decimal part of $lc2
-    my $pos = index( $lc2, "." );
-    if ( $pos < 0 ) { $pos = length($lc2); }
-    if ( $pos >= 0 && $pos < 5 ) {
-        ##Pad lc2 with zeros to create a 5digit decimal needed in marc record to sort as numeric
-
-        for ( 1 .. ( 5 - $pos ) ) {
-            $extras .= "0";
-        }
-    }
-    $lc2 = $extras . $lc2;
-    return ( $lc1 . $lc2 );
-}
-
-=head2 itemcalculator
-
-=over 4
-
-$cutterextra = itemcalculator( $dbh, $biblioitem, $callnumber );
-
-=back
-
-=cut
-
-sub itemcalculator {
-    my ( $dbh, $biblioitem, $callnumber ) = @_;
-    my $sth =
-      $dbh->prepare(
-"select classification, subclass from biblioitems where biblioitemnumber=?"
-      );
-
-    $sth->execute($biblioitem);
-    my ( $classification, $subclass ) = $sth->fetchrow;
-    my $all         = $classification . " " . $subclass;
-    my $total       = length($all);
-    my $cutterextra = substr( $callnumber, $total - 1 );
-
-    return $cutterextra;
-}
-
 =head2 ModBiblioMarc
 
     &ModBiblioMarc($newrec,$biblionumber,$frameworkcode);
@@ -3970,45 +3016,13 @@ sub ModBiblioMarc {
     ModZebra($biblionumber,"specialUpdate","biblioserver",$record);
     $sth =
       $dbh->prepare(
-        "update biblioitems set marc=?,marcxml=?  where biblionumber=?");
+        "UPDATE biblioitems SET marc=?,marcxml=? WHERE biblionumber=?");
     $sth->execute( $record->as_usmarc(), $record->as_xml_record($encoding),
         $biblionumber );
     $sth->finish;
     return $biblionumber;
 }
 
-=head2 AddItemInMarc
-
-=over 4
-
-$newbiblionumber = AddItemInMarc( $record, $biblionumber, $frameworkcode );
-
-Add an item in a MARC record and save the MARC record
-
-Function exported, but should NOT be used, unless you really know what you're doing
-
-=back
-
-=cut
-
-sub AddItemInMarc {
-
-    # pass the MARC::Record to this function, and it will create the records in the marc tables
-    my ( $record, $biblionumber, $frameworkcode ) = @_;
-    my $newrec = &GetMarcBiblio($biblionumber);
-
-    # create it
-    my @fields = $record->fields();
-    foreach my $field (@fields) {
-        $newrec->append_fields($field);
-    }
-
-    # FIXME: should we be making sure the biblionumbers are the same?
-    my $newbiblionumber =
-      &ModBiblioMarc( $newrec, $biblionumber, $frameworkcode );
-    return $newbiblionumber;
-}
-
 =head2 z3950_extended_services
 
 z3950_extended_services($serviceType,$serviceOptions,$record);
@@ -4117,25 +3131,6 @@ sub set_service_options {
     return $serviceOptions;
 }
 
-=head2 GetItemsCount
-
-$count = &GetItemsCount( $biblionumber);
-this function return count of item with $biblionumber
-=cut
-
-sub GetItemsCount {
-    my ( $biblionumber ) = @_;
-    my $dbh = C4::Context->dbh;
-    my $query = qq|SELECT count(*)
-                 FROM  items 
-                 WHERE biblionumber=?|;
-    my $sth = $dbh->prepare($query);
-    $sth->execute($biblionumber);
-    my $count = $sth->fetchrow;  
-    $sth->finish;
-    return ($count);
-}
-
 END { }    # module clean-up code here (global destructor)
 
 1;
@@ -4151,167 +3146,3 @@ Paul POULAIN paul.poulain@free.fr
 Joshua Ferraro jmf@liblime.com
 
 =cut
-
-# $Id$
-# $Log$
-# Revision 1.221  2007/07/31 16:01:11  toins
-# Some new functions.
-# TransformHTMLtoMarc rewrited.
-#
-# Revision 1.220  2007/07/20 15:43:16  hdl
-# Bug Fixing GetMarcSubjects.
-# Links parameters were mixed.
-#
-# Revision 1.218  2007/07/19 07:40:08  hdl
-# Adding selection by location for inventory
-#
-# Revision 1.217  2007/07/03 13:47:44  tipaul
-# fixing some display bugs (itemtype not properly returned and a html table bug that makes items appear strangely
-#
-# Revision 1.216  2007/07/03 09:40:58  tipaul
-# return itemtype description properly
-#
-# Revision 1.215  2007/07/03 09:33:05  tipaul
-# if you just replace su by a space in subjects, you'll replace jesus by je s, which is strange for users. this fix solves the problem and introduces authoritysep systempref as separator of subfields, for a better identification of where the authority starts and end
-#
-# Revision 1.214  2007/07/02 09:13:22  tipaul
-# unimarc bugfix : the encoding is in field 100 in UNIMARC. when TransformHTMLtoXML on an item, you must not automatically add a 100 field in items, otherwise there will be 2 100 fields in the biblio, which is wrong
-#
-# Revision 1.213  2007/06/25 15:01:45  tipaul
-# bugfixes on unimarc 100 handling (the field used for encoding)
-#
-# Revision 1.212  2007/06/15 13:44:44  tipaul
-# some fixes (and only fixes)
-#
-# Revision 1.211  2007/06/15 09:40:06  toins
-# do not get $3 $4 and $5 on GetMarcSubjects GetMarcAuthors on unimarc flavour.
-#
-# Revision 1.210  2007/06/13 13:03:34  toins
-# removing warn compilation.
-#
-# Revision 1.209  2007/05/23 16:19:40  tipaul
-# various bugfixes (minor) and french translation updated
-#
-# Revision 1.208  2007/05/22 09:13:54  tipaul
-# Bugfixes & improvements (various and minor) :
-# - updating templates to have tmpl_process3.pl running without any errors
-# - adding a drupal-like css for prog templates (with 3 small images)
-# - fixing some bugs in circulation & other scripts
-# - updating french translation
-# - fixing some typos in templates
-#
-# Revision 1.207  2007/05/22 08:51:19  hdl
-# Changing GetMarcStructure signature.
-# Deleting first parameter $dbh
-#
-# Revision 1.206  2007/05/21 08:44:17  btoumi
-# add security when u delete biblio :
-# u must delete linked items before delete biblio
-#
-# Revision 1.205  2007/05/11 16:04:03  btoumi
-# bug fix:
-# problem in  displayed label link  with subject in detail.tmpl
-# ex: label random => rdom
-#
-# Revision 1.204  2007/05/10 14:45:15  tipaul
-# Koha NoZebra :
-# - support for authorities
-# - some bugfixes in ordering and "CCL" parsing
-# - support for authorities <=> biblios walking
-#
-# Seems I can do what I want now, so I consider its done, except for bugfixes that will be needed i m sure !
-#
-# Revision 1.203  2007/05/03 15:16:02  tipaul
-# BUGFIX for : NoZebra
-# - NoZebra features : seems they work fine now (adding, modifying, deleting)
-# - Biblio edition major bugfix : before this commit editing a biblio resulted in an item removal in marcxml field
-#
-# Revision 1.202  2007/05/02 16:44:31  tipaul
-# NoZebra SQL index management :
-# * adding 3 subs in Biblio.pm
-# - GetNoZebraIndexes, that get the index structure in a new systempreference (added with this commit)
-# - _DelBiblioNoZebra, that retrieve all index entries for a biblio and remove in a variable the biblio reference
-# - _AddBiblioNoZebra, that add index entries for a biblio.
-# Note that the 2 _Add and _Del subs work only in a hash variable, to speed up things in case of a modif (ie : delete+add). The effective SQL update is done in the ModZebra sub (that existed before, and dealed with zebra index).
-# I think the code has to be more deeply tested, but it works at least partially.
-#
-# Revision 1.201  2007/04/27 14:00:49  hdl
-# Removing $dbh from GetMarcFromKohaField (dbh is not used in this function.)
-#
-# Revision 1.200  2007/04/25 16:26:42  tipaul
-# Koha 3.0 nozebra 1st commit : the script misc/migration_tools/rebuild_nozebra.pl build the nozebra table, and, if you set NoZebra to Yes, queries will be done through zebra. TODO :
-# - add nozebra table management on biblio editing
-# - the index table content is hardcoded. I still have to add some specific systempref to let the library update it
-# - manage pagination (next/previous)
-# - manage facets
-# WHAT works :
-# - NZgetRecords : has exactly the same API & returns as zebra getQuery, except that some parameters are unused
-# - search & sort works quite good
-# - CQL parser is better that what I thought I could do : title="harry and sally" and publicationyear>2000 not itemtype=LIVR should work fine
-#
-# Revision 1.199  2007/04/24 09:07:53  tipaul
-# moving dotransfer to Biblio.pm::ModItemTransfer + some CheckReserves fixes
-#
-# Revision 1.198  2007/04/23 15:21:17  tipaul
-# renaming currenttransfers to transferstoreceive
-#
-# Revision 1.197  2007/04/18 17:00:14  tipaul
-# removing all useless %env / $env
-#
-# Revision 1.196  2007/04/17 08:48:00  tipaul
-# circulation cleaning continued: bufixing
-#
-# Revision 1.195  2007/04/04 16:46:22  tipaul
-# HUGE COMMIT : code cleaning circulation.
-#
-# some stuff to do, i'll write a mail on koha-devel NOW !
-#
-# Revision 1.194  2007/03/30 12:00:42  tipaul
-# why the hell do we need to explicitly utf8 decode this string ? I really don't know, but it seems it's mandatory, otherwise, tag descriptions are not properly encoded...
-#
-# Revision 1.193  2007/03/29 16:45:53  tipaul
-# Code cleaning of Biblio.pm (continued)
-#
-# All subs have be cleaned :
-# - removed useless
-# - merged some
-# - reordering Biblio.pm completly
-# - using only naming conventions
-#
-# Seems to have broken nothing, but it still has to be heavily tested.
-# Note that Biblio.pm is now much more efficient than previously & probably more reliable as well.
-#
-# Revision 1.192  2007/03/29 13:30:31  tipaul
-# Code cleaning :
-# == Biblio.pm cleaning (useless) ==
-# * some sub declaration dropped
-# * removed modbiblio sub
-# * removed moditem sub
-# * removed newitems. It was used only in finishrecieve. Replaced by a TransformKohaToMarc+AddItem, that is better.
-# * removed MARCkoha2marcItem
-# * removed MARCdelsubfield declaration
-# * removed MARCkoha2marcBiblio
-#
-# == Biblio.pm cleaning (naming conventions) ==
-# * MARCgettagslib renamed to GetMarcStructure
-# * MARCgetitems renamed to GetMarcItem
-# * MARCfind_frameworkcode renamed to GetFrameworkCode
-# * MARCmarc2koha renamed to TransformMarcToKoha
-# * MARChtml2marc renamed to TransformHtmlToMarc
-# * MARChtml2xml renamed to TranformeHtmlToXml
-# * zebraop renamed to ModZebra
-#
-# == MARC=OFF ==
-# * removing MARC=OFF related scripts (in cataloguing directory)
-# * removed checkitems (function related to MARC=off feature, that is completly broken in head. If someone want to reintroduce it, hard work coming...)
-# * removed getitemsbybiblioitem (used only by MARC=OFF scripts, that is removed as well)
-#
-# Revision 1.191  2007/03/29 09:42:13  tipaul
-# adding default value new feature into cataloguing. The system (definition) part has already been added by toins
-#
-# Revision 1.190  2007/03/29 08:45:19  hdl
-# Deleting ignore_errors(1) pour MARC::Charset
-#
-# Revision 1.189  2007/03/28 10:39:16  hdl
-# removing $dbh as a parameter in AuthoritiesMarc functions
-# And reporting all differences into the scripts taht relies on those functions.