partial 1481: adding to templates, fixing non-display of data
[koha.git] / C4 / Biblio.pm
index d8ca22f..8ebb148 100644 (file)
@@ -18,2991 +18,4124 @@ package C4::Biblio;
 # Suite 330, Boston, MA  02111-1307 USA
 
 use strict;
+
 require Exporter;
+# use utf8;
 use C4::Context;
-use C4::Database;
-use C4::Date;
 use MARC::Record;
 use MARC::File::USMARC;
 use MARC::File::XML;
 use ZOOM;
+use C4::Koha;
+use C4::Date;
+use C4::Log; # logaction
 
 use vars qw($VERSION @ISA @EXPORT);
 
 # set the version for version checking
-$VERSION = 0.01;
+$VERSION = do { my @v = '$Revision$' =~ /\d+/g; shift(@v).".".join( "_", map { sprintf "%03d", $_ } @v ); };
 
-@ISA = qw(Exporter);
+@ISA = qw( Exporter );
 
-#
-# don't forget MARCxxx subs are exported only for testing purposes. Should not be used
-# as the old-style API and the NEW one are the only public functions.
-#
-@EXPORT = qw(
-  &newbiblio &newbiblioitem
-  &newsubject &newsubtitle &newitems 
-  
-  &modbiblio &checkitems &modbibitem
-  &modsubtitle &modsubject &modaddauthor &moditem
-  
-  &delitem &deletebiblioitem &delbiblio
+# EXPORTED FUNCTIONS.
+
+# to add biblios or items
+push @EXPORT, qw( &AddBiblio &AddItem );
+
+# to get something
+push @EXPORT, qw(
+  &GetBiblio
+  &GetBiblioData
+  &GetBiblioItemData
+  &GetBiblioItemInfosOf
+  &GetBiblioItemByBiblioNumber
+  &GetBiblioFromItemNumber
   
-  &getbiblio &bibdata &bibitems &bibitemdata 
-  &barcodes &ItemInfo &itemdata &itemissues &itemcount 
-  &getsubject &getaddauthor &getsubtitle
-  &getwebbiblioitems &getwebsites
-  &getbiblioitembybiblionumber
-  &getbiblioitem &getitemsbybiblioitem
-
-  &MARCfind_marc_from_kohafield
-  &MARCfind_frameworkcode
-  &find_biblioitemnumber
-  &MARCgettagslib
-
-  &NEWnewbiblio &NEWnewitem
-  &NEWmodbiblio &NEWmoditem
-  &NEWdelbiblio &NEWdelitem
-  &NEWmodbiblioframework
-
-  &MARCkoha2marcBiblio &MARCmarc2koha
-  &MARCkoha2marcItem &MARChtml2marc
-  &MARCgetbiblio &MARCgetitem
-  &XMLgetbiblio
+  &GetMarcItem
+  &GetItem
+  &GetItemInfosOf
+  &GetItemStatus
+  &GetItemLocation
+  &GetLostItems
+  &GetItemsForInventory
+  &GetItemsCount
+
+  &GetMarcNotes
+  &GetMarcSubjects
+  &GetMarcBiblio
+  &GetMarcAuthors
+  &GetMarcSeries
+  &GetUsedMarcStructure
+
+  &GetItemsInfo
+  &GetItemsByBiblioitemnumber
+  &GetItemnumberFromBarcode
+  &get_itemnumbers_of
+  &GetXmlBiblio
+
+  &GetAuthorisedValueDesc
+  &GetMarcStructure
+  &GetMarcFromKohaField
+  &GetFrameworkCode
+  &GetPublisherNameFromIsbn
+  &TransformKohaToMarc
+);
+
+# To modify something
+push @EXPORT, qw(
+  &ModBiblio
+  &ModItem
+  &ModItemTransfer
+  &ModBiblioframework
+  &ModZebra
+  &ModItemInMarc
+  &ModItemInMarconefield
+  &ModDateLastSeen
+);
+
+# To delete something
+push @EXPORT, qw(
+  &DelBiblio
+  &DelItem
+);
+
+# Internal functions
+# those functions are exported but should not be used
+# they are usefull is few circumstances, so are exported.
+# but don't use them unless you're a core developer ;-)
+push @EXPORT, qw(
+  &ModBiblioMarc
+  &AddItemInMarc
+  &calculatelc
+  &itemcalculator
+);
+
+# Others functions
+push @EXPORT, qw(
+  &TransformMarcToKoha
+  &TransformHtmlToMarc2
+  &TransformHtmlToMarc
+  &TransformHtmlToXml
+  &PrepareItemrecordDisplay
   &char_decode
-  
-  &FindDuplicate
-  &DisplayISBN
-    
-    get_item_from_barcode
-    MARCfind_MARCbibid_from_oldbiblionumber
+  &GetNoZebraIndexes
 );
 
 =head1 NAME
 
-C4::Biblio - acquisition, catalog  management functions
+C4::Biblio - cataloging management functions
 
-=head1 SYNOPSIS
+=head1 DESCRIPTION
 
-( lot of changes for Koha 3.0)
+Biblio.pm contains functions for managing storage and editing of bibliographic data within Koha. Most of the functions in this module are used for cataloging records: adding, editing, or removing biblios, biblioitems, or items. Koha's stores bibliographic information in three places:
 
-Koha 1.2 and previous version used a specific API to manage biblios. This API uses old-DB style parameters.
-They are based on a hash, and store data in biblio/biblioitems/items tables (plus additionalauthors, bibliosubject and bibliosubtitle where applicable)
+=over 4
 
-In Koha 2.0, we introduced a MARC-DB.
+=item 1. in the biblio,biblioitems,items, etc tables, which are limited to a one-to-one mapping to underlying MARC data
 
-In Koha 3.0 we removed this MARC-DB for search as we wanted to use Zebra as search system.
+=item 2. as raw MARC in the Zebra index and storage engine
 
-So in Koha 3.0, saving a record means :
- - storing the raw marc record (iso2709) in biblioitems.marc field. It contains both biblio & items informations.
- - storing the "decoded information" in biblio/biblioitems/items as previously.
- - using zebra to manage search & indexing on the MARC datas.
- In Koha, there is a systempreference saying "MARC=ON" or "MARC=OFF"
- * MARC=ON : when MARC=ON, koha uses a MARC::Record object (in sub parameters). Saving informations in the DB means : 
- - transform the MARC record into a hash
- - add the raw marc record into the hash
- - store them & update zebra
- * MARC=OFF : when MARC=OFF, koha uses a hash object (in sub parameters). Saving informations in the DB means :
- - transform the hash into a MARC record
- - add the raw marc record into the hash
- - store them and update zebra
-That's why we need 3 types of subs :
+=item 3. as raw MARC the biblioitems.marc and biblioitems.marcxml
 
-=head2 REALxxx subs
+=back
 
-all I<subs beginning by REAL> does effective storage of information (with a hash, one field of the hash being the raw marc record). Those subs also update the record in zebra. REAL subs should be only for internal use (called by NEW or "something else" subs
+In the 3.0 version of Koha, the authoritative record-level information is in biblioitems.marcxml
 
-=head2 NEWxxx related subs
+Because the data isn't completely normalized there's a chance for information to get out of sync. The design choice to go with a un-normalized schema was driven by performance and stability concerns. However, if this occur, it can be considered as a bug : The API is (or should be) complete & the only entry point for all biblio/items managements.
 
 =over 4
 
-all I<subs beginning by NEW> use MARC::Record as parameters. it's the API that MUST be used in MARC acquisition system. They just create the hash, add it the raw marc record. Then, they call REALxxx sub.
+=item 1. Compared with MySQL, Zebra is slow to update an index for small data changes -- especially for proc-intensive operations like circulation
 
-all subs requires/use $dbh as 1st parameter and a MARC::Record object as 2nd parameter. they sometimes requires another parameter.
+=item 2. Zebra's index has been known to crash and a backup of the data is necessary to rebuild it in such cases
 
 =back
 
-=head2 something_elsexxx related subs
+Because of this design choice, the process of managing storage and editing is a bit convoluted. Historically, Biblio.pm's grown to an unmanagable size and as a result we have several types of functions currently:
 
 =over 4
 
-all I<subs beginning by seomething else> are the old-style API. They use a hash as parameter, transform the hash into a -small- marc record, and calls REAL subs.
+=item 1. Add*/Mod*/Del*/ - high-level external functions suitable for being called from external scripts to manage the collection
+
+=item 2. _koha_* - low-level internal functions for managing the koha tables
+
+=item 3. Marc management function : as the MARC record is stored in biblioitems.marc(xml), some subs dedicated to it's management are in this package. They should be used only internally by Biblio.pm, the only official entry points being AddBiblio, AddItem, ModBiblio, ModItem.
+
+=item 4. Zebra functions used to update the Zebra index
 
-all subs requires/use $dbh as 1st parameter and a hash as 2nd parameter.
+=item 5. internal helper functions such as char_decode, checkitems, etc. Some of these probably belong in Koha.pm
 
 =back
 
-=head1 API
-
-=cut
-
-sub zebra_create {
-       my ($biblionumber,$record) = @_;
-       # create the iso2709 file for zebra
-#      my $cgidir = C4::Context->intranetdir ."/cgi-bin";
-#      unless (opendir(DIR, "$cgidir")) {
-#                      $cgidir = C4::Context->intranetdir."/";
-#      } 
-#      closedir DIR;
-#      my $filename = $cgidir."/zebra/biblios/BIBLIO".$biblionumber."iso2709";
-#      open F,"> $filename";
-#      print F $record->as_usmarc();
-#      close F;
-#      my $res = system("cd $cgidir/zebra;/usr/local/bin/zebraidx update biblios");
-#      unlink($filename);
-        my $Zconn;
-        my $xmlrecord;
-#      warn "zebra_create : $biblionumber =".$record->as_formatted;
-        eval {
-           $xmlrecord=$record->as_xml();
-           };
-        if ($@){
-           warn "ERROR badly formatted marc record";
-           warn "Skipping record";
-       } 
-        else {
-           eval {
-               $Zconn = new ZOOM::Connection(C4::Context->config("zebradb"));
-           };
-           if ($@){
-               warn "Error ", $@->code(), ": ", $@->message(), "\n";
-               die "Fatal error, cant connect to z3950 server";
-           }
-           
-           $Zconn->option(cqlfile => C4::Context->config("intranetdir")."/zebra/pqf.properties");
-           my $Zpackage = $Zconn->package();
-           $Zpackage->option(action => "specialUpdate");        
-           $Zpackage->option(record => $xmlrecord);
-           $Zpackage->send("update");
-           $Zpackage->destroy;
-       }
-}
+The MARC record (in biblioitems.marcxml) contains the complete marc record, including items. It also contains the biblionumber. That is the reason why it is not stored directly by AddBiblio, with all other fields . To save a biblio, we need to :
+
+=over 4
 
-=head
+=item 1. save datas in biblio and biblioitems table, that gives us a biblionumber and a biblioitemnumber
 
-z3950_extended_services can handle any interaction with Zebra's extended serices package.
+=item 2. add the biblionumber and biblioitemnumber into the MARC records
 
-$Zconn contains the server connection object (which is set before calling this s
-ubroutine)
+=item 3. save the marc record
 
-$service type is one of:
-        itemorder,create,drop,commit,update,xmlupdate
+=back
 
-$service_options is a hash of key/value pairs. For instance,
-if service_type is 'update', $service_options should contain:
+When dealing with items, we must :
 
-action => update action, one of specialUpdate, recordInsert, recordReplace, recordDelete, elementUpdate.
-(recordidOpaque => Opaque Record ID (user supplied)
+=over 4
 
-or
+=item 1. save the item in items table, that gives us an itemnumber
 
-recordidNumber => Record ID number (system number))
-record => the record itself
+=item 2. add the itemnumber to the item MARC field
 
-and maybe:
+=item 3. overwrite the MARC record (with the added item) into biblioitems.marc(xml)
 
-syntax => the record syntax (transfer syntax)
-databaseName = Database from connection object
+When modifying a biblio or an item, the behaviour is quite similar.
 
-=cut
-sub z3950_extended_services {
-        my ($Zconn,$serviceType,$serviceOptions,$record) = @_;
+=back
 
-        # create a new package object
-        my $Zpackage = $Zconn->package();
+=head1 EXPORTED FUNCTIONS
 
-        # set our options
-        $Zpackage->option(action => $serviceOptions->{'action'});
+=head2 AddBiblio
 
-        if ($serviceOptions->{'databaseName'}) {
-                $Zpackage->option(databaseName => $serviceOptions->{'databaseName'});
-        }
-        if ($serviceOptions->{'recordIdNumber'}) {
-                $Zpackage->option(recordIdNumber => $serviceOptions->{'recordIdNumber'});
+=over 4
+
+($biblionumber,$biblioitemnumber) = AddBiblio($record,$frameworkcode);
+Exported function (core API) for adding a new biblio to koha.
+
+=back
+
+=cut
+
+sub AddBiblio {
+    my ( $record, $frameworkcode ) = @_;
+    my $biblionumber;
+    my $biblioitemnumber;
+    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 );
+    $olddata->{'biblionumber'} = $biblionumber;
+    $biblioitemnumber = _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 );
         }
-        if ($serviceOptions->{'recordIdOpaque'}) {
-                $Zpackage->option(recordIdOpaque => $serviceOptions->{'recordIdOpaque'});
+        else {
+            $newfield =
+              MARC::Field->new( $biblio_tag, '', '',
+                "$biblio_subfield" => $biblionumber );
         }
 
-        # this is an ILL request (Zebra doesn't support it)
-        if ($serviceType eq 'itemorder') {
-           $Zpackage->option('contact-name' => $serviceOptions->{'contact-name'});
-           $Zpackage->option('contact-phone' => $serviceOptions->{'contact-phone'});
-           $Zpackage->option('contact-email' => $serviceOptions->{'contact-email'});
-           $Zpackage->option('itemorder-item' => $serviceOptions->{'itemorder-item'});
-        }
+        # drop old field and create new one...
+        my $old_field = $record->field($biblio_tag);
+        $record->delete_field($old_field);
+        $record->append_fields($newfield);
 
-        if ($record) {
-           $Zpackage->option(record => $record);
-           if ($serviceOptions->{'syntax'}) {
-              $Zpackage->option(syntax => $serviceOptions->{'syntax'});
-           }
+        # deal with biblioitemnumber
+        if ( $biblioitem_tag < 10 ) {
+            $newfield = MARC::Field->new( $biblioitem_tag, $biblioitemnumber, );
         }
-
-        # send the request, handle any exception encountered
-        eval {  $Zpackage->send($serviceType) };
-        if ($@ && $@->isa("ZOOM::Exception")) {
-                print "Oops!  ", $@->message(), "\n";
-                return $@->code();
+        else {
+            $newfield =
+              MARC::Field->new( $biblioitem_tag, '', '',
+                "$biblioitem_subfield" => $biblioitemnumber, );
         }
-        # free up package resources
-        $Zpackage->destroy();
+        # 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);
+    }
+
+    # now add the record
+    $biblionumber = ModBiblioMarc( $record, $biblionumber, $frameworkcode );
+      
+    &logaction(C4::Context->userenv->{'number'},"CATALOGUING","ADD",$biblionumber,"biblio") 
+        if C4::Context->preference("CataloguingLog");
+
+    return ( $biblionumber, $biblioitemnumber );
 }
 
-=head2 @tagslib = &MARCgettagslib($dbh,1|0,$frameworkcode);
+=head2 AddItem
 
-=over 4
+=over 2
 
-2nd param is 1 for liblibrarian and 0 for libopac
-$frameworkcode contains the framework reference. If empty or does not exist, the default one is used
-
-returns a hash with all values for all fields and subfields for a given MARC framework :
-        $res->{$tag}->{lib}        = ($forlibrarian or !$libopac)?$liblibrarian:$libopac;
-                    ->{tab}        = "";            # XXX
-                    ->{mandatory}  = $mandatory;
-                    ->{repeatable} = $repeatable;
-                    ->{$subfield}->{lib}              = ($forlibrarian or !$libopac)?$liblibrarian:$libopac;
-                                 ->{tab}              = $tab;
-                                 ->{mandatory}        = $mandatory;
-                                 ->{repeatable}       = $repeatable;
-                                 ->{authorised_value} = $authorised_value;
-                                 ->{authtypecode}     = $authtypecode;
-                                 ->{value_builder}    = $value_builder;
-                                 ->{kohafield}        = $kohafield;
-                                 ->{seealso}          = $seealso;
-                                 ->{hidden}           = $hidden;
-                                 ->{isurl}            = $isurl;
-                                 ->{link}            = $link;
+    $biblionumber = AddItem( $record, $biblionumber)
+    Exported function (core API) for adding a new item to Koha
 
 =back
 
 =cut
 
-sub MARCgettagslib {
-    my ( $dbh, $forlibrarian, $frameworkcode ) = @_;
-    $frameworkcode = "" unless $frameworkcode;
-    $forlibrarian = 1 unless $forlibrarian;
-    my $sth;
-    my $libfield = ( $forlibrarian eq 1 ) ? 'liblibrarian' : 'libopac';
+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 );
 
-    # check that framework exists
-    $sth =
+    # needs old biblionumber and biblioitemnumber
+    $item->{'biblionumber'} = $biblionumber;
+    my $sth =
       $dbh->prepare(
-        "select count(*) from marc_tag_structure where frameworkcode=?");
-    $sth->execute($frameworkcode);
-    my ($total) = $sth->fetchrow;
-    $frameworkcode = "" unless ( $total > 0 );
+        "select biblioitemnumber,itemtype from biblioitems where biblionumber=?"
+      );
+    $sth->execute( $item->{'biblionumber'} );
+    my $itemtype;
+    ( $item->{'biblioitemnumber'}, $itemtype ) = $sth->fetchrow;
     $sth =
       $dbh->prepare(
-"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 );
-
-    while ( ( $tag, $liblibrarian, $libopac, $mandatory, $repeatable ) = $sth->fetchrow ) {
-        $res->{$tag}->{lib}        = ($forlibrarian or !$libopac)?$liblibrarian:$libopac;
-        $res->{$tag}->{tab}        = "";            # XXX
-        $res->{$tag}->{mandatory}  = $mandatory;
-        $res->{$tag}->{repeatable} = $repeatable;
+        "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 );
     }
-
-    $sth =
-      $dbh->prepare(
-"select tagfield,tagsubfield,liblibrarian,libopac,tab, mandatory, repeatable,authorised_value,authtypecode,value_builder,kohafield,seealso,hidden,isurl,link from marc_subfield_structure where frameworkcode=? order by tagfield,tagsubfield"
-    );
-    $sth->execute($frameworkcode);
-
-    my $subfield;
-    my $authorised_value;
-    my $authtypecode;
-    my $value_builder;
-    my $kohafield;
-    my $seealso;
-    my $hidden;
-    my $isurl;
-       my $link;
-
-    while (
-        ( $tag,         $subfield,   $liblibrarian,   , $libopac,      $tab,
-        $mandatory,     $repeatable, $authorised_value, $authtypecode,
-        $value_builder, $kohafield,  $seealso,          $hidden,
-        $isurl,                        $link )
-        = $sth->fetchrow
-      )
-    {
-        $res->{$tag}->{$subfield}->{lib}              = ($forlibrarian or !$libopac)?$liblibrarian:$libopac;
-        $res->{$tag}->{$subfield}->{tab}              = $tab;
-        $res->{$tag}->{$subfield}->{mandatory}        = $mandatory;
-        $res->{$tag}->{$subfield}->{repeatable}       = $repeatable;
-        $res->{$tag}->{$subfield}->{authorised_value} = $authorised_value;
-        $res->{$tag}->{$subfield}->{authtypecode}     = $authtypecode;
-        $res->{$tag}->{$subfield}->{value_builder}    = $value_builder;
-        $res->{$tag}->{$subfield}->{kohafield}        = $kohafield;
-        $res->{$tag}->{$subfield}->{seealso}          = $seealso;
-        $res->{$tag}->{$subfield}->{hidden}           = $hidden;
-        $res->{$tag}->{$subfield}->{isurl}            = $isurl;
-        $res->{$tag}->{$subfield}->{link}            = $link;
+    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 );
     }
-    return $res;
+    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 ($tagfield,$tagsubfield) = &MARCfind_marc_from_kohafield($dbh,$kohafield);
+=head2 ModBiblio
 
-=over 4
+    ModBiblio( $record,$biblionumber,$frameworkcode);
+    Exported function (core API) to modify a biblio
 
-finds MARC tag and subfield for a given kohafield
-kohafield is "table.field" where table= biblio|biblioitems|items, and field a field of the previous table
+=cut
 
-=back
+sub ModBiblio {
+    my ( $record, $biblionumber, $frameworkcode ) = @_;
+    if (C4::Context->preference("CataloguingLog")) {
+        my $newrecord = GetMarcBiblio($biblionumber);
+        &logaction(C4::Context->userenv->{'number'},"CATALOGUING","MODIFY",$biblionumber,"BEFORE=>".$newrecord->as_formatted);
+    }
+    
+    my $dbh = C4::Context->dbh;
+    
+    $frameworkcode = "" unless $frameworkcode;
 
-=cut
+    # get the items before and append them to the biblio before updating the record, atm we just have the biblio
+    my ( $itemtag, $itemsubfield ) = GetMarcFromKohaField("items.itemnumber",$frameworkcode);
+    my $oldRecord = GetMarcBiblio( $biblionumber );
+    
+    # parse each item, and, for an unknown reason, re-encode each subfield 
+    # if you don't do that, the record will have encoding mixed
+    # and the biblio will be re-encoded.
+    # strange, I (Paul P.) searched more than 1 day to understand what happends
+    # but could only solve the problem this way...
+   my @fields = $oldRecord->field( $itemtag );
+    foreach my $fielditem ( @fields ){
+        my $field;
+        foreach ($fielditem->subfields()) {
+            if ($field) {
+                $field->add_subfields(Encode::encode('utf-8',$_->[0]) => Encode::encode('utf-8',$_->[1]));
+            } else {
+                $field = MARC::Field->new("$itemtag",'','',Encode::encode('utf-8',$_->[0]) => Encode::encode('utf-8',$_->[1]));
+            }
+          }
+        $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 the MARC record (that now contains biblio and items) with the new record data
+    &ModBiblioMarc( $record, $biblionumber, $frameworkcode );
+    
+    # load the koha-table data object
+    my $oldbiblio = TransformMarcToKoha( $dbh, $record, $frameworkcode );
 
-sub MARCfind_marc_from_kohafield {
-    my ( $dbh, $kohafield,$frameworkcode ) = @_;
-    return 0, 0 unless $kohafield;
-    $frameworkcode='' unless $frameworkcode;
-       my $relations = C4::Context->marcfromkohafield;
-       return ($relations->{$frameworkcode}->{$kohafield}->[0],$relations->{$frameworkcode}->{$kohafield}->[1]);
+    # modify the other koha tables
+    _koha_modify_biblio( $dbh, $oldbiblio );
+    _koha_modify_biblioitem( $dbh, $oldbiblio );
+    return 1;
 }
 
-=head2 $MARCRecord = &MARCgetbiblio($dbh,$biblionumber);
+=head2 ModItem
 
-=over 4
+=over 2
+
+Exported function (core API) for modifying an item in Koha.
 
-Returns a MARC::Record for the biblio $biblionumber.
+=back
 
 =cut
 
-sub MARCgetbiblio {
+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;
+    }
 
-    # Returns MARC::Record of the biblio passed in parameter.
-    my ( $dbh, $biblionumber ) = @_;
-       my $sth = $dbh->prepare('select marc from biblioitems where biblionumber=?');
-       $sth->execute($biblionumber);
-       my ($marc) = $sth->fetchrow;
-       my $record = MARC::Record::new_from_usmarc($marc);
-    return $record;
+    # 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 );
+    }
 }
 
-=head2 $XML = &XMLgetbiblio($dbh,$biblionumber);
+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;
+}
 
-=over 4
+=head2 ModBiblioframework
 
-Returns a raw XML for the biblio $biblionumber.
+    ModBiblioframework($biblionumber,$frameworkcode);
+    Exported function to modify a biblio framework
 
 =cut
 
-sub XMLgetbiblio {
-
-    # Returns MARC::Record of the biblio passed in parameter.
-    my ( $dbh, $biblionumber ) = @_;
-       my $sth = $dbh->prepare('select marcxml,marc from biblioitems where biblionumber=?');
-       $sth->execute($biblionumber);
-       my ($XML,$marc) = $sth->fetchrow;
-#      my $record =MARC::Record::new_from_usmarc($marc);
-#      warn "MARC : \n*-************************\n".$record->as_xml."\n*-************************\n";
-    return $XML;
+sub ModBiblioframework {
+    my ( $biblionumber, $frameworkcode ) = @_;
+    my $dbh = C4::Context->dbh;
+    my $sth = $dbh->prepare(
+        "UPDATE biblio SET frameworkcode=? WHERE biblionumber=$biblionumber"
+    );
+    $sth->execute($frameworkcode);
+    return 1;
 }
 
-=head2 $MARCrecord = &MARCgetitem($dbh,$biblionumber);
+=head2 ModItemInMarconefield
 
-=over 4
+=over
 
-Returns a MARC::Record with all items of biblio # $biblionumber
+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 MARCgetitem {
-
-    my ( $dbh, $biblionumber, $itemnumber ) = @_;
-       my $frameworkcode=MARCfind_frameworkcode($dbh,$biblionumber);
-       # get the complete MARC record
-       my $sth = $dbh->prepare("select marc from biblioitems where biblionumber=?");
-       $sth->execute($biblionumber);
-       my ($rawmarc) = $sth->fetchrow;
-       my $record = MARC::File::USMARC::decode($rawmarc);
-       # now, find the relevant itemnumber
-       my ($itemnumberfield,$itemnumbersubfield) = MARCfind_marc_from_kohafield($dbh,'items.itemnumber',$frameworkcode);
-       # prepare the new item record
-       my $itemrecord = MARC::Record->new();
-       # parse all fields fields from the complete record
-       foreach ($record->field($itemnumberfield)) {
-               # when the item field is found, save it
-               if ($_->subfield($itemnumbersubfield) == $itemnumber) {
-                       $itemrecord->append_fields($_);
-               }
-       }
+sub ModItemInMarconefield {
+    my ( $biblionumber, $itemnumber, $itemfield, $newvalue ) = @_;
+    my $dbh = C4::Context->dbh;
+    if ( !defined $newvalue ) {
+        $newvalue = "";
+    }
 
-    return $itemrecord;
+    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 sub find_biblioitemnumber($dbh,$biblionumber);
+=head2 ModItemInMarc
 
-=over 4
+=over
 
-Returns the 1st biblioitemnumber related to $biblionumber. When MARC=ON we should have 1 biblionumber = 1 and only 1 biblioitemnumber
-This sub is useless when MARC=OFF
+&ModItemInMarc( $record, $biblionumber, $itemnumber )
 
 =back
 
 =cut
-sub find_biblioitemnumber {
-       my ( $dbh, $biblionumber ) = @_;
-       my $sth = $dbh->prepare("select biblioitemnumber from biblioitems where biblionumber=?");
-       $sth->execute($biblionumber);
-       my ($biblioitemnumber) = $sth->fetchrow;
-       return $biblioitemnumber;
-}
-
-=head2 $frameworkcode = MARCfind_frameworkcode($dbh,$biblionumber);
 
-=over 4
+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);
+}
 
-returns the framework of a given biblio
+=head2 ModDateLastSeen
 
-=back
+&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 MARCfind_frameworkcode {
-       my ( $dbh, $biblionumber ) = @_;
-       my $sth = $dbh->prepare("select frameworkcode from biblio where biblionumber=?");
-       $sth->execute($biblionumber);
-       my ($frameworkcode) = $sth->fetchrow;
-       return $frameworkcode;
+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
 
-=head2 $MARCRecord = &MARCkoha2marcBiblio($dbh,$bibliohash);
-
-=over 4
+=over
 
-MARCkoha2marcBiblio is a wrapper between old-DB and MARC-DB. It returns a MARC::Record builded with old-DB biblio/biblioitem :
-all entries of the hash are transformed into their matching MARC field/subfield.
+my $error = &DelBiblio($dbh,$biblionumber);
+Exported function (core API) for deleting a biblio in koha.
+Deletes biblio record from Zebra and Koha tables (biblio,biblioitems,items)
+Also backs it up to deleted* tables
+Checks to make sure there are not issues on any of the items
+return:
+C<$error> : undef unless an error occurs
 
 =back
 
 =cut
 
-sub MARCkoha2marcBiblio {
-
-       # this function builds partial MARC::Record from the old koha-DB fields
-       my ( $dbh, $bibliohash ) = @_;
-       # we don't have biblio entries in the hash, so we add them first
-       my $sth = $dbh->prepare("select * from biblio where biblionumber=?");
-       $sth->execute($bibliohash->{biblionumber});
-       my $biblio = $sth->fetchrow_hashref;
-       foreach (keys %$biblio) {
-               $bibliohash->{$_}=$biblio->{$_};
-       }
-       $sth = $dbh->prepare("select tagfield,tagsubfield from marc_subfield_structure where frameworkcode=? and kohafield=?");
-       my $record = MARC::Record->new();
-       foreach ( keys %$bibliohash ) {
-               &MARCkoha2marcOnefield( $sth, $record, "biblio." . $_, $bibliohash->{$_}, '') if $bibliohash->{$_};
-               &MARCkoha2marcOnefield( $sth, $record, "biblioitems." . $_, $bibliohash->{$_}, '') if $bibliohash->{$_};
-       }
-
-       # other fields => additional authors, subjects, subtitles
-       my $sth2 = $dbh->prepare(" SELECT author FROM additionalauthors WHERE biblionumber=?");
-       $sth2->execute($bibliohash->{biblionumber});
-       while ( my $row = $sth2->fetchrow_hashref ) {
-               &MARCkoha2marcOnefield( $sth, $record, "additionalauthors.author", $bibliohash->{'author'},'' );
-       }
-       $sth2 = $dbh->prepare(" SELECT subject FROM bibliosubject WHERE biblionumber=?");
-       $sth2->execute($bibliohash->{biblionumber});
-       while ( my $row = $sth2->fetchrow_hashref ) {
-               &MARCkoha2marcOnefield( $sth, $record, "bibliosubject.subject", $row->{'subject'},'' );
-       }
-       $sth2 = $dbh->prepare(" SELECT subtitle FROM bibliosubtitle WHERE biblionumber=?");
-       $sth2->execute($bibliohash->{biblionumber});
-       while ( my $row = $sth2->fetchrow_hashref ) {
-               &MARCkoha2marcOnefield( $sth, $record, "bibliosubtitle.subtitle", $row->{'subtitle'},'' );
-       }
-       
-       return $record;
-}
-
-=head2 $MARCRecord = &MARCkoha2marcItem($dbh,$biblionumber,itemnumber);
-
-MARCkoha2marcItem is a wrapper between old-DB and MARC-DB. It returns a MARC::Record builded with old-DB items :
-all entries of the hash are transformed into their matching MARC field/subfield.
-
-=over 4
+sub DelBiblio {
+    my ( $biblionumber ) = @_;
+    my $dbh = C4::Context->dbh;
+    my $error;    # for error handling
 
-=back
+    # First make sure there are no items with issues are still 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";
+            }
+        }
+    }
+    return $error if $error;
 
-=cut
+    # Delete in Zebra. Be careful NOT to move this line after _koha_delete_biblio
+    # for at least 2 reasons :
+    # - 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);
 
-sub MARCkoha2marcItem {
+    # delete biblio from Koha tables and save in deletedbiblio
+    $error = &_koha_delete_biblio( $dbh, $biblionumber );
 
-    # this function builds partial MARC::Record from the old koha-DB fields
-    my ( $dbh, $item ) = @_;
+    # delete biblioitems and items from Koha tables and save in deletedbiblioitems,deleteditems
+    $sth =
+      $dbh->prepare(
+        "SELECT biblioitemnumber FROM biblioitems WHERE biblionumber=?");
+    $sth->execute($biblionumber);
+    while ( my $biblioitemnumber = $sth->fetchrow ) {
 
-    #    my $dbh=&C4Connect;
-    my $sth = $dbh->prepare("select tagfield,tagsubfield from marc_subfield_structure where frameworkcode=? and kohafield=?");
-    my $record = MARC::Record->new();
+        # delete this biblioitem
+        $error = &_koha_delete_biblioitems( $dbh, $biblioitemnumber );
+        return $error if $error;
 
-       foreach( keys %$item ) {
-               if ( $item->{$_} ) {
-                       &MARCkoha2marcOnefield( $sth, $record, "items." . $_,
-                               $item->{$_},'' );
-               }
-       }
-    return $record;
+        # 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 MARCkoha2marcOnefield
+=head2 DelItem
 
-=over 4
+=over
 
-This sub is for internal use only, used by koha2marcBiblio & koha2marcItem
+DelItem( $biblionumber, $itemnumber );
+Exported function (core API) for deleting an item record in Koha.
 
 =back
 
 =cut
 
-sub MARCkoha2marcOnefield {
-    my ( $sth, $record, $kohafieldname, $value,$frameworkcode ) = @_;
-    my $tagfield;
-    my $tagsubfield;
-    $sth->execute($frameworkcode,$kohafieldname);
-    if ( ( $tagfield, $tagsubfield ) = $sth->fetchrow ) {
-        if ( $record->field($tagfield) ) {
-            my $tag = $record->field($tagfield);
-            if ($tag) {
-                $tag->add_subfields( $tagsubfield, $value );
-                $record->delete_field($tag);
-                $record->add_fields($tag);
-            }
-        }
-        else {
-            $record->add_fields( $tagfield, " ", " ", $tagsubfield => $value );
+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 );
+
+    #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);
         }
     }
-    return $record;
+    &ModBiblioMarc( $record, $biblionumber, $frameworkcode );
+    &logaction(C4::Context->userenv->{'number'},"CATALOGUING","DELETE",$itemnumber,"item") 
+        if C4::Context->preference("CataloguingLog");
 }
 
-=head2 $MARCrecord = MARChtml2marc($dbh,$rtags,$rsubfields,$rvalues,%indicators);
+=head2 GetBiblioData
 
 =over 4
 
-transforms the parameters (coming from HTML form) into a MARC::Record
-parameters with r are references to arrays.
-
-FIXME : should be improved for 3.0, to avoid having 4 differents arrays
+$data = &GetBiblioData($biblionumber);
+Returns information about the book with the given biblionumber.
+C<&GetBiblioData> returns a reference-to-hash. The keys are the fields in
+the C<biblio> and C<biblioitems> tables in the
+Koha database.
+In addition, C<$data-E<gt>{subject}> is the list of the book's
+subjects, separated by C<" , "> (space, comma, space).
+If there are multiple biblioitems with the given biblionumber, only
+the first one is considered.
 
 =back
 
 =cut
 
-sub MARChtml2marc {
-       my ($dbh,$rtags,$rsubfields,$rvalues,%indicators) = @_;
-       my $prevtag = -1;
-       my $record = MARC::Record->new();
-#      my %subfieldlist=();
-       my $prevvalue; # if tag <10
-       my $field; # if tag >=10
-       for (my $i=0; $i< @$rtags; $i++) {
-               next unless @$rvalues[$i];
-               # rebuild MARC::Record
-#                      warn "0=>".@$rtags[$i].@$rsubfields[$i]." = ".@$rvalues[$i].": ";
-               if (@$rtags[$i] ne $prevtag) {
-                       if ($prevtag < 10) {
-                               if ($prevvalue) {
-                                       if ($prevtag ne '000') {
-                                               $record->add_fields((sprintf "%03s",$prevtag),$prevvalue);
-                                       } else {
-                                               $record->leader($prevvalue);
-                                       }
-                               }
-                       } else {
-                               if ($field) {
-                                       $record->add_fields($field);
-                               }
-                       }
-                       $indicators{@$rtags[$i]}.='  ';
-                       if (@$rtags[$i] <10) {
-                               $prevvalue= @$rvalues[$i];
-                               undef $field;
-                       } else {
-                               undef $prevvalue;
-                               $field = MARC::Field->new( (sprintf "%03s",@$rtags[$i]), substr($indicators{@$rtags[$i]},0,1),substr($indicators{@$rtags[$i]},1,1), @$rsubfields[$i] => @$rvalues[$i]);
-#                      warn "1=>".@$rtags[$i].@$rsubfields[$i]." = ".@$rvalues[$i].": ".$field->as_formatted;
-                       }
-                       $prevtag = @$rtags[$i];
-               } else {
-                       if (@$rtags[$i] <10) {
-                               $prevvalue=@$rvalues[$i];
-                       } else {
-                               if (length(@$rvalues[$i])>0) {
-                                       $field->add_subfields(@$rsubfields[$i] => @$rvalues[$i]);
-#                      warn "2=>".@$rtags[$i].@$rsubfields[$i]." = ".@$rvalues[$i].": ".$field->as_formatted;
-                               }
-                       }
-                       $prevtag= @$rtags[$i];
-               }
-       }
-       # the last has not been included inside the loop... do it now !
-       $record->add_fields($field) if $field;
-#      warn "HTML2MARC=".$record->as_formatted;
-       return $record;
-}
+sub GetBiblioData {
+    my ( $bibnum ) = @_;
+    my $dbh = C4::Context->dbh;
 
+    my $query = "
+        SELECT * , biblioitems.notes AS bnotes, 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
+    ";
+    my $sth = $dbh->prepare($query);
+    $sth->execute($bibnum);
+    my $data;
+    $data = $sth->fetchrow_hashref;
+    $sth->finish;
 
-=head2 $hash = &MARCmarc2koha($dbh,$MARCRecord);
+    return ($data);
+}    # sub GetBiblioData
 
-=over 4
 
-builds a hash with old-db datas from a MARC::Record
+=head2 GetItemsInfo
 
-=back
+=over 4
 
-=cut
+  @results = &GetItemsInfo($biblionumber, $type);
 
-sub MARCmarc2koha {
-       my ($dbh,$record,$frameworkcode) = @_;
-       my $sth=$dbh->prepare("select tagfield,tagsubfield from marc_subfield_structure where frameworkcode=? and kohafield=?");
-       my $result;  
-       my $sth2=$dbh->prepare("SHOW COLUMNS from biblio");
-       $sth2->execute;
-       my $field;
-       while (($field)=$sth2->fetchrow) {
-#              warn "biblio.".$field;
-               $result=&MARCmarc2kohaOneField($sth,"biblio",$field,$record,$result,$frameworkcode);
-       }
-       $sth2=$dbh->prepare("SHOW COLUMNS from biblioitems");
-       $sth2->execute;
-       while (($field)=$sth2->fetchrow) {
-               if ($field eq 'notes') { $field = 'bnotes'; }
-#              warn "biblioitems".$field;
-               $result=&MARCmarc2kohaOneField($sth,"biblioitems",$field,$record,$result,$frameworkcode);
-       }
-       $sth2=$dbh->prepare("SHOW COLUMNS from items");
-       $sth2->execute;
-       while (($field)=$sth2->fetchrow) {
-#              warn "items".$field;
-               $result=&MARCmarc2kohaOneField($sth,"items",$field,$record,$result,$frameworkcode);
-       }
-       # additional authors : specific
-       $result = &MARCmarc2kohaOneField($sth,"bibliosubtitle","subtitle",$record,$result,$frameworkcode);
-       $result = &MARCmarc2kohaOneField($sth,"additionalauthors","additionalauthors",$record,$result,$frameworkcode);
-# modify copyrightdate to keep only the 1st year found
-       my $temp = $result->{'copyrightdate'};
-       if ($temp){
-               $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;
-       }
-       return $result;
-}
-
-sub MARCmarc2kohaOneField {
-
-# FIXME ? if a field has a repeatable subfield that is used in old-db, only the 1st will be retrieved...
-    my ( $sth, $kohatable, $kohafield, $record, $result,$frameworkcode ) = @_;
-    #    warn "kohatable / $kohafield / $result / ";
-    my $res = "";
-    my $tagfield;
-    my $subfield;
-    ( $tagfield, $subfield ) = MARCfind_marc_from_kohafield("",$kohatable.".".$kohafield,$frameworkcode);
-    foreach my $field ( $record->field($tagfield) ) {
-               if ($field->tag()<10) {
-                       if ($result->{$kohafield}) {
-                               # Reverse array filled with elements from repeated subfields 
-                               # from first to last to avoid last to first concatenation of 
-                               # elements in Koha DB.  -- thd.
-                               $result->{$kohafield} .= " | ".reverse($field->data());
-                       } else {
-                               $result->{$kohafield} = $field->data();
-                       }
-               } else {
-                       if ( $field->subfields ) {
-                               my @subfields = $field->subfields();
-                               foreach my $subfieldcount ( 0 .. $#subfields ) {
-                                       if ($subfields[$subfieldcount][0] eq $subfield) {
-                                               if ( $result->{$kohafield} ) {
-                                                       $result->{$kohafield} .= " | " . $subfields[$subfieldcount][1];
-                                               }
-                                               else {
-                                                       $result->{$kohafield} = $subfields[$subfieldcount][1];
-                                               }
-                                       }
-                               }
-                       }
-               }
-    }
-#      warn "OneField for $kohatable.$kohafield and $frameworkcode=> $tagfield, $subfield";
-    return $result;
-}
+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.
 
-=head2 ($biblionumber,$biblioitemnumber) = NEWnewbibilio($dbh,$MARCRecord,$frameworkcode);
+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
 
-creates a biblio from a MARC::Record.
+=item C<$data-E<gt>{branchname}>
 
-=back
+The name (not the code) of the branch to which the book belongs.
 
-=cut
+=item C<$data-E<gt>{datelastseen}>
 
-sub NEWnewbiblio {
-    my ( $dbh, $record, $frameworkcode ) = @_;
-    my $biblionumber;
-    my $biblioitemnumber;
-    my $olddata = MARCmarc2koha( $dbh, $record,$frameworkcode );
-       $olddata->{frameworkcode} = $frameworkcode;
-    $biblionumber = REALnewbiblio( $dbh, $olddata );
-       $olddata->{biblionumber} = $biblionumber;
-       # add biblionumber into the MARC record (it's the ID for zebra)
-       my ( $tagfield, $tagsubfield ) =
-                                       MARCfind_marc_from_kohafield( $dbh, "biblio.biblionumber",$frameworkcode );
-       # create the field
-       my $newfield;
-       if ($tagfield<10) {
-               $newfield = MARC::Field->new(
-                       $tagfield, $biblionumber,
-               );
-       } else {
-               $newfield = MARC::Field->new(
-                       $tagfield, '', '', "$tagsubfield" => $biblionumber,
-               );
-       }
-       # drop old field (just in case it already exist and create new one...
-       my $old_field = $record->field($tagfield);
-       $record->delete_field($old_field);
-       $record->add_fields($newfield);
-
-       #create the marc entry, that stores the rax marc record in Koha 3.0
-       $olddata->{marc} = $record->as_usmarc();
-       $olddata->{marcxml} = $record->as_xml();
-       # and create biblioitem, that's all folks !
-    $biblioitemnumber = REALnewbiblioitem( $dbh, $olddata );
-
-    # search subtiles, addiauthors and subjects
-    ( $tagfield, $tagsubfield ) =
-      MARCfind_marc_from_kohafield( $dbh, "additionalauthors.author",$frameworkcode );
-    my @addiauthfields = $record->field($tagfield);
-    foreach my $addiauthfield (@addiauthfields) {
-        my @addiauthsubfields = $addiauthfield->subfield($tagsubfield);
-        foreach my $subfieldcount ( 0 .. $#addiauthsubfields ) {
-            REALmodaddauthor( $dbh, $biblionumber,
-                $addiauthsubfields[$subfieldcount] );
-        }
-    }
-    ( $tagfield, $tagsubfield ) =
-      MARCfind_marc_from_kohafield( $dbh, "bibliosubtitle.subtitle",$frameworkcode );
-    my @subtitlefields = $record->field($tagfield);
-    foreach my $subtitlefield (@subtitlefields) {
-        my @subtitlesubfields = $subtitlefield->subfield($tagsubfield);
-        foreach my $subfieldcount ( 0 .. $#subtitlesubfields ) {
-            REALnewsubtitle( $dbh, $biblionumber,
-                $subtitlesubfields[$subfieldcount] );
-        }
-    }
-    ( $tagfield, $tagsubfield ) =
-      MARCfind_marc_from_kohafield( $dbh, "bibliosubject.subject",$frameworkcode );
-    my @subj = $record->field($tagfield);
-    my @subjects;
-    foreach my $subject (@subj) {
-        my @subjsubfield = $subject->subfield($tagsubfield);
-        foreach my $subfieldcount ( 0 .. $#subjsubfield ) {
-            push @subjects, $subjsubfield[$subfieldcount];
-        }
-    }
-    REALmodsubject( $dbh, $biblionumber, 1, @subjects );
-    return ( $biblionumber, $biblioitemnumber );
-}
+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<//>.
 
-=head2 NEWmodbilbioframework($dbh,$biblionumber,$frameworkcode);
+=item C<$data-E<gt>{datedue}>
 
-=over 4
+=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}>
 
-modify the framework of a biblio
+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 NEWmodbiblioframework {
-       my ($dbh,$biblionumber,$frameworkcode) =@_;
-       my $sth = $dbh->prepare("Update biblio SET frameworkcode=? WHERE biblionumber=?");
-       $sth->execute($frameworkcode,$biblionumber);
-       return 1;
+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 NEWmodbiblio($dbh,$MARCrecord,$biblionumber,$frameworkcode);
+=head2 getitemstatus
 
 =over 4
 
-modify a biblio (MARC=ON)
+$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
 
-=back
+=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 NEWmodbiblio {
-       my ($dbh,$record,$biblionumber,$frameworkcode) =@_;
-       $frameworkcode="" unless $frameworkcode;
-#      &MARCmodbiblio($dbh,$bibid,$record,$frameworkcode,0);
-       my $oldbiblio = MARCmarc2koha($dbh,$record,$frameworkcode);
-       
-       $oldbiblio->{frameworkcode} = $frameworkcode;
-       #create the marc entry, that stores the rax marc record in Koha 3.0
-       $oldbiblio->{biblionumber} = $biblionumber unless $oldbiblio->{biblionumber};
-       $oldbiblio->{marc} = $record->as_usmarc();
-       $oldbiblio->{marcxml} = $record->as_xml();
-       warn "dans NEWmodbiblio $biblionumber = ".$oldbiblio->{biblionumber}." = ".$oldbiblio->{marcxml};
-       REALmodbiblio($dbh,$oldbiblio);
-       REALmodbiblioitem($dbh,$oldbiblio);
-       # now, modify addi authors, subject, addititles.
-       my ($tagfield,$tagsubfield) = MARCfind_marc_from_kohafield($dbh,"additionalauthors.author",$frameworkcode);
-       my @addiauthfields = $record->field($tagfield);
-       foreach my $addiauthfield (@addiauthfields) {
-               my @addiauthsubfields = $addiauthfield->subfield($tagsubfield);
-               $dbh->do("delete from additionalauthors where biblionumber=$biblionumber");
-               foreach my $subfieldcount (0..$#addiauthsubfields) {
-                       REALmodaddauthor($dbh,$biblionumber,$addiauthsubfields[$subfieldcount]);
-               }
-       }
-       ($tagfield,$tagsubfield) = MARCfind_marc_from_kohafield($dbh,"bibliosubtitle.subtitle",$frameworkcode);
-       my @subtitlefields = $record->field($tagfield);
-       foreach my $subtitlefield (@subtitlefields) {
-               my @subtitlesubfields = $subtitlefield->subfield($tagsubfield);
-               # delete & create subtitle again because REALmodsubtitle can't handle new subtitles
-               # between 2 modifs
-               $dbh->do("delete from bibliosubtitle where biblionumber=$biblionumber");
-               foreach my $subfieldcount (0..$#subtitlesubfields) {
-                       foreach my $subtit(split /\||#/,$subtitlesubfields[$subfieldcount]) {
-                               REALnewsubtitle($dbh,$biblionumber,$subtit);
-                       }
-               }
-       }
-       ($tagfield,$tagsubfield) = MARCfind_marc_from_kohafield($dbh,"bibliosubject.subject",$frameworkcode);
-       my @subj = $record->field($tagfield);
-       my @subjects;
-       foreach my $subject (@subj) {
-               my @subjsubfield = $subject->subfield($tagsubfield);
-               foreach my $subfieldcount (0..$#subjsubfield) {
-                       push @subjects,$subjsubfield[$subfieldcount];
-               }
-       }
-       REALmodsubject($dbh,$biblionumber,1,@subjects);
-       return 1;
+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 NEWmodbilbioframework($dbh,$biblionumber,$frameworkcode);
+=head2 getitemlocation
 
 =over 4
 
-delete a biblio
+$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 NEWdelbiblio {
-    my ( $dbh, $bibid ) = @_;
-    my $biblio = &MARCfind_oldbiblionumber_from_MARCbibid( $dbh, $bibid );
-    &REALdelbiblio( $dbh, $biblio );
-    my $sth =
-      $dbh->prepare(
-        "select biblioitemnumber from biblioitems where biblionumber=?");
-    $sth->execute($biblio);
-    while ( my ($biblioitemnumber) = $sth->fetchrow ) {
-        REALdelbiblioitem( $dbh, $biblioitemnumber );
+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;
     }
-    &MARCdelbiblio( $dbh, $bibid, 0 );
+
+    #No authvalue list
+    #build default
+    $itemlocation{"1"} = "Not For Loan";
+    return \%itemlocation;
 }
 
-=head2 $itemnumber = NEWnewitem($dbh, $record, $biblionumber, $biblioitemnumber);
+=head2 GetLostItems
 
-=over 4
+$items = GetLostItems($where,$orderby);
 
-creates an item from a MARC::Record
+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 NEWnewitem {
-    my ( $dbh, $record, $biblionumber, $biblioitemnumber ) = @_;
+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;
 
-    # add item in old-DB
-       my $frameworkcode=MARCfind_frameworkcode($dbh,$biblionumber);
-    my $item = &MARCmarc2koha( $dbh, $record,$frameworkcode );
-    # needs old biblionumber and biblioitemnumber
-    $item->{'biblionumber'} = $biblionumber;
-    $item->{'biblioitemnumber'}=$biblioitemnumber;
-    $item->{marc} = $record->as_usmarc();
-    warn $item->{marc};
-    my ( $itemnumber, $error ) = &REALnewitems( $dbh, $item, $item->{barcode} );
-       return $itemnumber;
+    my $sth = $dbh->prepare($query);
+    $sth->execute;
+    my @items;
+    while ( my $row = $sth->fetchrow_hashref ){
+        push @items, $row;
+    }
+    return \@items;
 }
 
+=head2 GetItemsForInventory
 
-=head2 $itemnumber = NEWmoditem($dbh, $record, $biblionumber, $biblioitemnumber,$itemnumber);
+$itemlist = GetItemsForInventory($minlocation,$maxlocation,$datelastseen,$offset,$size)
 
-=over 4
+Retrieve a list of title/authors/barcode/callnumber, for biblio inventory.
 
-Modify an item
+The sub returns a list of hashes, containing itemnumber, author, title, barcode & item callnumber.
+It is ordered by callnumber,title.
 
-=back
+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 NEWmoditem {
-    my ( $dbh, $record, $biblionumber, $biblioitemnumber, $itemnumber) = @_;
-    
-       my $frameworkcode=MARCfind_frameworkcode($dbh,$biblionumber);
-    my $olditem = MARCmarc2koha( $dbh, $record,$frameworkcode );
-       # add MARC record
-       $olditem->{marc} = $record->as_usmarc();
-       $olditem->{biblionumber} = $biblionumber;
-       $olditem->{biblioitemnumber} = $biblioitemnumber;
-       # and modify item
-    REALmoditem( $dbh, $olditem );
+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
+
+$itemdata = &GetBiblioItemData($biblioitemnumber);
+
+Looks up the biblioitem with the given biblioitemnumber. Returns a
+reference-to-hash. The keys are the fields from the C<biblio>,
+C<biblioitems>, and C<itemtypes> tables in the Koha database, except
+that C<biblioitems.notes> is given as C<$itemdata-E<gt>{bnotes}>.
+
+=back
+
+=cut
+
+#'
+sub GetBiblioItemData {
+    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 = ? "
+      );
+    my $data;
+    $sth->execute($biblioitemnumber);
+    $data = $sth->fetchrow_hashref;
+    $sth->finish;
+    return ($data);
+}    # sub &GetBiblioItemData
 
-=head2 $itemnumber = NEWdelitem($dbh, $biblionumber, $biblioitemnumber, $itemnumber);
+=head2 GetItemnumberFromBarcode
 
 =over 4
 
-delete an item
+$result = GetItemnumberFromBarcode($barcode);
 
 =back
 
 =cut
 
-sub NEWdelitem {
-    my ( $dbh, $bibid, $itemnumber ) = @_;
-    my $biblio = &MARCfind_oldbiblionumber_from_MARCbibid( $dbh, $bibid );
-    &REALdelitem( $dbh, $itemnumber );
-    &MARCdelitem( $dbh, $bibid, $itemnumber );
-}
+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 $biblionumber = REALnewbiblio($dbh,$biblio);
+=head2 GetBiblioItemByBiblioNumber
 
 =over 4
 
-adds a record in biblio table. Datas are in the hash $biblio.
+NOTE : This function has been copy/paste from C4/Biblio.pm from head before zebra integration.
 
 =back
 
 =cut
 
-sub REALnewbiblio {
-    my ( $dbh, $biblio ) = @_;
+sub GetBiblioItemByBiblioNumber {
+    my ($biblionumber) = @_;
+    my $dbh = C4::Context->dbh;
+    my $sth = $dbh->prepare("Select * from biblioitems where biblionumber = ?");
+    my $count = 0;
+    my @results;
 
-       $dbh->do('lock tables biblio WRITE');
-    my $sth = $dbh->prepare("Select max(biblionumber) from biblio");
-    $sth->execute;
-    my $data   = $sth->fetchrow_arrayref;
-    my $bibnum = $$data[0] + 1;
-    my $series = 0;
+    $sth->execute($biblionumber);
 
-    if ( $biblio->{'seriestitle'} ) { $series = 1 }
-    $sth->finish;
-    $sth =
-      $dbh->prepare("insert into biblio set    biblionumber=?, title=?,                author=?,       copyrightdate=?,
-                                                                                       serial=?,               seriestitle=?,  notes=?,        abstract=?,
-                                                                                       unititle=?"
-    );
-    $sth->execute(
-        $bibnum,             $biblio->{'title'},
-        $biblio->{'author'}, $biblio->{'copyrightdate'},
-        $biblio->{'serial'},             $biblio->{'seriestitle'},
-        $biblio->{'notes'},  $biblio->{'abstract'},
-               $biblio->{'unititle'}
-    );
+    while ( my $data = $sth->fetchrow_hashref ) {
+        push @results, $data;
+    }
 
     $sth->finish;
-       $dbh->do('unlock tables');
-    return ($bibnum);
+    return @results;
 }
 
-=head2 $biblionumber = REALmodbiblio($dbh,$biblio);
+=head2 GetBiblioFromItemNumber
 
 =over 4
 
-modify a record in biblio table. Datas are in the hash $biblio.
+$item = &GetBiblioFromItemNumber($itemnumber);
+
+Looks up the item with the given itemnumber.
+
+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
+database.
 
 =back
 
 =cut
 
-sub REALmodbiblio {
-    my ( $dbh, $biblio ) = @_;
-    my $sth = $dbh->prepare("Update biblio set title=?,                author=?,       abstract=?,     copyrightdate=?,
-                                                                                               seriestitle=?,  serial=?,       unititle=?,     notes=?,        frameworkcode=? 
-                                                                                       where biblionumber = ?"
-    );
-    $sth->execute(
-               $biblio->{'title'},       $biblio->{'author'},
-               $biblio->{'abstract'},    $biblio->{'copyrightdate'},
-               $biblio->{'seriestitle'}, $biblio->{'serial'},
-               $biblio->{'unititle'},    $biblio->{'notes'},
-               $biblio->{frameworkcode},
-               $biblio->{'biblionumber'}
+#'
+sub GetBiblioFromItemNumber {
+    my ( $itemnumber ) = @_;
+    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->finish;
-       return ( $biblio->{'biblionumber'} );
-}    # sub modbiblio
 
-=head2 REALmodsubtitle($dbh,$bibnum,$subtitle);
+    $sth->execute($itemnumber);
+    my $data = $sth->fetchrow_hashref;
+    $sth->finish;
+    return ($data);
+}
+
+=head2 GetBiblio
 
 =over 4
 
-modify subtitles in bibliosubtitle table.
+( $count, @results ) = &GetBiblio($biblionumber);
 
 =back
 
 =cut
 
-sub REALmodsubtitle {
-    my ( $dbh, $bibnum, $subtitle ) = @_;
-    my $sth =
-      $dbh->prepare(
-        "update bibliosubtitle set subtitle = ? where biblionumber = ?");
-    $sth->execute( $subtitle, $bibnum );
+sub GetBiblio {
+    my ($biblionumber) = @_;
+    my $dbh = C4::Context->dbh;
+    my $sth = $dbh->prepare("Select * from biblio where biblionumber = ?");
+    my $count = 0;
+    my @results;
+    $sth->execute($biblionumber);
+    while ( my $data = $sth->fetchrow_hashref ) {
+        $results[$count] = $data;
+        $count++;
+    }    # while
     $sth->finish;
-}    # sub modsubtitle
+    return ( $count, @results );
+}    # sub GetBiblio
 
-=head2 REALmodaddauthor($dbh,$bibnum,$author);
+=head2 GetItem
 
 =over 4
 
-adds or modify additional authors
-NOTE :  Strange sub : seems to delete MANY and add only ONE author... maybe buggy ?
+$data = &GetItem($itemnumber,$barcode);
+
+return Item information, for a given itemnumber or barcode
 
 =back
 
 =cut
 
-sub REALmodaddauthor {
-    my ( $dbh, $bibnum, @authors ) = @_;
-
-    #    my $dbh   = C4Connect;
-    my $sth =
-      $dbh->prepare("Delete from additionalauthors where biblionumber = ?");
-
-    $sth->execute($bibnum);
-    $sth->finish;
-    foreach my $author (@authors) {
-        if ( $author ne '' ) {
-            $sth =
-              $dbh->prepare(
-                "Insert into additionalauthors set author = ?, biblionumber = ?"
+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( $author, $bibnum );
-
-            $sth->finish;
-        }    # if
+        $sth->execute($barcode);
+        my $data = $sth->fetchrow_hashref;
+        return $data;
     }
-}    # sub modaddauthor
+}    # sub GetItem
 
-=head2 $errors = REALmodsubject($dbh,$bibnum, $force, @subject);
+=head2 get_itemnumbers_of
 
 =over 4
 
-modify/adds subjects
+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 REALmodsubject {
-    my ( $dbh, $bibnum, $force, @subject ) = @_;
 
-    #  my $dbh   = C4Connect;
-    my $count = @subject;
-    my $error="";
-    for ( my $i = 0 ; $i < $count ; $i++ ) {
-        $subject[$i] =~ s/^ //g;
-        $subject[$i] =~ s/ $//g;
-        my $sth =
-          $dbh->prepare(
-"select * from catalogueentry where entrytype = 's' and catalogueentry = ?"
-        );
-        $sth->execute( $subject[$i] );
+sub get_itemnumbers_of {
+    my @biblionumbers = @_;
 
-        if ( my $data = $sth->fetchrow_hashref ) {
-        }
-        else {
-            if ( $force eq $subject[$i] || $force == 1 ) {
+    my $dbh = C4::Context->dbh;
 
-                # subject not in aut, chosen to force anway
-                # so insert into cataloguentry so its in auth file
-                my $sth2 =
-                  $dbh->prepare(
-"Insert into catalogueentry (entrytype,catalogueentry) values ('s',?)"
-                );
+    my $query = '
+        SELECT itemnumber,
+            biblionumber
+        FROM items
+        WHERE biblionumber IN (?' . ( ',?' x scalar @biblionumbers - 1 ) . ')
+    ';
+    my $sth = $dbh->prepare($query);
+    $sth->execute(@biblionumbers);
 
-                $sth2->execute( $subject[$i] ) if ( $subject[$i] );
-                $sth2->finish;
-            }
-            else {
-                $error =
-                  "$subject[$i]\n does not exist in the subject authority file";
-                my $sth2 =
-                  $dbh->prepare(
-"Select * from catalogueentry where entrytype = 's' and (catalogueentry like ? or catalogueentry like ? or catalogueentry like ?)"
-                );
-                $sth2->execute( "$subject[$i] %", "% $subject[$i] %",
-                    "% $subject[$i]" );
-                while ( my $data = $sth2->fetchrow_hashref ) {
-                    $error .= "<br>$data->{'catalogueentry'}";
-                }    # while
-                $sth2->finish;
-            }    # else
-        }    # else
-        $sth->finish;
-    }    # else
-    if ($error eq '') {
-        my $sth =
-          $dbh->prepare("Delete from bibliosubject where biblionumber = ?");
-        $sth->execute($bibnum);
-        $sth->finish;
-        $sth =
-          $dbh->prepare(
-            "Insert into bibliosubject (subject,biblionumber) values (?,?)");
-        my $query;
-        foreach $query (@subject) {
-            $sth->execute( $query, $bibnum ) if ( $query && $bibnum );
-        }    # foreach
-        $sth->finish;
-    }    # if
+    my %itemnumbers_of;
+
+    while ( my ( $itemnumber, $biblionumber ) = $sth->fetchrow_array ) {
+        push @{ $itemnumbers_of{$biblionumber} }, $itemnumber;
+    }
 
-    #  $dbh->disconnect;
-    return ($error);
-}    # sub modsubject
+    return \%itemnumbers_of;
+}
 
-=head2 REALmodbiblioitem($dbh, $biblioitem);
+=head2 GetItemInfosOf
 
 =over 4
 
-modify a biblioitem
+GetItemInfosOf(@itemnumbers);
 
 =back
 
 =cut
-sub REALmodbiblioitem {
-    my ( $dbh, $biblioitem ) = @_;
-    my $query;
 
-    my $sth = $dbh->prepare("update biblioitems set number=?,volume=?,                 volumedate=?,           lccn=?,
-                                                                               itemtype=?,                     url=?,                          isbn=?,                         issn=?,
-                                                                               publishercode=?,        publicationyear=?,      classification=?,       dewey=?,
-                                                                               subclass=?,                     illus=?,                        pages=?,                        volumeddesc=?,
-                                                                               notes=?,                        size=?,                         place=?,                        marc=?,
-                                                                               marcxml=?
-                                                       where biblioitemnumber=?");
-       $sth->execute(  $biblioitem->{number},                  $biblioitem->{volume},  $biblioitem->{volumedate},      $biblioitem->{lccn},
-                                       $biblioitem->{itemtype},                $biblioitem->{url},             $biblioitem->{isbn},    $biblioitem->{issn},
-                               $biblioitem->{publishercode},   $biblioitem->{publicationyear}, $biblioitem->{classification},  $biblioitem->{dewey},
-                               $biblioitem->{subclass},                $biblioitem->{illus},           $biblioitem->{pages},   $biblioitem->{volumeddesc},
-                               $biblioitem->{bnotes},                  $biblioitem->{size},            $biblioitem->{place},   $biblioitem->{marc},
-                                       $biblioitem->{marcxml},                 $biblioitem->{biblioitemnumber});
-       my $record = MARC::File::USMARC::decode($biblioitem->{marc});
-       zebra_create($biblioitem->{biblionumber}, $record);
-#      warn "MOD : $biblioitem->{biblioitemnumber} = ".$biblioitem->{marc};
-}    # sub modbibitem
-
-=head2 REALnewbiblioitem($dbh,$biblioitem);
+sub GetItemInfosOf {
+    my @itemnumbers = @_;
+
+    my $query = '
+        SELECT *
+        FROM items
+        WHERE itemnumber IN (' . join( ',', @itemnumbers ) . ')
+    ';
+    return get_infos_of( $query, 'itemnumber' );
+}
+
+=head2 GetItemsByBiblioitemnumber
 
 =over 4
 
-adds a biblioitem ($biblioitem is a hash with the values)
+GetItemsByBiblioitemnumber($biblioitemnumber);
+
+Returns an arrayref of hashrefs suitable for use in a TMPL_LOOP
+Called by moredetail.pl
 
 =back
 
 =cut
 
-sub REALnewbiblioitem {
-       my ( $dbh, $biblioitem ) = @_;
-
-       $dbh->do("lock tables biblioitems WRITE, biblio WRITE, marc_subfield_structure READ");
-       my $sth = $dbh->prepare("Select max(biblioitemnumber) from biblioitems");
-       my $data;
-       my $biblioitemnumber;
-
-       $sth->execute;
-       $data       = $sth->fetchrow_arrayref;
-       $biblioitemnumber = $$data[0] + 1;
-       
-       # Insert biblioitemnumber in MARC record, we need it to manage items later...
-       my $frameworkcode=MARCfind_frameworkcode($dbh,$biblioitem->{biblionumber});
-       my ($biblioitemnumberfield,$biblioitemnumbersubfield) = MARCfind_marc_from_kohafield($dbh,'biblioitems.biblioitemnumber',$frameworkcode);
-       my $record = MARC::File::USMARC::decode($biblioitem->{marc});
-       my $field=$record->field($biblioitemnumberfield);
-       $field->update($biblioitemnumbersubfield => "$biblioitemnumber");
-       $biblioitem->{marc} = $record->as_usmarc();
-       $biblioitem->{marcxml} = $record->as_xml();
-
-       $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             = ?,                           place            = ?,
-                                                                       marcxml          = ?"
-       );
-       $sth->execute(
-               $biblioitemnumber,               $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'},
-               $biblioitem->{marcxml},
-       );
-       $dbh->do("unlock tables");
-       zebra_create($biblioitem->{biblionumber}, $record);
-       return ($biblioitemnumber);
-}
-
-=head2 REALnewsubtitle($dbh,$bibnum,$subtitle);
+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
 
-create a new subtitle
+GetBiblioItemInfosOf(@biblioitemnumbers);
 
 =back
 
 =cut
-sub REALnewsubtitle {
-    my ( $dbh, $bibnum, $subtitle ) = @_;
-    my $sth =
-      $dbh->prepare(
-        "insert into bibliosubtitle set biblionumber = ?, subtitle = ?");
-    $sth->execute( $bibnum, $subtitle ) if $subtitle;
-    $sth->finish;
+
+sub GetBiblioItemInfosOf {
+    my @biblioitemnumbers = @_;
+
+    my $query = '
+        SELECT biblioitemnumber,
+            publicationyear,
+            itemtype
+        FROM biblioitems
+        WHERE biblioitemnumber IN (' . join( ',', @biblioitemnumbers ) . ')
+    ';
+    return get_infos_of( $query, 'biblioitemnumber' );
 }
 
-=head2 ($itemnumber,$errors)= REALnewitems($dbh,$item,$barcode);
+=head1 FUNCTIONS FOR HANDLING MARC MANAGEMENT
+
+=head2 GetMarcStructure
 
 =over 4
 
-create a item. $item is a hash and $barcode the barcode.
+$res = GetMarcStructure($forlibrarian,$frameworkcode);
+
+Returns a reference to a big hash of hash, with the Marc structure for the given frameworkcode
+$forlibrarian  :if set to 1, the MARC descriptions are the librarians ones, otherwise it's the public (OPAC) ones
+$frameworkcode : the framework code to read
 
 =back
 
 =cut
 
-sub REALnewitems {
-    my ( $dbh, $item, $barcode ) = @_;
-
-#      warn "OLDNEWITEMS";
-       
-       $dbh->do('lock tables items WRITE, biblio WRITE,biblioitems WRITE,marc_subfield_structure WRITE');
-    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;
+sub GetMarcStructure {
+    my ( $forlibrarian, $frameworkcode ) = @_;
+    my $dbh=C4::Context->dbh;
+    $frameworkcode = "" unless $frameworkcode;
+    my $sth;
+    my $libfield = ( $forlibrarian eq 1 ) ? 'liblibrarian' : 'libopac';
 
-# FIXME the "notforloan" field seems to be named "loan" in some places. workaround bugfix.
-    if ( $item->{'loan'} ) {
-        $item->{'notforloan'} = $item->{'loan'};
-    }
+    # check that framework exists
+    $sth =
+      $dbh->prepare(
+        "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"
+      );
+    $sth->execute($frameworkcode);
+    my ( $liblibrarian, $libopac, $tag, $res, $tab, $mandatory, $repeatable );
 
-    # if dateaccessioned is provided, use it. Otherwise, set to NOW()
-    if ( $item->{'dateaccessioned'} ) {
-        $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 = ?
-                                                       "
-        );
-        $sth->execute(
-                       $itemnumber,                            $item->{'biblionumber'},
-                       $item->{'multivolumepart'},
-                       $item->{'biblioitemnumber'},$item->{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'}
-        );
-               if ( defined $sth->errstr ) {
-                       $error .= $sth->errstr;
-               }
-    }
-    else {
-        $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 = ?
-                                                       "
-        );
-        $sth->execute(
-                       $itemnumber,                            $item->{'biblionumber'},
-                       $item->{'multivolumepart'},
-                       $item->{'biblioitemnumber'},$item->{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'}
-        );
-               if ( defined $sth->errstr ) {
-                       $error .= $sth->errstr;
-               }
+    while ( ( $tag, $liblibrarian, $libopac, $mandatory, $repeatable ) =
+        $sth->fetchrow )
+    {
+        $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->{$tag}->{mandatory}  = $mandatory;
+        $res->{$tag}->{repeatable} = $repeatable;
     }
-       # item stored, now, deal with the marc part...
-       $sth = $dbh->prepare("select biblioitems.marc,biblio.frameworkcode from biblioitems,biblio 
-                                                       where   biblio.biblionumber=biblioitems.biblionumber and 
-                                                                       biblio.biblionumber=?");
-       $sth->execute($item->{biblionumber});
-    if ( defined $sth->errstr ) {
-        $error .= $sth->errstr;
+
+    $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"
+    );
+    
+    $sth->execute($frameworkcode);
+
+    my $subfield;
+    my $authorised_value;
+    my $authtypecode;
+    my $value_builder;
+    my $kohafield;
+    my $seealso;
+    my $hidden;
+    my $isurl;
+    my $link;
+    my $defaultvalue;
+
+    while (
+        (
+            $tag,          $subfield,      $liblibrarian,
+            ,              $libopac,       $tab,
+            $mandatory,    $repeatable,    $authorised_value,
+            $authtypecode, $value_builder, $kohafield,
+            $seealso,      $hidden,        $isurl,
+            $link,$defaultvalue
+        )
+        = $sth->fetchrow
+      )
+    {
+        $res->{$tag}->{$subfield}->{lib} =
+          ( $forlibrarian or !$libopac ) ? $liblibrarian : $libopac;
+        $res->{$tag}->{$subfield}->{tab}              = $tab;
+        $res->{$tag}->{$subfield}->{mandatory}        = $mandatory;
+        $res->{$tag}->{$subfield}->{repeatable}       = $repeatable;
+        $res->{$tag}->{$subfield}->{authorised_value} = $authorised_value;
+        $res->{$tag}->{$subfield}->{authtypecode}     = $authtypecode;
+        $res->{$tag}->{$subfield}->{value_builder}    = $value_builder;
+        $res->{$tag}->{$subfield}->{kohafield}        = $kohafield;
+        $res->{$tag}->{$subfield}->{seealso}          = $seealso;
+        $res->{$tag}->{$subfield}->{hidden}           = $hidden;
+        $res->{$tag}->{$subfield}->{isurl}            = $isurl;
+        $res->{$tag}->{$subfield}->{'link'}           = $link;
+        $res->{$tag}->{$subfield}->{defaultvalue}     = $defaultvalue;
     }
-       my ($rawmarc,$frameworkcode) = $sth->fetchrow;
-       warn "ERROR IN REALnewitem, MARC record not found FOR $item->{biblionumber} => $rawmarc <=" unless $rawmarc;
-       my $record = MARC::File::USMARC::decode($rawmarc);
-       # ok, we have the marc record, add item number to the item field (in {marc}, and add the field to the record)
-       my ($itemnumberfield,$itemnumbersubfield) = MARCfind_marc_from_kohafield($dbh,'items.itemnumber',$frameworkcode);
-       my $itemrecord = MARC::Record->new_from_usmarc($item->{marc});
-        warn $itemrecord;
-        warn $itemnumberfield;
-        warn $itemrecord->field($itemnumberfield);
-       my $itemfield = $itemrecord->field($itemnumberfield);
-       $itemfield->add_subfields($itemnumbersubfield => "$itemnumber");
-       $record->insert_grouped_field($itemfield);
-       # save the record into biblioitem
-       $sth=$dbh->prepare("update biblioitems set marc=?,marcxml=? where biblionumber=?");
-       $sth->execute($record->as_usmarc(),$record->as_xml(),$item->{biblionumber});
-    if ( defined $sth->errstr ) {
-        $error .= $sth->errstr;
+    return $res;
+}
+
+=head2 GetUsedMarcStructure
+
+    the same function as GetMarcStructure expcet it just take field
+    in tab 0-9. (used field)
+    
+    my $results = GetUsedMarcStructure($frameworkcode);
+    
+    L<$results> is a ref to an array which each case containts a ref
+    to a hash which each keys is the columns from marc_subfield_structure
+    
+    L<$frameworkcode> is the framework code. 
+    
+=cut
+
+sub GetUsedMarcStructure($){
+    my $frameworkcode = shift || '';
+    my $dbh           = C4::Context->dbh;
+    my $query         = qq/
+        SELECT *
+        FROM   marc_subfield_structure
+        WHERE   tab > -1 
+            AND frameworkcode = ?
+    /;
+    my @results;
+    my $sth = $dbh->prepare($query);
+    $sth->execute($frameworkcode);
+    while (my $row = $sth->fetchrow_hashref){
+        push @results,$row;
     }
-       zebra_create($item->{biblionumber},$record);
-       $dbh->do('unlock tables');
-    return ( $itemnumber, $error );
+    return \@results;
 }
 
-=head2 REALmoditem($dbh,$item);
+=head2 GetMarcFromKohaField
 
 =over 4
 
-modify item
+($MARCfield,$MARCsubfield)=GetMarcFromKohaField($kohafield,$frameworkcode);
+Returns the MARC fields & subfields mapped to the koha field 
+for the given frameworkcode
 
 =back
 
 =cut
 
-sub REALmoditem {
-    my ( $dbh, $item ) = @_;
-       my $error;
-       $dbh->do('lock tables items WRITE, biblio WRITE,biblioitems WRITE');
-    $item->{'itemnum'} = $item->{'itemnumber'} unless $item->{'itemnum'};
-    my $query = "update items set  barcode=?,itemnotes=?,itemcallnumber=?,notforloan=?,location=?,multivolumepart=?,multivolume=?,stack=?,wthdrawn=?";
-    my @bind = (
-        $item->{'barcode'},                    $item->{'itemnotes'},
-        $item->{'itemcallnumber'},     $item->{'notforloan'},
-        $item->{'location'},           $item->{multivolumepart},
-               $item->{multivolume},           $item->{stack},
-               $item->{wthdrawn},
+sub GetMarcFromKohaField {
+    my ( $kohafield, $frameworkcode ) = @_;
+    return 0, 0 unless $kohafield;
+    my $relations = C4::Context->marcfromkohafield;
+    return (
+        $relations->{$frameworkcode}->{$kohafield}->[0],
+        $relations->{$frameworkcode}->{$kohafield}->[1]
     );
-    if ( $item->{'lost'} ne '' ) {
-        $query = "update items set biblioitemnumber=?,barcode=?,itemnotes=?,homebranch=?,
-                                                       itemlost=?,wthdrawn=?,itemcallnumber=?,notforloan=?,
-                                                       location=?,multivolumepart=?,multivolume=?,stack=?,wthdrawn=?";
-        @bind = (
-            $item->{'bibitemnum'},     $item->{'barcode'},
-            $item->{'itemnotes'},          $item->{'homebranch'},
-            $item->{'lost'},           $item->{'wthdrawn'},
-            $item->{'itemcallnumber'}, $item->{'notforloan'},
-            $item->{'location'},               $item->{multivolumepart},
-                       $item->{multivolume},           $item->{stack},
-                       $item->{wthdrawn},
-        );
-               if ($item->{homebranch}) {
-                       $query.=",homebranch=?";
-                       push @bind, $item->{homebranch};
-               }
-               if ($item->{holdingbranch}) {
-                       $query.=",holdingbranch=?";
-                       push @bind, $item->{holdingbranch};
-               }
+}
+
+=head2 GetMarcBiblio
+
+=over 4
+
+Returns MARC::Record of the biblionumber passed in parameter.
+the marc record contains both biblio & item datas
+
+=back
+
+=cut
+
+sub GetMarcBiblio {
+    my $biblionumber = shift;
+    my $dbh          = C4::Context->dbh;
+    my $sth          =
+      $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'));
+     $marcxml =~ s/\x1e//g;
+     $marcxml =~ s/\x1f//g;
+     $marcxml =~ s/\x1d//g;
+     $marcxml =~ s/\x0f//g;
+     $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 $@;}
+#      $record = MARC::Record::new_from_usmarc( $marc) if $marc;
+    return $record;
+}
+
+=head2 GetXmlBiblio
+
+=over 4
+
+my $marcxml = GetXmlBiblio($biblionumber);
+
+Returns biblioitems.marcxml of the biblionumber passed in parameter.
+The XML contains both biblio & item datas
+
+=back
+
+=cut
+
+sub GetXmlBiblio {
+    my ( $biblionumber ) = @_;
+    my $dbh = C4::Context->dbh;
+    my $sth =
+      $dbh->prepare("select marcxml from biblioitems where biblionumber=? ");
+    $sth->execute($biblionumber);
+    my ($marcxml) = $sth->fetchrow;
+    return $marcxml;
+}
+
+=head2 GetAuthorisedValueDesc
+
+=over 4
+
+my $subfieldvalue =get_authorised_value_desc(
+    $tag, $subf[$i][0],$subf[$i][1], '', $taglib);
+Retrieve the complete description for a given authorised value.
+
+=back
+
+=cut
+
+sub GetAuthorisedValueDesc {
+    my ( $tag, $subfield, $value, $framework, $tagslib ) = @_;
+    my $dbh = C4::Context->dbh;
+    
+    #---- branch
+    if ( $tagslib->{$tag}->{$subfield}->{'authorised_value'} eq "branches" ) {
+        return C4::Branch::GetBranchName($value);
     }
-       $query.=" where itemnumber=?";
-       push @bind,$item->{'itemnum'};
-   if ( $item->{'replacement'} ne '' ) {
-        $query =~ s/ where/,replacementprice='$item->{'replacement'}' where/;
+
+    #---- itemtypes
+    if ( $tagslib->{$tag}->{$subfield}->{'authorised_value'} eq "itemtypes" ) {
+        return getitemtypeinfo($value)->{description};
     }
-    my $sth = $dbh->prepare($query);
-    $sth->execute(@bind);
-       
-       # item stored, now, deal with the marc part...
-       $sth = $dbh->prepare("select biblioitems.marc,biblio.frameworkcode from biblioitems,biblio 
-                                                       where   biblio.biblionumber=biblioitems.biblionumber and 
-                                                                       biblio.biblionumber=? and 
-                                                                       biblioitems.biblioitemnumber=?");
-       $sth->execute($item->{biblionumber},$item->{biblioitemnumber});
-    if ( defined $sth->errstr ) {
-        $error .= $sth->errstr;
+
+    #---- "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 = ?"
+          );
+        $sth->execute( $category, $value );
+        my $data = $sth->fetchrow_hashref;
+        return $data->{'lib'};
     }
-       my ($rawmarc,$frameworkcode) = $sth->fetchrow;
-       warn "ERROR IN REALmoditem, MARC record not found" unless $rawmarc;
-       my $record = MARC::File::USMARC::decode($rawmarc);
-       # ok, we have the marc record, find the previous item record for this itemnumber and delete it
-       my ($itemnumberfield,$itemnumbersubfield) = MARCfind_marc_from_kohafield($dbh,'items.itemnumber',$frameworkcode);
-       # prepare the new item record
-       my $itemrecord = MARC::File::USMARC::decode($item->{marc});
-       my $itemfield = $itemrecord->field($itemnumberfield);
-       $itemfield->add_subfields($itemnumbersubfield => '$itemnumber');
-       # parse all fields fields from the complete record
-       foreach ($record->field($itemnumberfield)) {
-               # when the previous field is found, replace by the new one
-               if ($_->subfield($itemnumbersubfield) == $item->{itemnum}) {
-                       $_->replace_with($itemfield);
-               }
-       }
-#      $record->insert_grouped_field($itemfield);
-       # save the record into biblioitem
-       $sth=$dbh->prepare("update biblioitems set marc=?,marcxml=? where biblionumber=? and biblioitemnumber=?");
-       $sth->execute($record->as_usmarc(),$record->as_xml(),$item->{biblionumber},$item->{biblioitemnumber});
-       zebra_create($item->biblionumber,$record);
-    if ( defined $sth->errstr ) {
-        $error .= $sth->errstr;
+    else {
+        return $value;    # if nothing is found return the original value
     }
-       $dbh->do('unlock tables');
+}
+
+=head2 GetMarcItem
+
+=over 4
+
+Returns MARC::Record of the item passed in parameter.
 
-    #  $dbh->disconnect;
+=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 REALdelitem($dbh,$itemnum);
+
+
+=head2 GetMarcNotes
 
 =over 4
 
-delete item
+$marcnotesarray = GetMarcNotes( $record, $marcflavour );
+Get all notes from the MARC record and returns them in an array.
+The note are stored in differents places depending on MARC flavour
 
 =back
 
 =cut
 
-sub REALdelitem {
-    my ( $dbh, $itemnum ) = @_;
+sub GetMarcNotes {
+    my ( $record, $marcflavour ) = @_;
+    my $scope;
+    if ( $marcflavour eq "MARC21" ) {
+        $scope = '5..';
+    }
+    else {    # assume unimarc if not marc21
+        $scope = '3..';
+    }
+    my @marcnotes;
+    my $note = "";
+    my $tag  = "";
+    my $marcnote;
+    foreach my $field ( $record->field($scope) ) {
+        my $value = $field->as_string();
+        if ( $note ne "" ) {
+            $marcnote = { marcnote => $note, };
+            push @marcnotes, $marcnote;
+            $note = $value;
+        }
+        if ( $note ne $value ) {
+            $note = $note . " " . $value;
+        }
+    }
 
-    #  my $dbh=C4Connect;
-    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} );
+    if ( $note ) {
+        $marcnote = { marcnote => $note };
+        push @marcnotes, $marcnote;    #load last tag into array
     }
-    $query =~ s/\,$//;
+    return \@marcnotes;
+}    # end GetMarcNotes
 
-    #  print $query;
-    $sth = $dbh->prepare($query);
-    $sth->execute(@bind);
-    $sth->finish;
-    $sth = $dbh->prepare("Delete from items where itemnumber=?");
-    $sth->execute($itemnum);
-    $sth->finish;
+=head2 GetMarcSubjects
 
-    #  $dbh->disconnect;
-}
+=over 4
+
+$marcsubjcts = GetMarcSubjects($record,$marcflavour);
+Get all subjects from the MARC record and returns them in an array.
+The subjects are stored in differents places depending on MARC flavour
+
+=back
+
+=cut
+
+sub GetMarcSubjects {
+    my ( $record, $marcflavour ) = @_;
+    my ( $mintag, $maxtag );
+    if ( $marcflavour eq "MARC21" ) {
+        $mintag = "600";
+        $maxtag = "699";
+    }
+    else {    # assume unimarc if not marc21
+        $mintag = "600";
+        $maxtag = "611";
+    }
 
-=head2 REALdelbiblioitem($dbh,$biblioitemnumber);
+    my @marcsubjcts;
+
+    foreach my $field ( $record->fields ) {
+        next unless $field->tag() >= $mintag && $field->tag() <= $maxtag;
+        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 $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:$//;
+            }
+        }
+         $label =~ s/$authoritysep$//;
+        push @marcsubjcts,
+          {
+            label => $label,
+            link  => $link
+          }
+    }
+    return \@marcsubjcts;
+}    #end GetMarcSubjects
+
+=head2 GetMarcAuthors
 
 =over 4
 
-deletes a biblioitem
-NOTE : not standard sub name. Should be REALdelbiblioitem()
+authors = GetMarcAuthors($record,$marcflavour);
+Get all authors from the MARC record and returns them in an array.
+The authors are stored in differents places depending on MARC flavour
 
 =back
 
 =cut
 
-sub REALdelbiblioitem {
-    my ( $dbh, $biblioitemnumber ) = @_;
+sub GetMarcAuthors {
+    my ( $record, $marcflavour ) = @_;
+    my ( $mintag, $maxtag );
+    # 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"; 
+    }
+    else {    # assume unimarc if not marc21
+        $mintag = "701";
+        $maxtag = "712";
+    }
 
-    #    my $dbh   = C4Connect;
-    my $sth = $dbh->prepare( "Select * from biblioitems
-where biblioitemnumber = ?"
-    );
-    my $results;
+    my @marcauthors;
+
+    foreach my $field ( $record->fields ) {
+        next unless $field->tag() >= $mintag && $field->tag() <= $maxtag;
+        my %hash;
+        my @subfields = $field->subfields();
+        my $count_auth = 0;
+        my $and ;
+        for my $authors_subfield (@subfields) {
+            if (
+                $marcflavour ne 'MARC21'
+                and (
+                    ($authors_subfield->[0] eq '3') or
+                    ($authors_subfield->[0] eq '5')
+                )
+            )
+            {
+                next;
+            }
+            if ($count_auth ne '0'){
+                $and = " and au:";
+            }
+            $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;
+    }
+    return \@marcauthors;
+}
 
-    $sth->execute($biblioitemnumber);
+=head2 GetMarcSeries
 
-    if ( $results = $sth->fetchrow_hashref ) {
-        $sth->finish;
-        $sth =
-          $dbh->prepare(
-"Insert into deletedbiblioitems (biblioitemnumber, biblionumber, volume, number, classification, itemtype,
-                                       isbn, issn ,dewey ,subclass ,publicationyear ,publishercode ,volumedate ,volumeddesc ,timestamp ,illus ,
-                                       pages ,notes ,size ,url ,lccn ) values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"
-        );
+=over 4
 
-        $sth->execute(
-            $results->{biblioitemnumber}, $results->{biblionumber},
-            $results->{volume},           $results->{number},
-            $results->{classification},   $results->{itemtype},
-            $results->{isbn},             $results->{issn},
-            $results->{dewey},            $results->{subclass},
-            $results->{publicationyear},  $results->{publishercode},
-            $results->{volumedate},       $results->{volumeddesc},
-            $results->{timestamp},        $results->{illus},
-            $results->{pages},            $results->{notes},
-            $results->{size},             $results->{url},
-            $results->{lccn}
-        );
-        my $sth2 =
-          $dbh->prepare("Delete from biblioitems where biblioitemnumber = ?");
-        $sth2->execute($biblioitemnumber);
-        $sth2->finish();
-    }    # if
-    $sth->finish;
+$marcseriessarray = 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
 
-    # Now delete all the items attached to the biblioitem
-    $sth = $dbh->prepare("Select * from items where biblioitemnumber = ?");
-    $sth->execute($biblioitemnumber);
-    my @results;
-    while ( my $data = $sth->fetchrow_hashref ) {
-        my $query = "Insert into deleteditems set ";
-        my @bind  = ();
-        foreach my $temp ( keys %$data ) {
-            $query .= "$temp = ?,";
-            push ( @bind, $data->{$temp} );
+=back
+
+=cut
+
+sub GetMarcSeries {
+    my ($record, $marcflavour) = @_;
+    my ($mintag, $maxtag);
+    if ($marcflavour eq "MARC21") {
+        $mintag = "440";
+        $maxtag = "490";
+    } else {           # assume unimarc if not marc21
+        $mintag = "600";
+        $maxtag = "619";
+    }
+
+    my @marcseries;
+    my $subjct = "";
+    my $subfield = "";
+    my $marcsubjct;
+
+    foreach my $field ($record->field('440'), $record->field('490')) {
+        my @subfields_loop;
+        #my $value = $field->subfield('a');
+        #$marcsubjct = {MARCSUBJCT => $value,};
+        my @subfields = $field->subfields();
+        #warn "subfields:".join " ", @$subfields;
+        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 $code = $series_subfield->[0];
+            my $value = $series_subfield->[1];
+            my $linkvalue = $value;
+            $linkvalue =~ s/(\(|\))//g;
+            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 {
+            push @subfields_loop, {code => $code, value => $value, link_loop => \@link_loop, separator => $separator, volumenum => $volume_number};
+                       }
+            $counter++;
         }
-        $query =~ s/\,$//;
-        my $sth2 = $dbh->prepare($query);
-        $sth2->execute(@bind);
-    }    # while
-    $sth->finish;
-    $sth = $dbh->prepare("Delete from items where biblioitemnumber = ?");
-    $sth->execute($biblioitemnumber);
-    $sth->finish();
+        push @marcseries, { MARCSERIES_SUBFIELDS_LOOP => \@subfields_loop };
+        #$marcsubjct = {MARCSUBJCT => $field->as_string(),};
+        #push @marcsubjcts, $marcsubjct;
+        #$subjct = $value;
 
-    #    $dbh->disconnect;
-}    # sub deletebiblioitem
+    }
+    my $marcseriessarray=\@marcseries;
+    return $marcseriessarray;
+}  #end getMARCseriess
 
-=head2 REALdelbiblio($dbh,$biblio);
+=head2 GetFrameworkCode
 
 =over 4
 
-delete a biblio
+    $frameworkcode = GetFrameworkCode( $biblionumber )
 
 =back
 
 =cut
 
-sub REALdelbiblio {
-    my ( $dbh, $biblio ) = @_;
-    my $sth = $dbh->prepare("select * from biblio where biblionumber=?");
-    $sth->execute($biblio);
-    if ( my $data = $sth->fetchrow_hashref ) {
-        $sth->finish;
-        my $query = "Insert into deletedbiblio set ";
-        my @bind  = ();
-        foreach my $temp ( keys %$data ) {
-            $query .= "$temp = ?,";
-            push ( @bind, $data->{$temp} );
-        }
+sub GetFrameworkCode {
+    my ( $biblionumber ) = @_;
+    my $dbh = C4::Context->dbh;
+    my $sth = $dbh->prepare("select frameworkcode from biblio where biblionumber=?");
+    $sth->execute($biblionumber);
+    my ($frameworkcode) = $sth->fetchrow;
+    return $frameworkcode;
+}
 
-        #replacing the last , by ",?)"
-        $query =~ s/\,$//;
-        $sth = $dbh->prepare($query);
-        $sth->execute(@bind);
-        $sth->finish;
-        $sth = $dbh->prepare("Delete from biblio where biblionumber=?");
-        $sth->execute($biblio);
-        $sth->finish;
+=head2 GetPublisherNameFromIsbn
+
+    $name = GetPublishercodeFromIsbn($isbn);
+    if(defined $name){
+        ...
     }
-    $sth->finish;
+
+=cut
+
+sub GetPublisherNameFromIsbn($){
+    my $isbn = shift;
+    $isbn =~ s/[- _]//g;
+    $isbn =~ s/^0*//;
+    my @codes = (split '-', DisplayISBN($isbn));
+    my $code = $codes[0].$codes[1].$codes[2];
+    my $dbh  = C4::Context->dbh;
+    my $query = qq{
+        SELECT distinct publishercode
+        FROM   biblioitems
+        WHERE  isbn LIKE ?
+        AND    publishercode IS NOT NULL
+        LIMIT 1
+    };
+    my $sth = $dbh->prepare($query);
+    $sth->execute("$code%");
+    my $name = $sth->fetchrow;
+    return $name if length $name;
+    return undef;
 }
 
-=head2 $number = itemcount($biblio);
+=head2 TransformKohaToMarc
 
 =over 4
 
-returns the number of items attached to a biblio
+    $record = TransformKohaToMarc( $hash )
+    This function builds partial MARC::Record from a hash
+    Hash entries can be from biblio or biblioitems.
+    This function is called in acquisition module, to create a basic catalogue entry from user entry
 
 =back
 
 =cut
 
-sub itemcount {
-    my ($biblio) = @_;
+sub TransformKohaToMarc {
+
+    my ( $hash ) = @_;
     my $dbh = C4::Context->dbh;
+    my $sth =
+    $dbh->prepare(
+        "select tagfield,tagsubfield from marc_subfield_structure where frameworkcode=? and kohafield=?"
+    );
+    my $record = MARC::Record->new();
+    foreach (keys %{$hash}) {
+        &TransformKohaToMarcOneField( $sth, $record, $_,
+            $hash->{$_}, '' );
+        }
+    return $record;
+}
 
-    #  print $query;
-    my $sth = $dbh->prepare("Select count(*) from items where biblionumber=?");
-    $sth->execute($biblio);
-    my $data = $sth->fetchrow_hashref;
-    $sth->finish;
-    return ( $data->{'count(*)'} );
+=head2 TransformKohaToMarcOneField
+
+=over 4
+
+    $record = TransformKohaToMarcOneField( $sth, $record, $kohafieldname, $value, $frameworkcode );
+
+=back
+
+=cut
+
+sub TransformKohaToMarcOneField {
+    my ( $sth, $record, $kohafieldname, $value, $frameworkcode ) = @_;
+    $frameworkcode='' unless $frameworkcode;
+    my $tagfield;
+    my $tagsubfield;
+
+    if ( !defined $sth ) {
+        my $dbh = C4::Context->dbh;
+        $sth = $dbh->prepare(
+            "select tagfield,tagsubfield from marc_subfield_structure where frameworkcode=? and kohafield=?"
+        );
+    }
+    $sth->execute( $frameworkcode, $kohafieldname );
+    if ( ( $tagfield, $tagsubfield ) = $sth->fetchrow ) {
+        my $tag = $record->field($tagfield);
+        if ($tag) {
+            $tag->update( $tagsubfield => $value );
+            $record->delete_field($tag);
+            $record->insert_fields_ordered($tag);
+        }
+        else {
+            $record->add_fields( $tagfield, " ", " ", $tagsubfield => $value );
+        }
+    }
+    return $record;
+}
+
+=head2 TransformHtmlToXml
+
+=over 4
+
+$xml = TransformHtmlToXml( $tags, $subfields, $values, $indicator, $ind_tag, $auth_type )
+
+$auth_type contains :
+- nothing : rebuild a biblio, un UNIMARC the encoding is in 100$a pos 26/27
+- UNIMARCAUTH : rebuild an authority. In UNIMARC, the encoding is in 100$a pos 13/14
+- ITEM : rebuild an item : in UNIMARC, 100$a, it's in the biblio ! (otherwise, we would get 2 100 fields !)
+
+=back
+
+=cut
+
+sub TransformHtmlToXml {
+    my ( $tags, $subfields, $values, $indicator, $ind_tag, $auth_type ) = @_;
+    my $xml = MARC::File::XML::header('UTF-8');
+    $auth_type = C4::Context->preference('marcflavour') unless $auth_type;
+    MARC::File::XML->default_record_format($auth_type);
+    # in UNIMARC, field 100 contains the encoding
+    # check that there is one, otherwise the 
+    # MARC::Record->new_from_xml will fail (and Koha will die)
+    my $unimarc_and_100_exist=0;
+    $unimarc_and_100_exist=1 if $auth_type eq 'ITEM'; # if we rebuild an item, no need of a 100 field
+    my $prevvalue;
+    my $prevtag = -1;
+    my $first   = 1;
+    my $j       = -1;
+    for ( my $i = 0 ; $i <= @$tags ; $i++ ) {
+        if (C4::Context->preference('marcflavour') eq 'UNIMARC' and @$tags[$i] eq "100" and @$subfields[$i] eq "a") {
+            # if we have a 100 field and it's values are not correct, skip them.
+            # if we don't have any valid 100 field, we will create a default one at the end
+            my $enc = substr( @$values[$i], 26, 2 );
+            if ($enc eq '01' or $enc eq '50' or $enc eq '03') {
+                $unimarc_and_100_exist=1;
+            } else {
+                next;
+            }
+        }
+        @$values[$i] =~ s/&/&amp;/g;
+        @$values[$i] =~ s/</&lt;/g;
+        @$values[$i] =~ s/>/&gt;/g;
+        @$values[$i] =~ s/"/&quot;/g;
+        @$values[$i] =~ s/'/&apos;/g;
+#         if ( !utf8::is_utf8( @$values[$i] ) ) {
+#             utf8::decode( @$values[$i] );
+#         }
+        if ( ( @$tags[$i] ne $prevtag ) ) {
+            $j++ unless ( @$tags[$i] eq "" );
+            if ( !$first ) {
+                $xml .= "</datafield>\n";
+                if (   ( @$tags[$i] && @$tags[$i] > 10 )
+                    && ( @$values[$i] ne "" ) )
+                {
+                    my $ind1 = substr( @$indicator[$j], 0, 1 );
+                    my $ind2;
+                    if ( @$indicator[$j] ) {
+                        $ind2 = substr( @$indicator[$j], 1, 1 );
+                    }
+                    else {
+                        warn "Indicator in @$tags[$i] is empty";
+                        $ind2 = " ";
+                    }
+                    $xml .=
+"<datafield tag=\"@$tags[$i]\" ind1=\"$ind1\" ind2=\"$ind2\">\n";
+                    $xml .=
+"<subfield code=\"@$subfields[$i]\">@$values[$i]</subfield>\n";
+                    $first = 0;
+                }
+                else {
+                    $first = 1;
+                }
+            }
+            else {
+                if ( @$values[$i] ne "" ) {
+
+                    # leader
+                    if ( @$tags[$i] eq "000" ) {
+                        $xml .= "<leader>@$values[$i]</leader>\n";
+                        $first = 1;
+
+                        # rest of the fixed fields
+                    }
+                    elsif ( @$tags[$i] < 10 ) {
+                        $xml .=
+"<controlfield tag=\"@$tags[$i]\">@$values[$i]</controlfield>\n";
+                        $first = 1;
+                    }
+                    else {
+                        my $ind1 = substr( @$indicator[$j], 0, 1 );
+                        my $ind2 = substr( @$indicator[$j], 1, 1 );
+                        $xml .=
+"<datafield tag=\"@$tags[$i]\" ind1=\"$ind1\" ind2=\"$ind2\">\n";
+                        $xml .=
+"<subfield code=\"@$subfields[$i]\">@$values[$i]</subfield>\n";
+                        $first = 0;
+                    }
+                }
+            }
+        }
+        else {    # @$tags[$i] eq $prevtag
+            if ( @$values[$i] eq "" ) {
+            }
+            else {
+                if ($first) {
+                    my $ind1 = substr( @$indicator[$j], 0, 1 );
+                    my $ind2 = substr( @$indicator[$j], 1, 1 );
+                    $xml .=
+"<datafield tag=\"@$tags[$i]\" ind1=\"$ind1\" ind2=\"$ind2\">\n";
+                    $first = 0;
+                }
+                $xml .=
+"<subfield code=\"@$subfields[$i]\">@$values[$i]</subfield>\n";
+            }
+        }
+        $prevtag = @$tags[$i];
+    }
+    if (C4::Context->preference('marcflavour') and !$unimarc_and_100_exist) {
+#     warn "SETTING 100 for $auth_type";
+        use POSIX qw(strftime);
+        my $string = strftime( "%Y%m%d", localtime(time) );
+        # set 50 to position 26 is biblios, 13 if authorities
+        my $pos=26;
+        $pos=13 if $auth_type eq 'UNIMARCAUTH';
+        $string = sprintf( "%-*s", 35, $string );
+        substr( $string, $pos , 6, "50" );
+        $xml .= "<datafield tag=\"100\" ind1=\"\" ind2=\"\">\n";
+        $xml .= "<subfield code=\"a\">$string</subfield>\n";
+        $xml .= "</datafield>\n";
+    }
+    $xml .= MARC::File::XML::footer();
+    return $xml;
+}
+
+=head2 TransformHtmlToMarc
+
+    L<$record> = TransformHtmlToMarc(L<$params>,L<$cgi>)
+    L<$params> is a ref to an array as below:
+    {
+        'tag_010_indicator_531951' ,
+        'tag_010_code_a_531951_145735' ,
+        'tag_010_subfield_a_531951_145735' ,
+        'tag_200_indicator_873510' ,
+        'tag_200_code_a_873510_673465' ,
+        'tag_200_subfield_a_873510_673465' ,
+        'tag_200_code_b_873510_704318' ,
+        'tag_200_subfield_b_873510_704318' ,
+        'tag_200_code_e_873510_280822' ,
+        'tag_200_subfield_e_873510_280822' ,
+        'tag_200_code_f_873510_110730' ,
+        'tag_200_subfield_f_873510_110730' ,
+    }
+    L<$cgi> is the CGI object which containts the value.
+    L<$record> is the MARC::Record object.
+
+=cut
+
+sub TransformHtmlToMarc {
+    my $params = shift;
+    my $cgi    = shift;
+    
+    # creating a new record
+    my $record  = MARC::Record->new();
+    my $i=0;
+    my @fields;
+    while ($params->[$i]){ # browse all CGI params
+        my $param = $params->[$i];
+        my $newfield=0;
+        # if we are on biblionumber, store it in the MARC::Record (it may not be in the edited fields)
+        if ($param eq 'biblionumber') {
+            my ( $biblionumbertagfield, $biblionumbertagsubfield ) =
+                &GetMarcFromKohaField( "biblio.biblionumber", '' );
+            if ($biblionumbertagfield < 10) {
+                $newfield = MARC::Field->new(
+                    $biblionumbertagfield,
+                    $cgi->param($param),
+                );
+            } else {
+                $newfield = MARC::Field->new(
+                    $biblionumbertagfield,
+                    '',
+                    '',
+                    "$biblionumbertagsubfield" => $cgi->param($param),
+                );
+            }
+            push @fields,$newfield if($newfield);
+        } 
+        elsif ($param =~ /^tag_(\d*)_indicator_/){ # new field start when having 'input name="..._indicator_..."
+            my $tag  = $1;
+            
+            my $ind1 = substr($cgi->param($param),0,1);
+            my $ind2 = substr($cgi->param($param),1,1);
+            $newfield=0;
+            my $j=$i+1;
+            
+            if($tag < 10){ # no code for theses fields
+    # in MARC editor, 000 contains the leader.
+                if ($tag eq '000' ) {
+                    $record->leader($cgi->param($params->[$j+1])) if length($cgi->param($params->[$j+1]))==24;
+    # between 001 and 009 (included)
+                } else {
+                    $newfield = MARC::Field->new(
+                        $tag,
+                        $cgi->param($params->[$j+1]),
+                    );
+                }
+    # > 009, deal with subfields
+            } else {
+                while($params->[$j] =~ /_code_/){ # browse all it's subfield
+                    my $inner_param = $params->[$j];
+                    if ($newfield){
+                        if($cgi->param($params->[$j+1])){  # only if there is a value (code => value)
+                            $newfield->add_subfields(
+                                $cgi->param($inner_param) => $cgi->param($params->[$j+1])
+                            );
+                        }
+                    } else {
+                        if ( $cgi->param($params->[$j+1]) ) { # creating only if there is a value (code => value)
+                            $newfield = MARC::Field->new(
+                                $tag,
+                                ''.$ind1,
+                                ''.$ind2,
+                                $cgi->param($inner_param) => $cgi->param($params->[$j+1]),
+                            );
+                        }
+                    }
+                    $j+=2;
+                }
+            }
+            push @fields,$newfield if($newfield);
+        }
+        $i++;
+    }
+    
+    $record->append_fields(@fields);
+    return $record;
 }
 
-=head2 $biblionumber = newbiblio($biblio);
+=head2 TransformMarcToKoha
 
 =over 4
 
-create a biblio. The parameter is a hash
+       $result = TransformMarcToKoha( $dbh, $record, $frameworkcode )
 
 =back
 
 =cut
 
-sub newbiblio {
-    my ($biblio) = @_;
-    my $dbh    = C4::Context->dbh;
-    my $bibnum = REALnewbiblio( $dbh, $biblio );
-    # finds new (MARC bibid
-    #  my $bibid = &MARCfind_MARCbibid_from_oldbiblionumber($dbh,$bibnum);
-#     my $record = &MARCkoha2marcBiblio( $dbh, $bibnum );
-#     MARCaddbiblio( $dbh, $record, $bibnum,'' );
-    return ($bibnum);
-}
-
-=head2   $biblionumber = &modbiblio($biblio);
+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 $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 );
+    }
+    $sth2 = $dbh->prepare("SHOW COLUMNS from items");
+    $sth2->execute;
+    while ( ($field) = $sth2->fetchrow ) {
+        $result =
+          &TransformMarcToKohaOneField( "items", $field, $record, $result,
+            $frameworkcode );
+    }
 
-=over 4
+    #
+    # 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;
+    }
 
-Update a biblio record.
+    # 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;
+    }
+    return $result;
+}
 
-C<$biblio> is a reference-to-hash whose keys are the fields in the
-biblio table in the Koha database. All fields must be present, not
-just the ones you wish to change.
+=head2 TransformMarcToKohaOneField
 
-C<&modbiblio> updates the record defined by
-C<$biblio-E<gt>{biblionumber}> with the values in C<$biblio>.
+=over 4
 
-C<&modbiblio> returns C<$biblio-E<gt>{biblionumber}> whether it was
-successful or not.
+$result = TransformMarcToKohaOneField( $kohatable, $kohafield, $record, $result, $frameworkcode )
 
 =back
 
 =cut
 
-sub modbiblio {
-       my ($biblio) = @_;
-       my $dbh  = C4::Context->dbh;
-       my $biblionumber=REALmodbiblio($dbh,$biblio);
-       my $record = MARCkoha2marcBiblio($dbh,$biblionumber,$biblionumber);
-       # finds new (MARC bibid
-       my $bibid = &MARCfind_MARCbibid_from_oldbiblionumber($dbh,$biblionumber);
-       MARCmodbiblio($dbh,$bibid,$record,"",0);
-       return($biblionumber);
-} # sub modbiblio
+sub TransformMarcToKohaOneField {
+
+    # FIXME ? if a field has a repeatable subfield that is used in old-db,
+    # only the 1st will be retrieved...
+    my ( $kohatable, $kohafield, $record, $result, $frameworkcode ) = @_;
+    my $res = "";
+    my ( $tagfield, $subfield ) =
+      GetMarcFromKohaField( $kohatable . "." . $kohafield,
+        $frameworkcode );
+    foreach my $field ( $record->field($tagfield) ) {
+        if ( $field->tag() < 10 ) {
+            if ( $result->{$kohafield} ) {
+                $result->{$kohafield} .= " | " . $field->data();
+            }
+            else {
+                $result->{$kohafield} = $field->data();
+            }
+        }
+        else {
+            if ( $field->subfields ) {
+                my @subfields = $field->subfields();
+                foreach my $subfieldcount ( 0 .. $#subfields ) {
+                    if ( $subfields[$subfieldcount][0] eq $subfield ) {
+                        if ( $result->{$kohafield} ) {
+                            $result->{$kohafield} .=
+                              " | " . $subfields[$subfieldcount][1];
+                        }
+                        else {
+                            $result->{$kohafield} =
+                              $subfields[$subfieldcount][1];
+                        }
+                    }
+                }
+            }
+        }
+    }
+    return $result;
+}
+
+=head1  OTHER FUNCTIONS
 
-=head2   &modsubtitle($biblionumber, $subtitle);
+=head2 char_decode
 
 =over 4
 
-Sets the subtitle of a book.
-
-C<$biblionumber> is the biblionumber of the book to modify.
+my $string = char_decode( $string, $encoding );
 
-C<$subtitle> is the new subtitle.
+converts ISO 5426 coded string to UTF-8
+sloppy code : should be improved in next issue
 
 =back
 
 =cut
 
-sub modsubtitle {
-    my ( $bibnum, $subtitle ) = @_;
-    my $dbh = C4::Context->dbh;
-    &REALmodsubtitle( $dbh, $bibnum, $subtitle );
-}    # sub modsubtitle
-
-=head2 &modaddauthor($biblionumber, $author);
-
-=over 4
+sub char_decode {
+    my ( $string, $encoding ) = @_;
+    $_ = $string;
 
-Replaces all additional authors for the book with biblio number
-C<$biblionumber> with C<$author>. If C<$author> is the empty string,
-C<&modaddauthor> deletes all additional authors.
+    $encoding = C4::Context->preference("marcflavour") unless $encoding;
+    if ( $encoding eq "UNIMARC" ) {
 
-=back
+        #         s/\xe1/Æ/gm;
+        s/\xe2/Ğ/gm;
+        s/\xe9/Ø/gm;
+        s/\xec/ş/gm;
+        s/\xf1/æ/gm;
+        s/\xf3/ğ/gm;
+        s/\xf9/ø/gm;
+        s/\xfb/ß/gm;
+        s/\xc1\x61/à/gm;
+        s/\xc1\x65/è/gm;
+        s/\xc1\x69/ì/gm;
+        s/\xc1\x6f/ò/gm;
+        s/\xc1\x75/ù/gm;
+        s/\xc1\x41/À/gm;
+        s/\xc1\x45/È/gm;
+        s/\xc1\x49/Ì/gm;
+        s/\xc1\x4f/Ò/gm;
+        s/\xc1\x55/Ù/gm;
+        s/\xc2\x41/Á/gm;
+        s/\xc2\x45/É/gm;
+        s/\xc2\x49/Í/gm;
+        s/\xc2\x4f/Ó/gm;
+        s/\xc2\x55/Ú/gm;
+        s/\xc2\x59/İ/gm;
+        s/\xc2\x61/á/gm;
+        s/\xc2\x65/é/gm;
+        s/\xc2\x69/í/gm;
+        s/\xc2\x6f/ó/gm;
+        s/\xc2\x75/ú/gm;
+        s/\xc2\x79/ı/gm;
+        s/\xc3\x41/Â/gm;
+        s/\xc3\x45/Ê/gm;
+        s/\xc3\x49/Î/gm;
+        s/\xc3\x4f/Ô/gm;
+        s/\xc3\x55/Û/gm;
+        s/\xc3\x61/â/gm;
+        s/\xc3\x65/ê/gm;
+        s/\xc3\x69/î/gm;
+        s/\xc3\x6f/ô/gm;
+        s/\xc3\x75/û/gm;
+        s/\xc4\x41/Ã/gm;
+        s/\xc4\x4e/Ñ/gm;
+        s/\xc4\x4f/Õ/gm;
+        s/\xc4\x61/ã/gm;
+        s/\xc4\x6e/ñ/gm;
+        s/\xc4\x6f/õ/gm;
+        s/\xc8\x41/Ä/gm;
+        s/\xc8\x45/Ë/gm;
+        s/\xc8\x49/Ï/gm;
+        s/\xc8\x61/ä/gm;
+        s/\xc8\x65/ë/gm;
+        s/\xc8\x69/ï/gm;
+        s/\xc8\x6F/ö/gm;
+        s/\xc8\x75/ü/gm;
+        s/\xc8\x76/ÿ/gm;
+        s/\xc9\x41/Ä/gm;
+        s/\xc9\x45/Ë/gm;
+        s/\xc9\x49/Ï/gm;
+        s/\xc9\x4f/Ö/gm;
+        s/\xc9\x55/Ü/gm;
+        s/\xc9\x61/ä/gm;
+        s/\xc9\x6f/ö/gm;
+        s/\xc9\x75/ü/gm;
+        s/\xca\x41/Å/gm;
+        s/\xca\x61/å/gm;
+        s/\xd0\x43/Ç/gm;
+        s/\xd0\x63/ç/gm;
 
-=cut
+        # this handles non-sorting blocks (if implementation requires this)
+        $string = nsb_clean($_);
+    }
+    elsif ( $encoding eq "USMARC" || $encoding eq "MARC21" ) {
+        ##MARC-8 to UTF-8
+
+        s/\xe1\x61/à/gm;
+        s/\xe1\x65/è/gm;
+        s/\xe1\x69/ì/gm;
+        s/\xe1\x6f/ò/gm;
+        s/\xe1\x75/ù/gm;
+        s/\xe1\x41/À/gm;
+        s/\xe1\x45/È/gm;
+        s/\xe1\x49/Ì/gm;
+        s/\xe1\x4f/Ò/gm;
+        s/\xe1\x55/Ù/gm;
+        s/\xe2\x41/Á/gm;
+        s/\xe2\x45/É/gm;
+        s/\xe2\x49/Í/gm;
+        s/\xe2\x4f/Ó/gm;
+        s/\xe2\x55/Ú/gm;
+        s/\xe2\x59/İ/gm;
+        s/\xe2\x61/á/gm;
+        s/\xe2\x65/é/gm;
+        s/\xe2\x69/í/gm;
+        s/\xe2\x6f/ó/gm;
+        s/\xe2\x75/ú/gm;
+        s/\xe2\x79/ı/gm;
+        s/\xe3\x41/Â/gm;
+        s/\xe3\x45/Ê/gm;
+        s/\xe3\x49/Î/gm;
+        s/\xe3\x4f/Ô/gm;
+        s/\xe3\x55/Û/gm;
+        s/\xe3\x61/â/gm;
+        s/\xe3\x65/ê/gm;
+        s/\xe3\x69/î/gm;
+        s/\xe3\x6f/ô/gm;
+        s/\xe3\x75/û/gm;
+        s/\xe4\x41/Ã/gm;
+        s/\xe4\x4e/Ñ/gm;
+        s/\xe4\x4f/Õ/gm;
+        s/\xe4\x61/ã/gm;
+        s/\xe4\x6e/ñ/gm;
+        s/\xe4\x6f/õ/gm;
+        s/\xe6\x41/Ă/gm;
+        s/\xe6\x45/Ĕ/gm;
+        s/\xe6\x65/ĕ/gm;
+        s/\xe6\x61/ă/gm;
+        s/\xe8\x45/Ë/gm;
+        s/\xe8\x49/Ï/gm;
+        s/\xe8\x65/ë/gm;
+        s/\xe8\x69/ï/gm;
+        s/\xe8\x76/ÿ/gm;
+        s/\xe9\x41/A/gm;
+        s/\xe9\x4f/O/gm;
+        s/\xe9\x55/U/gm;
+        s/\xe9\x61/a/gm;
+        s/\xe9\x6f/o/gm;
+        s/\xe9\x75/u/gm;
+        s/\xea\x41/A/gm;
+        s/\xea\x61/a/gm;
+
+        #Additional Turkish characters
+        s/\x1b//gm;
+        s/\x1e//gm;
+        s/(\xf0)s/\xc5\x9f/gm;
+        s/(\xf0)S/\xc5\x9e/gm;
+        s/(\xf0)c/ç/gm;
+        s/(\xf0)C/Ç/gm;
+        s/\xe7\x49/\\xc4\xb0/gm;
+        s/(\xe6)G/\xc4\x9e/gm;
+        s/(\xe6)g/ğ\xc4\x9f/gm;
+        s/\xB8/ı/gm;
+        s/\xB9/£/gm;
+        s/(\xe8|\xc8)o/ö/gm;
+        s/(\xe8|\xc8)O/Ö/gm;
+        s/(\xe8|\xc8)u/ü/gm;
+        s/(\xe8|\xc8)U/Ü/gm;
+        s/\xc2\xb8/\xc4\xb1/gm;
+        s/¸/\xc4\xb1/gm;
 
-sub modaddauthor {
-    my ( $bibnum, @authors ) = @_;
-    my $dbh = C4::Context->dbh;
-    &REALmodaddauthor( $dbh, $bibnum, @authors );
-}    # sub modaddauthor
+        # this handles non-sorting blocks (if implementation requires this)
+        $string = nsb_clean($_);
+    }
+    return ($string);
+}
 
-=head2 $error = &modsubject($biblionumber, $force, @subjects);
+=head2 nsb_clean
 
 =over 4
 
-$force - a subject to force
-$error - Error message, or undef if successful.
+my $string = nsb_clean( $string, $encoding );
 
 =back
 
 =cut
 
-sub modsubject {
-    my ( $bibnum, $force, @subject ) = @_;
-    my $dbh = C4::Context->dbh;
-    my $error = &REALmodsubject( $dbh, $bibnum, $force, @subject );
-    if ($error eq ''){
-               # When MARC is off, ensures that the MARC biblio table gets updated with new
-               # subjects, of course, it deletes the biblio in marc, and then recreates.
-               # This check is to ensure that no MARC data exists to lose.
-#              if (C4::Context->preference("MARC") eq '0'){
-#              warn "in modSUBJECT";
-#                      my $MARCRecord = &MARCkoha2marcBiblio($dbh,$bibnum);
-#                      my $bibid = &MARCfind_MARCbibid_from_oldbiblionumber($dbh,$bibnum);
-#                      &MARCmodbiblio($dbh,$bibid, $MARCRecord);
-#              }
-       }
-       return ($error);
-}    # sub modsubject
-
-=head2 modbibitem($biblioitem);
+sub nsb_clean {
+    my $NSB      = '\x88';    # NSB : begin Non Sorting Block
+    my $NSE      = '\x89';    # NSE : Non Sorting Block end
+                              # handles non sorting blocks
+    my ($string) = @_;
+    $_ = $string;
+    s/$NSB/(/gm;
+    s/[ ]{0,1}$NSE/) /gm;
+    $string = $_;
+    return ($string);
+}
+
+=head2 PrepareItemrecordDisplay
 
 =over 4
 
-modify a biblioitem. The parameter is a hash
+PrepareItemrecordDisplay($itemrecord,$bibnum,$itemumber);
+
+Returns a hash with all the fields for Display a given item data in a template
 
 =back
 
 =cut
 
-sub modbibitem {
-    my ($biblioitem) = @_;
+sub PrepareItemrecordDisplay {
+
+    my ( $bibnum, $itemnum ) = @_;
+
     my $dbh = C4::Context->dbh;
-    &REALmodbiblioitem( $dbh, $biblioitem );
-}    # sub modbibitem
+    my $frameworkcode = &GetFrameworkCode( $bibnum );
+    my ( $itemtagfield, $itemtagsubfield ) =
+      &GetMarcFromKohaField( "items.itemnumber", $frameworkcode );
+    my $tagslib = &GetMarcStructure( 1, $frameworkcode );
+    my $itemrecord = GetMarcItem( $bibnum, $itemnum) if ($itemnum);
+    my @loop_data;
+    my $authorised_values_sth =
+      $dbh->prepare(
+"select authorised_value,lib from authorised_values where category=? order by lib"
+      );
+    foreach my $tag ( sort keys %{$tagslib} ) {
+        my $previous_tag = '';
+        if ( $tag ne '' ) {
+            # loop through each subfield
+            my $cntsubf;
+            foreach my $subfield ( sort keys %{ $tagslib->{$tag} } ) {
+                next if ( subfield_is_koha_internal_p($subfield) );
+                next if ( $tagslib->{$tag}->{$subfield}->{'tab'} ne "10" );
+                my %subfield_data;
+                $subfield_data{tag}           = $tag;
+                $subfield_data{subfield}      = $subfield;
+                $subfield_data{countsubfield} = $cntsubf++;
+                $subfield_data{kohafield}     =
+                  $tagslib->{$tag}->{$subfield}->{'kohafield'};
+
+         #        $subfield_data{marc_lib}=$tagslib->{$tag}->{$subfield}->{lib};
+                $subfield_data{marc_lib} =
+                    "<span id=\"error\" title=\""
+                  . $tagslib->{$tag}->{$subfield}->{lib} . "\">"
+                  . substr( $tagslib->{$tag}->{$subfield}->{lib}, 0, 12 )
+                  . "</span>";
+                $subfield_data{mandatory} =
+                  $tagslib->{$tag}->{$subfield}->{mandatory};
+                $subfield_data{repeatable} =
+                  $tagslib->{$tag}->{$subfield}->{repeatable};
+                $subfield_data{hidden} = "display:none"
+                  if $tagslib->{$tag}->{$subfield}->{hidden};
+                my ( $x, $value );
+                ( $x, $value ) = _find_value( $tag, $subfield, $itemrecord )
+                  if ($itemrecord);
+                $value =~ s/"/&quot;/g;
+
+                # search for itemcallnumber if applicable
+                if ( $tagslib->{$tag}->{$subfield}->{kohafield} eq
+                    'items.itemcallnumber'
+                    && C4::Context->preference('itemcallnumber') )
+                {
+                    my $CNtag =
+                      substr( C4::Context->preference('itemcallnumber'), 0, 3 );
+                    my $CNsubfield =
+                      substr( C4::Context->preference('itemcallnumber'), 3, 1 );
+                    my $temp = $itemrecord->field($CNtag) if ($itemrecord);
+                    if ($temp) {
+                        $value = $temp->subfield($CNsubfield);
+                    }
+                }
+                if ( $tagslib->{$tag}->{$subfield}->{authorised_value} ) {
+                    my @authorised_values;
+                    my %authorised_lib;
+
+                    # builds list, depending on authorised value...
+                    #---- branch
+                    if ( $tagslib->{$tag}->{$subfield}->{'authorised_value'} eq
+                        "branches" )
+                    {
+                        if ( ( C4::Context->preference("IndependantBranches") )
+                            && ( C4::Context->userenv->{flags} != 1 ) )
+                        {
+                            my $sth =
+                              $dbh->prepare(
+"select branchcode,branchname from branches where branchcode = ? order by branchname"
+                              );
+                            $sth->execute( C4::Context->userenv->{branch} );
+                            push @authorised_values, ""
+                              unless (
+                                $tagslib->{$tag}->{$subfield}->{mandatory} );
+                            while ( my ( $branchcode, $branchname ) =
+                                $sth->fetchrow_array )
+                            {
+                                push @authorised_values, $branchcode;
+                                $authorised_lib{$branchcode} = $branchname;
+                            }
+                        }
+                        else {
+                            my $sth =
+                              $dbh->prepare(
+"select branchcode,branchname from branches order by branchname"
+                              );
+                            $sth->execute;
+                            push @authorised_values, ""
+                              unless (
+                                $tagslib->{$tag}->{$subfield}->{mandatory} );
+                            while ( my ( $branchcode, $branchname ) =
+                                $sth->fetchrow_array )
+                            {
+                                push @authorised_values, $branchcode;
+                                $authorised_lib{$branchcode} = $branchname;
+                            }
+                        }
+
+                        #----- itemtypes
+                    }
+                    elsif ( $tagslib->{$tag}->{$subfield}->{authorised_value} eq
+                        "itemtypes" )
+                    {
+                        my $sth =
+                          $dbh->prepare(
+"select itemtype,description from itemtypes order by description"
+                          );
+                        $sth->execute;
+                        push @authorised_values, ""
+                          unless ( $tagslib->{$tag}->{$subfield}->{mandatory} );
+                        while ( my ( $itemtype, $description ) =
+                            $sth->fetchrow_array )
+                        {
+                            push @authorised_values, $itemtype;
+                            $authorised_lib{$itemtype} = $description;
+                        }
+
+                        #---- "true" authorised value
+                    }
+                    else {
+                        $authorised_values_sth->execute(
+                            $tagslib->{$tag}->{$subfield}->{authorised_value} );
+                        push @authorised_values, ""
+                          unless ( $tagslib->{$tag}->{$subfield}->{mandatory} );
+                        while ( my ( $value, $lib ) =
+                            $authorised_values_sth->fetchrow_array )
+                        {
+                            push @authorised_values, $value;
+                            $authorised_lib{$value} = $lib;
+                        }
+                    }
+                    $subfield_data{marc_value} = CGI::scrolling_list(
+                        -name     => 'field_value',
+                        -values   => \@authorised_values,
+                        -default  => "$value",
+                        -labels   => \%authorised_lib,
+                        -size     => 1,
+                        -tabindex => '',
+                        -multiple => 0,
+                    );
+                }
+                elsif ( $tagslib->{$tag}->{$subfield}->{thesaurus_category} ) {
+                    $subfield_data{marc_value} =
+"<input type=\"text\" name=\"field_value\"  size=47 maxlength=255> <a href=\"javascript:Dopop('cataloguing/thesaurus_popup.pl?category=$tagslib->{$tag}->{$subfield}->{thesaurus_category}&index=',)\">...</a>";
+
+#"
+# COMMENTED OUT because No $i is provided with this API.
+# And thus, no value_builder can be activated.
+# BUT could be thought over.
+#         } elsif ($tagslib->{$tag}->{$subfield}->{'value_builder'}) {
+#             my $plugin="value_builder/".$tagslib->{$tag}->{$subfield}->{'value_builder'};
+#             require $plugin;
+#             my $extended_param = plugin_parameters($dbh,$itemrecord,$tagslib,$i,0);
+#             my ($function_name,$javascript) = plugin_javascript($dbh,$record,$tagslib,$i,0);
+#             $subfield_data{marc_value}="<input type=\"text\" value=\"$value\" name=\"field_value\"  size=47 maxlength=255 DISABLE READONLY OnFocus=\"javascript:Focus$function_name()\" OnBlur=\"javascript:Blur$function_name()\"> <a href=\"javascript:Clic$function_name()\">...</a> $javascript";
+                }
+                else {
+                    $subfield_data{marc_value} =
+"<input type=\"text\" name=\"field_value\" value=\"$value\" size=50 maxlength=255>";
+                }
+                push( @loop_data, \%subfield_data );
+            }
+        }
+    }
+    my $itemnumber = $itemrecord->subfield( $itemtagfield, $itemtagsubfield )
+      if ( $itemrecord && $itemrecord->field($itemtagfield) );
+    return {
+        'itemtagfield'    => $itemtagfield,
+        'itemtagsubfield' => $itemtagsubfield,
+        'itemnumber'      => $itemnumber,
+        'iteminformation' => \@loop_data
+    };
+}
+#"
 
-=head2 $biblioitemnumber = newbiblioitem($biblioitem)
+#
+# true ModZebra commented until indexdata fixes zebraDB crashes (it seems they occur on multiple updates
+# at the same time
+# replaced by a zebraqueue table, that is filled with ModZebra to run.
+# the table is emptied by misc/cronjobs/zebraqueue_start.pl script
+# =head2 ModZebrafiles
+# 
+# &ModZebrafiles( $dbh, $biblionumber, $record, $folder, $server );
+# 
+# =cut
+# 
+# sub ModZebrafiles {
+# 
+#     my ( $dbh, $biblionumber, $record, $folder, $server ) = @_;
+# 
+#     my $op;
+#     my $zebradir =
+#       C4::Context->zebraconfig($server)->{directory} . "/" . $folder . "/";
+#     unless ( opendir( DIR, "$zebradir" ) ) {
+#         warn "$zebradir not found";
+#         return;
+#     }
+#     closedir DIR;
+#     my $filename = $zebradir . $biblionumber;
+# 
+#     if ($record) {
+#         open( OUTPUT, ">", $filename . ".xml" );
+#         print OUTPUT $record;
+#         close OUTPUT;
+#     }
+# }
+
+=head2 ModZebra
 
 =over 4
 
-create a biblioitem, the parameter is a hash
+ModZebra( $biblionumber, $op, $server, $newRecord );
 
+    $biblionumber is the biblionumber we want to index
+    $op is specialUpdate or delete, and is used to know what we want to do
+    $server is the server that we want to update
+    $newRecord is the MARC::Record containing the new record. It is usefull only when NoZebra=1, and is used to know what to add to the nozebra database. (the record in mySQL being, if it exist, the previous record, the one just before the modif. We need both : the previous and the new one.
+    
 =back
 
 =cut
 
-sub newbiblioitem {
-    my ($biblioitem) = @_;
-    my $dbh        = C4::Context->dbh;
-       # add biblio information to the hash
-    my $MARCbiblio = MARCkoha2marcBiblio( $dbh, $biblioitem );
-       $biblioitem->{marc} = $MARCbiblio->as_usmarc();
-    my $bibitemnum = &REALnewbiblioitem( $dbh, $biblioitem );
-    return ($bibitemnum);
+sub ModZebra {
+###Accepts a $server variable thus we can use it for biblios authorities or other zebra dbs
+    my ( $biblionumber, $op, $server, $newRecord ) = @_;
+    my $dbh=C4::Context->dbh;
+
+    # true ModZebra commented until indexdata fixes zebraDB crashes (it seems they occur on multiple updates
+    # at the same time
+    # replaced by a zebraqueue table, that is filled with ModZebra to run.
+    # the table is emptied by misc/cronjobs/zebraqueue_start.pl script
+
+    if (C4::Context->preference("NoZebra")) {
+        # lock the nozebra table : we will read index lines, update them in Perl process
+        # and write everything in 1 transaction.
+        # lock the table to avoid someone else overwriting what we are doing
+        $dbh->do('LOCK TABLES nozebra WRITE,biblio WRITE,biblioitems WRITE, systempreferences WRITE, auth_types WRITE, auth_header WRITE');
+        my %result; # the result hash that will be builded by deletion / add, and written on mySQL at the end, to improve speed
+        my $record;
+        if ($server eq 'biblioserver') {
+            $record= GetMarcBiblio($biblionumber);
+        } else {
+            $record= C4::AuthoritiesMarc::GetAuthority($biblionumber);
+        }
+        if ($op eq 'specialUpdate') {
+            # OK, we have to add or update the record
+            # 1st delete (virtually, in indexes) ...
+            %result = _DelBiblioNoZebra($biblionumber,$record,$server);
+            # ... add the record
+            %result=_AddBiblioNoZebra($biblionumber,$newRecord, $server, %result);
+        } else {
+            # it's a deletion, delete the record...
+            # warn "DELETE the record $biblionumber on $server".$record->as_formatted;
+            %result=_DelBiblioNoZebra($biblionumber,$record,$server);
+        }
+        # ok, now update the database...
+        my $sth = $dbh->prepare("UPDATE nozebra SET biblionumbers=? WHERE server=? AND indexname=? AND value=?");
+        foreach my $key (keys %result) {
+            foreach my $index (keys %{$result{$key}}) {
+                $sth->execute($result{$key}->{$index}, $server, $key, $index);
+            }
+        }
+        $dbh->do('UNLOCK TABLES');
+
+    } else {
+        #
+        # we use zebra, just fill zebraqueue table
+        #
+        my $sth=$dbh->prepare("insert into zebraqueue  (biblio_auth_number ,server,operation) values(?,?,?)");
+        $sth->execute($biblionumber,$server,$op);
+        $sth->finish;
+    }
 }
 
-=head2 newsubtitle($biblionumber,$subtitle);
-
-=over 4
-
-insert a subtitle for $biblionumber biblio
+=head2 GetNoZebraIndexes
 
-=back
+    %indexes = GetNoZebraIndexes;
+    
+    return the data from NoZebraIndexes syspref.
 
 =cut
 
-
-sub newsubtitle {
-    my ( $bibnum, $subtitle ) = @_;
-    my $dbh = C4::Context->dbh;
-    &REALnewsubtitle( $dbh, $bibnum, $subtitle );
+sub GetNoZebraIndexes {
+    my $index = C4::Context->preference('NoZebraIndexes');
+    my %indexes;
+    foreach my $line (split /('|"),/,$index) {
+        $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;
+        $indexes{$index}=$fields;
+    }
+    return %indexes;
 }
 
-=head2 $errors = newitems($item, @barcodes);
-
-=over 4
+=head1 INTERNAL FUNCTIONS
 
-insert items ($item is a hash)
+=head2 _DelBiblioNoZebra($biblionumber,$record,$server);
 
-=back
+    function to delete a biblio in NoZebra indexes
+    This function does NOT delete anything in database : it reads all the indexes entries
+    that have to be deleted & delete them in the hash
+    The SQL part is done either :
+    - after the Add if we are modifying a biblio (delete + add again)
+    - immediatly after this sub if we are doing a true deletion.
+    $server can be 'biblioserver' or 'authorityserver' : it indexes biblios or authorities (in the same table, $server being part of the table itself
 
 =cut
 
 
-sub newitems {
-    my ( $item, @barcodes ) = @_;
+sub _DelBiblioNoZebra {
+    my ($biblionumber, $record, $server)=@_;
+    
+    # Get the indexes
     my $dbh = C4::Context->dbh;
-    my $errors;
-    my $itemnumber;
-    my $error;
-    foreach my $barcode (@barcodes) {
-               # add items, one by one for each barcode.
-               my $oneitem=$item;
-               $oneitem->{barcode}= $barcode;
-        my $MARCitem = &MARCkoha2marcItem( $dbh, $oneitem);
-               $oneitem->{marc} = $MARCitem->as_usmarc;
-        ( $itemnumber, $error ) = &REALnewitems( $dbh, $oneitem);
-#         $errors .= $error;
-#         &MARCadditem( $dbh, $MARCitem, $item->{biblionumber} );
+    # Get the indexes
+    my %index;
+    my $title;
+    if ($server eq 'biblioserver') {
+        %index=GetNoZebraIndexes;
+        # get title of the record (to store the 10 first letters with the index)
+        my ($titletag,$titlesubfield) = GetMarcFromKohaField('biblio.title');
+        $title = lc($record->subfield($titletag,$titlesubfield));
+    } else {
+        # for authorities, the "title" is the $a mainentry
+        my $authref = C4::AuthoritiesMarc::GetAuthType($record->subfield(152,'b'));
+        warn "ERROR : authtype undefined for ".$record->as_formatted unless $authref;
+        $title = $record->subfield($authref->{auth_tag_to_report},'a');
+        $index{'mainmainentry'}= $authref->{'auth_tag_to_report'}.'a';
+        $index{'mainentry'}    = $authref->{'auth_tag_to_report'}.'*';
+        $index{'auth_type'}    = '152b';
+    }
+    
+    my %result;
+    # remove blancks comma (that could cause problem when decoding the string for CQL retrieval) and regexp specific values
+    $title =~ s/ |,|;|\[|\]|\(|\)|\*|-|'|=//g;
+    # limit to 10 char, should be enough, and limit the DB size
+    $title = substr($title,0,10);
+    #parse each field
+    my $sth2=$dbh->prepare('SELECT biblionumbers FROM nozebra WHERE server=? AND indexname=? AND value=?');
+    foreach my $field ($record->fields()) {
+        #parse each subfield
+        next if $field->tag <10;
+        foreach my $subfield ($field->subfields()) {
+            my $tag = $field->tag();
+            my $subfieldcode = $subfield->[0];
+            my $indexed=0;
+            # check each index to see if the subfield is stored somewhere
+            # otherwise, store it in __RAW__ index
+            foreach my $key (keys %index) {
+#                 warn "examining $key index : ".$index{$key}." for $tag $subfieldcode";
+                if ($index{$key} =~ /$tag\*/ or $index{$key} =~ /$tag$subfieldcode/) {
+                    $indexed=1;
+                    my $line= lc $subfield->[1];
+                    # remove meaningless value in the field...
+                    $line =~ s/-|\.|\?|,|;|!|'|\(|\)|\[|\]|{|}|"|<|>|&|\+|\*|\/|=|:/ /g;
+                    # ... and split in words
+                    foreach (split / /,$line) {
+                        next unless $_; # skip  empty values (multiple spaces)
+                        # if the entry is already here, do nothing, the biblionumber has already be removed
+                        unless ($result{$key}->{$_} =~ /$biblionumber,$title\-(\d);/) {
+                            # get the index value if it exist in the nozebra table and remove the entry, otherwise, do nothing
+                            $sth2->execute($server,$key,$_);
+                            my $existing_biblionumbers = $sth2->fetchrow;
+                            # it exists
+                            if ($existing_biblionumbers) {
+#                                 warn " existing for $key $_: $existing_biblionumbers";
+                                $result{$key}->{$_} =$existing_biblionumbers;
+                                $result{$key}->{$_} =~ s/$biblionumber,$title\-(\d);//;
+                            }
+                        }
+                    }
+                }
+            }
+            # the subfield is not indexed, store it in __RAW__ index anyway
+            unless ($indexed) {
+                my $line= lc $subfield->[1];
+                $line =~ s/-|\.|\?|,|;|!|'|\(|\)|\[|\]|{|}|"|<|>|&|\+|\*|\/|=|:/ /g;
+                # ... and split in words
+                foreach (split / /,$line) {
+                    next unless $_; # skip  empty values (multiple spaces)
+                    # if the entry is already here, do nothing, the biblionumber has already be removed
+                    unless ($result{'__RAW__'}->{$_} =~ /$biblionumber,$title\-(\d);/) {
+                        # get the index value if it exist in the nozebra table and remove the entry, otherwise, do nothing
+                        $sth2->execute($server,'__RAW__',$_);
+                        my $existing_biblionumbers = $sth2->fetchrow;
+                        # it exists
+                        if ($existing_biblionumbers) {
+                            $result{'__RAW__'}->{$_} =$existing_biblionumbers;
+                            $result{'__RAW__'}->{$_} =~ s/$biblionumber,$title\-(\d);//;
+                        }
+                    }
+                }
+            }
+        }
     }
-    return ($errors);
+    return %result;
 }
 
-=head2 moditem($item);
-
-=over 4
-
-modify an item ($item is a hash with all item informations)
+=head2 _AddBiblioNoZebra($biblionumber, $record, $server, %result);
 
-=back
+    function to add a biblio in NoZebra indexes
 
 =cut
 
-
-sub moditem {
-    my ($item) = @_;
+sub _AddBiblioNoZebra {
+    my ($biblionumber, $record, $server, %result)=@_;
     my $dbh = C4::Context->dbh;
-    &REALmoditem( $dbh, $item );
-    my $MARCitem =
-      &MARCkoha2marcItem( $dbh, $item->{'biblionumber'}, $item->{'itemnum'} );
-    my $bibid =
-      &MARCfind_MARCbibid_from_oldbiblionumber( $dbh, $item->{biblionumber} );
-    &MARCmoditem( $dbh, $MARCitem, $bibid, $item->{itemnum}, 0 );
+    # Get the indexes
+    my %index;
+    my $title;
+    if ($server eq 'biblioserver') {
+        %index=GetNoZebraIndexes;
+        # get title of the record (to store the 10 first letters with the index)
+        my ($titletag,$titlesubfield) = GetMarcFromKohaField('biblio.title');
+        $title = lc($record->subfield($titletag,$titlesubfield));
+    } else {
+        # warn "server : $server";
+        # for authorities, the "title" is the $a mainentry
+        my $authref = C4::AuthoritiesMarc::GetAuthType($record->subfield(152,'b'));
+        warn "ERROR : authtype undefined for ".$record->as_formatted unless $authref;
+        $title = $record->subfield($authref->{auth_tag_to_report},'a');
+        $index{'mainmainentry'} = $authref->{auth_tag_to_report}.'a';
+        $index{'mainentry'}     = $authref->{auth_tag_to_report}.'*';
+        $index{'auth_type'}     = '152b';
+    }
+
+    # remove blancks comma (that could cause problem when decoding the string for CQL retrieval) and regexp specific values
+    $title =~ s/ |,|;|\[|\]|\(|\)|\*|-|'|=//g;
+    # limit to 10 char, should be enough, and limit the DB size
+    $title = substr($title,0,10);
+    #parse each field
+    my $sth2=$dbh->prepare('SELECT biblionumbers FROM nozebra WHERE server=? AND indexname=? AND value=?');
+    foreach my $field ($record->fields()) {
+        #parse each subfield
+        next if $field->tag <10;
+        foreach my $subfield ($field->subfields()) {
+            my $tag = $field->tag();
+            my $subfieldcode = $subfield->[0];
+            my $indexed=0;
+            # check each index to see if the subfield is stored somewhere
+            # otherwise, store it in __RAW__ index
+            foreach my $key (keys %index) {
+#                 warn "examining $key index : ".$index{$key}." for $tag $subfieldcode";
+                if ($index{$key} =~ /$tag\*/ or $index{$key} =~ /$tag$subfieldcode/) {
+                    $indexed=1;
+                    my $line= lc $subfield->[1];
+                    # remove meaningless value in the field...
+                    $line =~ s/-|\.|\?|,|;|!|'|\(|\)|\[|\]|{|}|"|<|>|&|\+|\*|\/|=|:/ /g;
+                    # ... and split in words
+                    foreach (split / /,$line) {
+                        next unless $_; # skip  empty values (multiple spaces)
+                        # if the entry is already here, improve weight
+#                         warn "managing $_";
+                        if ($result{$key}->{"$_"} =~ /$biblionumber,$title\-(\d);/) {
+                            my $weight=$1+1;
+                            $result{$key}->{"$_"} =~ s/$biblionumber,$title\-(\d);//;
+                            $result{$key}->{"$_"} .= "$biblionumber,$title-$weight;";
+                        } else {
+                            # get the value if it exist in the nozebra table, otherwise, create it
+                            $sth2->execute($server,$key,$_);
+                            my $existing_biblionumbers = $sth2->fetchrow;
+                            # it exists
+                            if ($existing_biblionumbers) {
+                                $result{$key}->{"$_"} =$existing_biblionumbers;
+                                my $weight=$1+1;
+                                $result{$key}->{"$_"} =~ s/$biblionumber,$title\-(\d);//;
+                                $result{$key}->{"$_"} .= "$biblionumber,$title-$weight;";
+                            # create a new ligne for this entry
+                            } else {
+#                             warn "INSERT : $server / $key / $_";
+                                $dbh->do('INSERT INTO nozebra SET server='.$dbh->quote($server).', indexname='.$dbh->quote($key).',value='.$dbh->quote($_));
+                                $result{$key}->{"$_"}.="$biblionumber,$title-1;";
+                            }
+                        }
+                    }
+                }
+            }
+            # the subfield is not indexed, store it in __RAW__ index anyway
+            unless ($indexed) {
+                my $line= lc $subfield->[1];
+                $line =~ s/-|\.|\?|,|;|!|'|\(|\)|\[|\]|{|}|"|<|>|&|\+|\*|\/|=|:/ /g;
+                # ... and split in words
+                foreach (split / /,$line) {
+                    next unless $_; # skip  empty values (multiple spaces)
+                    # if the entry is already here, improve weight
+                    if ($result{'__RAW__'}->{"$_"} =~ /$biblionumber,$title\-(\d);/) {
+                        my $weight=$1+1;
+                        $result{'__RAW__'}->{"$_"} =~ s/$biblionumber,$title\-(\d);//;
+                        $result{'__RAW__'}->{"$_"} .= "$biblionumber,$title-$weight;";
+                    } else {
+                        # get the value if it exist in the nozebra table, otherwise, create it
+                        $sth2->execute($server,'__RAW__',$_);
+                        my $existing_biblionumbers = $sth2->fetchrow;
+                        # it exists
+                        if ($existing_biblionumbers) {
+                            $result{'__RAW__'}->{"$_"} =$existing_biblionumbers;
+                            my $weight=$1+1;
+                            $result{'__RAW__'}->{"$_"} =~ s/$biblionumber,$title\-(\d);//;
+                            $result{'__RAW__'}->{"$_"} .= "$biblionumber,$title-$weight;";
+                        # create a new ligne for this entry
+                        } else {
+                            $dbh->do('INSERT INTO nozebra SET server='.$dbh->quote($server).',  indexname="__RAW__",value='.$dbh->quote($_));
+                            $result{'__RAW__'}->{"$_"}.="$biblionumber,$title-1;";
+                        }
+                    }
+                }
+            }
+        }
+    }
+    return %result;
 }
 
-=head2 $error = checkitems($count,@barcodes);
+
+=head2 MARCitemchange
 
 =over 4
 
-check for each @barcode entry that the barcode is not a duplicate
+&MARCitemchange( $record, $itemfield, $newvalue )
+
+Function to update a single value in an item field.
+Used twice, could probably be replaced by something else, but works well...
+
+=back
 
 =back
 
 =cut
 
-sub checkitems {
-    my ( $count, @barcodes ) = @_;
+sub MARCitemchange {
+    my ( $record, $itemfield, $newvalue ) = @_;
     my $dbh = C4::Context->dbh;
-    my $error;
-    my $sth = $dbh->prepare("Select * from items where barcode=?");
-    for ( my $i = 0 ; $i < $count ; $i++ ) {
-        $barcodes[$i] = uc $barcodes[$i];
-        $sth->execute( $barcodes[$i] );
-        if ( my $data = $sth->fetchrow_hashref ) {
-            $error .= " Duplicate Barcode: $barcodes[$i]";
+    
+    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);
         }
     }
-    $sth->finish;
-    return ($error);
 }
 
-=head2 $delitem($itemnum);
+=head2 _koha_add_biblio
 
 =over 4
 
-delete item $itemnum being the item number to delete
+_koha_add_biblio($dbh,$biblioitem);
+
+Internal function to add a biblio ($biblio is a hash with the values)
 
 =back
 
 =cut
 
-sub delitem {
-    my ($itemnum) = @_;
-    my $dbh = C4::Context->dbh;
-    &REALdelitem( $dbh, $itemnum );
+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;
+
+    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
+    );
+
+    $sth->finish;
+    return ($biblionumber);
 }
 
-=head2 deletebiblioitem($biblioitemnumber);
+=head2 _find_value
 
 =over 4
 
-delete the biblioitem $biblioitemnumber
+($indicators, $value) = _find_value($tag, $subfield, $record,$encoding);
+
+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.
+
+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 deletebiblioitem {
-    my ($biblioitemnumber) = @_;
-    my $dbh = C4::Context->dbh;
-    &REALdelbiblioitem( $dbh, $biblioitemnumber );
-}    # sub deletebiblioitem
+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 delbiblio($biblionumber)
+=head2 _koha_modify_biblio
 
 =over 4
 
-delete biblio $biblionumber
+$biblionumber = _koha_modify_biblio($dbh,$biblio);
+Internal function for updating the biblio table
 
 =back
 
 =cut
 
-sub delbiblio {
-    my ($biblio) = @_;
-    my $dbh = C4::Context->dbh;
-    &REALdelbiblio( $dbh, $biblio );
-    my $bibid = &MARCfind_MARCbibid_from_oldbiblionumber( $dbh, $biblio );
-    &MARCdelbiblio( $dbh, $bibid, 0 );
+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{
+        UPDATE biblio
+        SET    title = ?,
+               author = ?,
+               abstract = ?,
+               copyrightdate = ?,
+               seriestitle = ?,
+               serial = ?,
+               unititle = ?,
+               notes = ?
+        WHERE  biblionumber = ?
+    };
+    my $sth = $dbh->prepare($query);
+    
+    $sth->execute(
+        $biblio->{'title'},
+        $biblio->{'author'},
+        $biblio->{'abstract'},
+        $biblio->{'copyrightdate'},
+        $biblio->{'seriestitle'},
+        $biblio->{'serial'},
+        $biblio->{'unititle'},
+        $biblio->{'notes'},
+        $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'} );
 }
 
-=head2 ($count,@results) = getbiblio($biblionumber);
+=head2 _koha_modify_biblioitem
 
 =over 4
 
-return an array with hash of biblios.
-
-FIXME : biblionumber being the primary key, this sub will always return only 1 result, API should be modified...
+_koha_modify_biblioitem( $dbh, $biblioitem );
 
 =back
 
 =cut
 
-sub getbiblio {
-    my ($biblionumber) = @_;
-    my $dbh = C4::Context->dbh;
-    my $sth = $dbh->prepare("Select * from biblio where biblionumber = ?");
-
-    # || die "Cannot prepare $query\n" . $dbh->errstr;
-    my $count = 0;
-    my @results;
-
-    $sth->execute($biblionumber);
-
-    # || die "Cannot execute $query\n" . $sth->errstr;
-    while ( my $data = $sth->fetchrow_hashref ) {
-        $results[$count] = $data;
-        $count++;
-    }    # while
-
-    $sth->finish;
-    return ( $count, @results );
-}    # sub getbiblio
-
-=item bibdata
-
-  $data = &bibdata($biblionumber, $type);
-
-Returns information about the book with the given biblionumber.
-
-C<$type> is ignored.
-
-C<&bibdata> returns a reference-to-hash. The keys are the fields in
-the C<biblio>, C<biblioitems>, and C<bibliosubtitle> tables in the
-Koha database.
-
-In addition, C<$data-E<gt>{subject}> is the list of the book's
-subjects, separated by C<" , "> (space, comma, space).
-
-If there are multiple biblioitems with the given biblionumber, only
-the first one is considered.
+sub _koha_modify_biblioitem {
+    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);
+    if ( $dbh->errstr ) {
+        warn "ERROR in _koha_modify_biblioitem $query";
+    }
+}
 
-=cut
-#'
-sub bibdata {
-       my ($bibnum, $type) = @_;
-       my $dbh   = C4::Context->dbh;
-       my $sth   = $dbh->prepare("Select *, biblioitems.notes AS bnotes, biblio.notes
-                                                               from biblio 
-                                                               left join biblioitems on biblioitems.biblionumber = biblio.biblionumber
-                                                               left join bibliosubtitle on
-                                                               biblio.biblionumber = bibliosubtitle.biblionumber
-                                                               left join itemtypes on biblioitems.itemtype=itemtypes.itemtype
-                                                               where biblio.biblionumber = ?
-                                                               ");
-       $sth->execute($bibnum);
-       my $data;
-       $data  = $sth->fetchrow_hashref;
-       $sth->finish;
-       # handle management of repeated subtitle
-       $sth   = $dbh->prepare("Select * from bibliosubtitle where biblionumber = ?");
-       $sth->execute($bibnum);
-       my @subtitles;
-       while (my $dat = $sth->fetchrow_hashref){
-               my %line;
-               $line{subtitle} = $dat->{subtitle};
-               push @subtitles, \%line;
-       } # while
-       $data->{subtitles} = \@subtitles;
-       $sth->finish;
-       $sth   = $dbh->prepare("Select * from bibliosubject where biblionumber = ?");
-       $sth->execute($bibnum);
-       my @subjects;
-       while (my $dat = $sth->fetchrow_hashref){
-               my %line;
-               $line{subject} = $dat->{'subject'};
-               push @subjects, \%line;
-       } # while
-       $data->{subjects} = \@subjects;
-       $sth->finish;
-       $sth   = $dbh->prepare("Select * from additionalauthors where biblionumber = ?");
-       $sth->execute($bibnum);
-       while (my $dat = $sth->fetchrow_hashref){
-               $data->{'additionalauthors'} .= "$dat->{'author'} - ";
-       } # while
-       chop $data->{'additionalauthors'};
-       chop $data->{'additionalauthors'};
-       chop $data->{'additionalauthors'};
-       $sth->finish;
-       return($data);
-} # sub bibdata
-
-=head2 ($count,@results) = getbiblioitem($biblioitemnumber);
+=head2 _koha_add_biblioitem
 
 =over 4
 
-return an array with hash of biblioitemss.
+_koha_add_biblioitem( $dbh, $biblioitem );
 
-FIXME : biblioitemnumber being unique, this sub will always return only 1 result, API should be modified...
+Internal function to add a biblioitem
 
 =back
 
 =cut
 
-sub getbiblioitem {
-    my ($biblioitemnum) = @_;
-    my $dbh = C4::Context->dbh;
-    my $sth = $dbh->prepare( "Select * from biblioitems where
-biblioitemnumber = ?"
-    );
-    my $count = 0;
-    my @results;
+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($biblioitemnum);
+    $sth->execute;
+    $data       = $sth->fetchrow_arrayref;
+    $bibitemnum = $$data[0] + 1;
 
-    while ( my $data = $sth->fetchrow_hashref ) {
-        $results[$count] = $data;
-        $count++;
-    }    # while
+    $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'};
+    $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 ( $count, @results );
-}    # sub getbiblioitem
+    return ($bibitemnum);
+}
 
-=head2 ($count,@results) = getbiblioitembybiblionumber($biblionumber);
+=head2 _koha_new_items
 
 =over 4
 
-return an array with hash of biblioitems for the given biblionumber.
+_koha_new_items( $dbh, $item, $barcode );
 
 =back
 
 =cut
 
-sub getbiblioitembybiblionumber {
-    my ($biblionumber) = @_;
-    my $dbh = C4::Context->dbh;
-    my $sth = $dbh->prepare("Select * from biblioitems where biblionumber = ?");
-    my $count = 0;
-    my @results;
-
-    $sth->execute($biblionumber);
+sub _koha_new_items {
+    my ( $dbh, $item, $barcode ) = @_;
 
-    while ( my $data = $sth->fetchrow_hashref ) {
-        $results[$count] = $data;
-        $count++;
-    }    # while
+    #  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;
-    return ( $count, @results );
-}    # sub
+## 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     = ?,
+            biblioitemnumber     = ?,     barcode          = ?,
+            booksellerid         = ?,     dateaccessioned  = NOW(),
+            homebranch           = ?,     holdingbranch    = ?,
+            price                = ?,     replacementprice = ?,
+            replacementpricedate = NOW(), datelastseen     = NOW(),
+                       stack            = ?,
+            itemlost             = ?,     wthdrawn         = ?,
+            paidfor              = ?,     itemnotes        = ?,
+            itemcallnumber       =?,      notforloan       = ?,
+            location             = ?,     Cutterextra      = ?
+          "
+        );
+        $sth->execute(
+            $itemnumber,                $item->{'biblionumber'},
+                       $item->{'biblioitemnumber'},
+            $barcode,                   $item->{'booksellerid'},
+            $item->{'homebranch'},      $item->{'holdingbranch'},
+            $item->{'price'},           $item->{'replacementprice'},
+                       $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     = ?,
+            biblioitemnumber     = ?,     barcode          = ?,
+            booksellerid         = ?,     dateaccessioned  = ?,
+            homebranch           = ?,     holdingbranch    = ?,
+            price                = ?,     replacementprice = ?,
+            replacementpricedate = NOW(), datelastseen     = NOW(),
+                       stack            = ?,
+            itemlost             = ?,     wthdrawn         = ?,
+            paidfor              = ?,     itemnotes        = ?,
+            itemcallnumber       = ?,     notforloan       = ?,
+            location             = ?,
+            Cutterextra          = ?
+                            "
+        );
+        $sth->execute(
+            $itemnumber,                 $item->{'biblionumber'},
+                       $item->{'biblioitemnumber'},
+            $barcode,                    $item->{'booksellerid'},
+            $item->{'dateaccessioned'},  $item->{'homebranch'},
+            $item->{'holdingbranch'},    $item->{'price'},
+            $item->{'replacementprice'},
+            $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 ($count,@results) = getitemsbybiblioitem($biblionumber);
+=head2 _koha_modify_item
 
 =over 4
 
-returns an array with hash of items
+_koha_modify_item( $dbh, $item, $op );
 
 =back
 
 =cut
 
-sub getitemsbybiblioitem {
-    my ($biblioitemnum) = @_;
-    my $dbh = C4::Context->dbh;
-    my $sth = $dbh->prepare( "Select * from items, biblio where
-biblio.biblionumber = items.biblionumber and biblioitemnumber
-= ?"
-    );
-
-    # || die "Cannot prepare $query\n" . $dbh->errstr;
-    my $count = 0;
-    my @results;
+sub _koha_modify_item {
+    my ( $dbh, $item, $op ) = @_;
+    $item->{'itemnum'} = $item->{'itemnumber'} unless $item->{'itemnum'};
 
-    $sth->execute($biblioitemnum);
+    # 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=? WHERE itemnumber=?";
+        my @bind = (
+            $item->{'itemlost'}, $item->{'wthdrawn'},
+                       $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'} );
 
-    # || die "Cannot execute $query\n" . $sth->errstr;
-    while ( my $data = $sth->fetchrow_hashref ) {
-        $results[$count] = $data;
-        $count++;
-    }    # while
+    my $query = "UPDATE items SET
+barcode=?,itemnotes=?,itemcallnumber=?,notforloan=?,location=?,stack=?,wthdrawn=?,holdingbranch=?,homebranch=?,cutterextra=?, onloan=?";
 
+    my @bind = (
+        $item->{'barcode'},        $item->{'notes'},
+        $item->{'itemcallnumber'}, $item->{'notforloan'},
+        $item->{'location'},       $item->{stack},
+        $item->{wthdrawn},         $item->{holdingbranch},
+        $item->{homebranch},       $cutterextra,
+        $item->{onloan},           
+    );
+    if ( $item->{'lost'} ne '' ) {
+        $query =
+"update items set biblioitemnumber=?,barcode=?,itemnotes=?,homebranch=?,
+                            itemlost=?,wthdrawn=?,itemcallnumber=?,notforloan=?,
+                             location=?,stack=?,wthdrawn=?,holdingbranch=?,cutterextra=?,onloan=?";
+        @bind = (
+            $item->{'bibitemnum'},     $item->{'barcode'},
+            $item->{'notes'},          $item->{'homebranch'},
+            $item->{'lost'},           $item->{'wthdrawn'},
+            $item->{'itemcallnumber'}, $item->{'notforloan'},
+            $item->{'location'},       $item->{stack},
+            $item->{wthdrawn},         $item->{holdingbranch},
+            $cutterextra,              $item->{onloan}
+        );
+        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 $sth = $dbh->prepare($query);
+    $sth->execute(@bind);
     $sth->finish;
-    return ( $count, @results );
-}    # sub getitemsbybiblioitem
+}
 
-=item ItemInfo
+=head2 _koha_delete_biblio
 
-  @results = &ItemInfo($env, $biblionumber, $type);
+=over 4
 
-Returns information about books with the given biblionumber.
+$error = _koha_delete_biblio($dbh,$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.
+Internal sub for deleting from biblio table -- also saves to deletedbiblio
 
-C<$env> is ignored.
+C<$dbh> - the database handle
+C<$biblionumber> - the biblionumber of the biblio to be deleted
 
-C<&ItemInfo> 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:
+=back
 
-=over 4
+=cut
 
-=item C<$data-E<gt>{branchname}>
+# FIXME: add error handling
 
-The name (not the code) of the branch to which the book belongs.
+sub _koha_delete_biblio {
+    my ( $dbh, $biblionumber ) = @_;
 
-=item C<$data-E<gt>{datelastseen}>
+    # get all the data for this biblio
+    my $sth = $dbh->prepare("SELECT * FROM biblio WHERE biblionumber=?");
+    $sth->execute($biblionumber);
 
-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<//>.
+    if ( my $data = $sth->fetchrow_hashref ) {
 
-=item C<$data-E<gt>{datedue}>
+        # save the record in deletedbiblio
+        # find the fields to save
+        my $query = "INSERT INTO deletedbiblio SET ";
+        my @bind  = ();
+        foreach my $temp ( keys %$data ) {
+            $query .= "$temp = ?,";
+            push( @bind, $data->{$temp} );
+        }
 
-=item C<$data-E<gt>{class}>
+        # replace the last , by ",?)"
+        $query =~ s/\,$//;
+        my $bkup_sth = $dbh->prepare($query);
+        $bkup_sth->execute(@bind);
+        $bkup_sth->finish;
+
+        # delete the biblio
+        my $del_sth = $dbh->prepare("DELETE FROM biblio WHERE biblionumber=?");
+        $del_sth->execute($biblionumber);
+        $del_sth->finish;
+    }
+    $sth->finish;
+    return undef;
+}
 
-This is the concatenation of C<biblioitems.classification>, the book's
-Dewey code, and C<biblioitems.subclass>.
+=head2 _koha_delete_biblioitems
 
-=item C<$data-E<gt>{ocount}>
+=over 4
 
-I think this is the number of copies of the book available.
+$error = _koha_delete_biblioitems($dbh,$biblioitemnumber);
 
-=item C<$data-E<gt>{order}>
+Internal sub for deleting from biblioitems table -- also saves to deletedbiblioitems
 
-If this is set, it is set to C<One Order>.
+C<$dbh> - the database handle
+C<$biblionumber> - the biblioitemnumber of the biblioitem to be deleted
 
 =back
 
 =cut
-#'
-sub ItemInfo {
-       my ($env,$biblionumber,$type) = @_;
-       my $dbh   = C4::Context->dbh;
-       my $query = "SELECT *,items.notforloan as itemnotforloan FROM items, biblio, biblioitems 
-                                       left join itemtypes on biblioitems.itemtype = itemtypes.itemtype
-                                       WHERE items.biblionumber = ?
-                                       AND biblioitems.biblioitemnumber = items.biblioitemnumber
-                                       AND biblio.biblionumber = items.biblionumber";
-       $query .= " order by items.dateaccessioned desc";
-       my $sth=$dbh->prepare($query);
-       $sth->execute($biblionumber);
-       my $i=0;
-       my @results;
-       while (my $data=$sth->fetchrow_hashref){
-               my $datedue = '';
-               my $isth=$dbh->prepare("Select issues.*,borrowers.cardnumber from issues,borrowers where itemnumber = ? and returndate is null and issues.borrowernumber=borrowers.borrowernumber");
-               $isth->execute($data->{'itemnumber'});
-               if (my $idata=$isth->fetchrow_hashref){
-               $data->{borrowernumber} = $idata->{borrowernumber};
-               $data->{cardnumber} = $idata->{cardnumber};
-               $datedue = format_date($idata->{'date_due'});
-               }
-               if ($datedue eq ''){
-                       my ($restype,$reserves)=C4::Reserves2::CheckReserves($data->{'itemnumber'});
-                       if ($restype) {
-                               $datedue=$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;
-       # 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;
-               }
-               $results[$i]=$data;
-               $i++;
-       }
-       $sth->finish;
-       return(@results);
-}
 
-=item bibitems
+# FIXME: add error handling
 
-  ($count, @results) = &bibitems($biblionumber);
+sub _koha_delete_biblioitems {
+    my ( $dbh, $biblioitemnumber ) = @_;
 
-Given the biblionumber for a book, C<&bibitems> looks up that book's
-biblioitems (different publications of the same book, the audio book
-and film versions, etc.).
+    # get all the data for this biblioitem
+    my $sth =
+      $dbh->prepare("SELECT * FROM biblioitems WHERE biblioitemnumber=?");
+    $sth->execute($biblioitemnumber);
 
-C<$count> is the number of elements in C<@results>.
+    if ( my $data = $sth->fetchrow_hashref ) {
 
-C<@results> is an array of references-to-hash; the keys are the fields
-of the C<biblioitems> and C<itemtypes> tables of the Koha database. In
-addition, C<itemlost> indicates the availability of the item: if it is
-"2", then all copies of the item are long overdue; if it is "1", then
-all copies are lost; otherwise, there is at least one copy available.
+        # save the record in deletedbiblioitems
+        # find the fields to save
+        my $query = "INSERT INTO deletedbiblioitems SET ";
+        my @bind  = ();
+        foreach my $temp ( keys %$data ) {
+            $query .= "$temp = ?,";
+            push( @bind, $data->{$temp} );
+        }
 
-=cut
-#'
-sub bibitems {
-    my ($bibnum) = @_;
-    my $dbh   = C4::Context->dbh;
-    my $sth   = $dbh->prepare("SELECT biblioitems.*,
-                        itemtypes.*,
-                        MIN(items.itemlost)        as itemlost,
-                        MIN(items.dateaccessioned) as dateaccessioned
-                          FROM biblioitems, itemtypes, items
-                         WHERE biblioitems.biblionumber     = ?
-                           AND biblioitems.itemtype         = itemtypes.itemtype
-                           AND biblioitems.biblioitemnumber = items.biblioitemnumber
-                      GROUP BY items.biblioitemnumber");
-    my $count = 0;
-    my @results;
-    $sth->execute($bibnum);
-    while (my $data = $sth->fetchrow_hashref) {
-        $results[$count] = $data;
-        $count++;
-    } # while
+        # replace the last , by ",?)"
+        $query =~ s/\,$//;
+        my $bkup_sth = $dbh->prepare($query);
+        $bkup_sth->execute(@bind);
+        $bkup_sth->finish;
+
+        # delete the biblioitem
+        my $del_sth =
+          $dbh->prepare("DELETE FROM biblioitems WHERE biblioitemnumber=?");
+        $del_sth->execute($biblioitemnumber);
+        $del_sth->finish;
+    }
     $sth->finish;
-    return($count, @results);
-} # sub bibitems
+    return undef;
+}
 
+=head2 _koha_delete_item
 
-=item bibitemdata
+=over 4
 
-  $itemdata = &bibitemdata($biblioitemnumber);
+_koha_delete_item( $dbh, $itemnum );
 
-Looks up the biblioitem with the given biblioitemnumber. Returns a
-reference-to-hash. The keys are the fields from the C<biblio>,
-C<biblioitems>, and C<itemtypes> tables in the Koha database, except
-that C<biblioitems.notes> is given as C<$itemdata-E<gt>{bnotes}>.
+Internal function to delete an item record from the koha tables
 
-=cut
-#'
-sub bibitemdata {
-    my ($bibitem) = @_;
-    my $dbh   = C4::Context->dbh;
-    my $sth   = $dbh->prepare("Select *,biblioitems.notes as bnotes from biblio, biblioitems,itemtypes where biblio.biblionumber = biblioitems.biblionumber and biblioitemnumber = ? and biblioitems.itemtype = itemtypes.itemtype");
-    my $data;
+=back
 
-    $sth->execute($bibitem);
+=cut
 
-    $data = $sth->fetchrow_hashref;
+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;
-    return($data);
-} # sub bibitemdata
+    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;
+}
 
-=item getbibliofromitemnumber
+=head1 UNEXPORTED FUNCTIONS
 
-  $item = &getbibliofromitemnumber($env, $dbh, $itemnumber);
+=over 4
 
-Looks up the item with the given itemnumber.
+=head2 calculatelc
 
-C<$env> and C<$dbh> are ignored.
+$lc = calculatelc($classification);
 
-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
-database.
+=back
 
 =cut
-#'
-sub getbibliofromitemnumber {
-  my ($env,$dbh,$itemnumber) = @_;
-  $dbh = C4::Context->dbh;
-  my $sth=$dbh->prepare("Select * from biblio,items,biblioitems
-    where items.itemnumber = ?
-    and biblio.biblionumber = items.biblionumber
-    and biblioitems.biblioitemnumber = items.biblioitemnumber");
-#  print $query;
-  $sth->execute($itemnumber);
-  my $data=$sth->fetchrow_hashref;
-  $sth->finish;
-  return($data);
-}
 
-=item barcodes
+sub calculatelc {
+    my ($classification) = @_;
+    $classification =~ s/^\s+|\s+$//g;
+    my $i = 0;
+    my $lc2;
+    my $lc1;
 
-  @barcodes = &barcodes($biblioitemnumber);
+    for ( $i = 0 ; $i < length($classification) ; $i++ ) {
+        my $c = ( substr( $classification, $i, 1 ) );
+        if ( $c ge '0' && $c le '9' ) {
 
-Given a biblioitemnumber, looks up the corresponding items.
+            $lc2 = substr( $classification, $i );
+            last;
+        }
+        else {
+            $lc1 .= substr( $classification, $i, 1 );
 
-Returns an array of references-to-hash; the keys are C<barcode> and
-C<itemlost>.
+        }
+    }    #while
 
-The returned items include very overdue items, but not lost ones.
+    my $other = length($lc1);
+    if ( !$lc1 ) {
+        $other = 0;
+    }
 
-=cut
-#'
-sub barcodes{
-    #called from request.pl
-    my ($biblioitemnumber)=@_;
-    my $dbh = C4::Context->dbh;
-    my $sth=$dbh->prepare("SELECT barcode, itemlost, holdingbranch FROM items
-                           WHERE biblioitemnumber = ?
-                             AND (wthdrawn <> 1 OR wthdrawn IS NULL)");
-    $sth->execute($biblioitemnumber);
-    my @barcodes;
-    my $i=0;
-    while (my $data=$sth->fetchrow_hashref){
-       $barcodes[$i]=$data;
-       $i++;
+    my $extras;
+    if ( $other < 4 ) {
+        for ( 1 .. ( 4 - $other ) ) {
+            $extras .= "0";
+        }
     }
-    $sth->finish;
-    return(@barcodes);
+    $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
 
-=item itemdata
+=over 4
 
-  $item = &itemdata($barcode);
+$cutterextra = itemcalculator( $dbh, $biblioitem, $callnumber );
 
-Looks up the item with the given barcode, and returns a
-reference-to-hash containing information about that item. The keys of
-the hash are the fields from the C<items> and C<biblioitems> tables in
-the Koha database.
+=back
 
 =cut
-#'
-sub get_item_from_barcode {
-  my ($barcode)=@_;
-  my $dbh = C4::Context->dbh;
-  my $sth=$dbh->prepare("Select * from items,biblioitems where barcode=?
-  and items.biblioitemnumber=biblioitems.biblioitemnumber");
-  $sth->execute($barcode);
-  my $data=$sth->fetchrow_hashref;
-  $sth->finish;
-  return($data);
-}
-
-
-=item itemissues
-
-  @issues = &itemissues($biblioitemnumber, $biblio);
 
-Looks up information about who has borrowed the bookZ<>(s) with the
-given biblioitemnumber.
-
-C<$biblio> is ignored.
-
-C<&itemissues> returns an array of references-to-hash. The keys
-include the fields from the C<items> table in the Koha database.
-Additional keys include:
+sub itemcalculator {
+    my ( $dbh, $biblioitem, $callnumber ) = @_;
+    my $sth =
+      $dbh->prepare(
+"select classification, subclass from biblioitems where biblioitemnumber=?"
+      );
 
-=over 4
+    $sth->execute($biblioitem);
+    my ( $classification, $subclass ) = $sth->fetchrow;
+    my $all         = $classification . " " . $subclass;
+    my $total       = length($all);
+    my $cutterextra = substr( $callnumber, $total - 1 );
 
-=item C<date_due>
+    return $cutterextra;
+}
 
-If the item is currently on loan, this gives the due date.
+=head2 ModBiblioMarc
 
-If the item is not on loan, then this is either "Available" or
-"Cancelled", if the item has been withdrawn.
+    &ModBiblioMarc($newrec,$biblionumber,$frameworkcode);
+    
+    Add MARC data for a biblio to koha 
+    
+    Function exported, but should NOT be used, unless you really know what you're doing
 
-=item C<card>
+=cut
 
-If the item is currently on loan, this gives the card number of the
-patron who currently has the item.
+sub ModBiblioMarc {
+    
+# pass the MARC::Record to this function, and it will create the records in the marc field
+    my ( $record, $biblionumber, $frameworkcode ) = @_;
+    my $dbh = C4::Context->dbh;
+    my @fields = $record->fields();
+    if ( !$frameworkcode ) {
+        $frameworkcode = "";
+    }
+    my $sth =
+      $dbh->prepare("UPDATE biblio SET frameworkcode=? WHERE biblionumber=?");
+    $sth->execute( $frameworkcode, $biblionumber );
+    $sth->finish;
+    my $encoding = C4::Context->preference("marcflavour");
 
-=item C<timestamp0>, C<timestamp1>, C<timestamp2>
+    # deal with UNIMARC field 100 (encoding) : create it if needed & set encoding to unicode
+    if ( $encoding eq "UNIMARC" ) {
+        my $string;
+        if ( length($record->subfield( 100, "a" )) == 35 ) {
+            $string = $record->subfield( 100, "a" );
+            my $f100 = $record->field(100);
+            $record->delete_field($f100);
+        }
+        else {
+            $string = POSIX::strftime( "%Y%m%d", localtime );
+            $string =~ s/\-//g;
+            $string = sprintf( "%-*s", 35, $string );
+        }
+        substr( $string, 22, 6, "frey50" );
+        unless ( $record->subfield( 100, "a" ) ) {
+            $record->insert_grouped_field(
+                MARC::Field->new( 100, "", "", "a" => $string ) );
+        }
+    }
+    ModZebra($biblionumber,"specialUpdate","biblioserver",$record);
+    $sth =
+      $dbh->prepare(
+        "update biblioitems set marc=?,marcxml=?  where biblionumber=?");
+    $sth->execute( $record->as_usmarc(), $record->as_xml_record($encoding),
+        $biblionumber );
+    $sth->finish;
+    return $biblionumber;
+}
 
-These give the timestamp for the last three times the item was
-borrowed.
+=head2 AddItemInMarc
 
-=item C<card0>, C<card1>, C<card2>
+=over 4
 
-The card number of the last three patrons who borrowed this item.
+$newbiblionumber = AddItemInMarc( $record, $biblionumber, $frameworkcode );
 
-=item C<borrower0>, C<borrower1>, C<borrower2>
+Add an item in a MARC record and save the MARC record
 
-The borrower number of the last three patrons who borrowed this item.
+Function exported, but should NOT be used, unless you really know what you're doing
 
 =back
 
 =cut
-#'
-sub itemissues {
-    my ($bibitem, $biblio)=@_;
-    my $dbh   = C4::Context->dbh;
-    # FIXME - If this function die()s, the script will abort, and the
-    # user won't get anything; depending on how far the script has
-    # gotten, the user might get a blank page. It would be much better
-    # to at least print an error message. The easiest way to do this
-    # is to set $SIG{__DIE__}.
-    my $sth   = $dbh->prepare("Select * from items where
-items.biblioitemnumber = ?")
-      || die $dbh->errstr;
-    my $i     = 0;
-    my @results;
 
-    $sth->execute($bibitem)
-      || die $sth->errstr;
-
-    while (my $data = $sth->fetchrow_hashref) {
-        # Find out who currently has this item.
-        # FIXME - Wouldn't it be better to do this as a left join of
-        # some sort? Currently, this code assumes that if
-        # fetchrow_hashref() fails, then the book is on the shelf.
-        # fetchrow_hashref() can fail for any number of reasons (e.g.,
-        # database server crash), not just because no items match the
-        # search criteria.
-        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) {
-            $data->{'date_due'} = $data2->{'date_due'};
-            $data->{'card'}     = $data2->{'cardnumber'};
-           $data->{'borrower'}     = $data2->{'borrowernumber'};
-        } else {
-            if ($data->{'wthdrawn'} eq '1') {
-                $data->{'date_due'} = 'Cancelled';
-            } else {
-                $data->{'date_due'} = 'Available';
-            } # else
-        } # else
-
-        $sth2->finish;
+sub AddItemInMarc {
 
-        # Find the last 3 people who borrowed this item.
-        $sth2 = $dbh->prepare("select * from issues, borrowers
-                                               where itemnumber = ?
-                                                                       and issues.borrowernumber = borrowers.borrowernumber
-                                                                       and returndate is not NULL
-                                                                       order by returndate desc,timestamp desc") || die $dbh->errstr;
-        $sth2->execute($data->{'itemnumber'}) || die $sth2->errstr;
-        for (my $i2 = 0; $i2 < 2; $i2++) { # FIXME : error if there is less than 3 pple borrowing this item
-            if (my $data2 = $sth2->fetchrow_hashref) {
-                $data->{"timestamp$i2"} = $data2->{'timestamp'};
-                $data->{"card$i2"}      = $data2->{'cardnumber'};
-                $data->{"borrower$i2"}  = $data2->{'borrowernumber'};
-            } # if
-        } # for
+    # 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);
 
-        $sth2->finish;
-        $results[$i] = $data;
-        $i++;
+    # create it
+    my @fields = $record->fields();
+    foreach my $field (@fields) {
+        $newrec->append_fields($field);
     }
 
-    $sth->finish;
-    return(@results);
+    # FIXME: should we be making sure the biblionumbers are the same?
+    my $newbiblionumber =
+      &ModBiblioMarc( $newrec, $biblionumber, $frameworkcode );
+    return $newbiblionumber;
 }
 
-=item getsubject
-
-  ($count, $subjects) = &getsubject($biblionumber);
-
-Looks up the subjects of the book with the given biblionumber. Returns
-a two-element list. C<$subjects> is a reference-to-array, where each
-element is a subject of the book, and C<$count> is the number of
-elements in C<$subjects>.
-
-=cut
-#'
-sub getsubject {
-  my ($bibnum)=@_;
-  my $dbh = C4::Context->dbh;
-  my $sth=$dbh->prepare("Select * from bibliosubject where biblionumber=?");
-  $sth->execute($bibnum);
-  my @results;
-  my $i=0;
-  while (my $data=$sth->fetchrow_hashref){
-    $results[$i]=$data;
-    $i++;
-  }
-  $sth->finish;
-  return($i,\@results);
-}
+=head2 z3950_extended_services
 
-=item getaddauthor
+z3950_extended_services($serviceType,$serviceOptions,$record);
 
-  ($count, $authors) = &getaddauthor($biblionumber);
+    z3950_extended_services is used to handle all interactions with Zebra's extended serices package, which is employed to perform all management of the MARC data stored in Zebra.
 
-Looks up the additional authors for the book with the given
-biblionumber.
+C<$serviceType> one of: itemorder,create,drop,commit,update,xmlupdate
 
-Returns a two-element list. C<$authors> is a reference-to-array, where
-each element is an additional author, and C<$count> is the number of
-elements in C<$authors>.
+C<$serviceOptions> a has of key/value pairs. For instance, if service_type is 'update', $service_options should contain:
 
-=cut
-#'
-sub getaddauthor {
-  my ($bibnum)=@_;
-  my $dbh = C4::Context->dbh;
-  my $sth=$dbh->prepare("Select * from additionalauthors where biblionumber=?");
-  $sth->execute($bibnum);
-  my @results;
-  my $i=0;
-  while (my $data=$sth->fetchrow_hashref){
-    $results[$i]=$data;
-    $i++;
-  }
-  $sth->finish;
-  return($i,\@results);
-}
+    action => update action, one of specialUpdate, recordInsert, recordReplace, recordDelete, elementUpdate.
 
+and maybe
 
-=item getsubtitle
+    recordidOpaque => Opaque Record ID (user supplied) or recordidNumber => Record ID number (system number).
+    syntax => the record syntax (transfer syntax)
+    databaseName = Database from connection object
 
-  ($count, $subtitles) = &getsubtitle($biblionumber);
+    To set serviceOptions, call set_service_options($serviceType)
 
-Looks up the subtitles for the book with the given biblionumber.
+C<$record> the record, if one is needed for the service type
 
-Returns a two-element list. C<$subtitles> is a reference-to-array,
-where each element is a subtitle, and C<$count> is the number of
-elements in C<$subtitles>.
+    A record should be in XML. You can convert it to XML from MARC by running it through marc2xml().
 
 =cut
-#'
-sub getsubtitle {
-  my ($bibnum)=@_;
-  my $dbh = C4::Context->dbh;
-  my $sth=$dbh->prepare("Select * from bibliosubtitle where biblionumber=?");
-  $sth->execute($bibnum);
-  my @results;
-  my $i=0;
-  while (my $data=$sth->fetchrow_hashref){
-    $results[$i]=$data;
-    $i++;
-  }
-  $sth->finish;
-  return($i,\@results);
-}
 
+sub z3950_extended_services {
+    my ( $server, $serviceType, $action, $serviceOptions ) = @_;
 
-=item getwebsites
+    # get our connection object
+    my $Zconn = C4::Context->Zconn( $server, 0, 1 );
 
-  ($count, @websites) = &getwebsites($biblionumber);
+    # create a new package object
+    my $Zpackage = $Zconn->package();
 
-Looks up the web sites pertaining to the book with the given
-biblionumber.
+    # set our options
+    $Zpackage->option( action => $action );
 
-C<$count> is the number of elements in C<@websites>.
+    if ( $serviceOptions->{'databaseName'} ) {
+        $Zpackage->option( databaseName => $serviceOptions->{'databaseName'} );
+    }
+    if ( $serviceOptions->{'recordIdNumber'} ) {
+        $Zpackage->option(
+            recordIdNumber => $serviceOptions->{'recordIdNumber'} );
+    }
+    if ( $serviceOptions->{'recordIdOpaque'} ) {
+        $Zpackage->option(
+            recordIdOpaque => $serviceOptions->{'recordIdOpaque'} );
+    }
 
-C<@websites> is an array of references-to-hash; the keys are the
-fields from the C<websites> table in the Koha database.
+ # this is an ILL request (Zebra doesn't support it, but Koha could eventually)
+ #if ($serviceType eq 'itemorder') {
+ #   $Zpackage->option('contact-name' => $serviceOptions->{'contact-name'});
+ #   $Zpackage->option('contact-phone' => $serviceOptions->{'contact-phone'});
+ #   $Zpackage->option('contact-email' => $serviceOptions->{'contact-email'});
+ #   $Zpackage->option('itemorder-item' => $serviceOptions->{'itemorder-item'});
+ #}
 
-=cut
-#FIXME : could maybe be deleted. Otherwise, would be better in a Websites.pm package
-#(with add / modify / delete subs)
+    if ( $serviceOptions->{record} ) {
+        $Zpackage->option( record => $serviceOptions->{record} );
 
-sub getwebsites {
-    my ($biblionumber) = @_;
-    my $dbh   = C4::Context->dbh;
-    my $sth   = $dbh->prepare("Select * from websites where biblionumber = ?");
-    my $count = 0;
-    my @results;
+        # can be xml or marc
+        if ( $serviceOptions->{'syntax'} ) {
+            $Zpackage->option( syntax => $serviceOptions->{'syntax'} );
+        }
+    }
 
-    $sth->execute($biblionumber);
-    while (my $data = $sth->fetchrow_hashref) {
-        # FIXME - The URL scheme shouldn't be stripped off, at least
-        # not here, since it's part of the URL, and will be useful in
-        # constructing a link to the site. If you don't want the user
-        # to see the "http://" part, strip that off when building the
-        # HTML code.
-        $data->{'url'} =~ s/^http:\/\///;      # FIXME - Leaning toothpick
-                                               # syndrome
-        $results[$count] = $data;
-       $count++;
-    } # while
+    # send the request, handle any exception encountered
+    eval { $Zpackage->send($serviceType) };
+    if ( $@ && $@->isa("ZOOM::Exception") ) {
+        return "error:  " . $@->code() . " " . $@->message() . "\n";
+    }
 
-    $sth->finish;
-    return($count, @results);
-} # sub getwebsites
+    # free up package resources
+    $Zpackage->destroy();
+}
 
-=item getwebbiblioitems
+=head2 set_service_options
 
-  ($count, @results) = &getwebbiblioitems($biblionumber);
+my $serviceOptions = set_service_options($serviceType);
 
-Given a book's biblionumber, looks up the web versions of the book
-(biblioitems with itemtype C<WEB>).
+C<$serviceType> itemorder,create,drop,commit,update,xmlupdate
 
-C<$count> is the number of items in C<@results>. C<@results> is an
-array of references-to-hash; the keys are the items from the
-C<biblioitems> table of the Koha database.
+Currently, we only support 'create', 'commit', and 'update'. 'drop' support will be added as soon as Zebra supports it.
 
 =cut
-#'
-sub getwebbiblioitems {
-    my ($biblionumber) = @_;
-    my $dbh   = C4::Context->dbh;
-    my $sth   = $dbh->prepare("Select * from biblioitems where biblionumber = ?
-and itemtype = 'WEB'");
-    my $count = 0;
-    my @results;
-
-    $sth->execute($biblionumber);
-    while (my $data = $sth->fetchrow_hashref) {
-        $data->{'url'} =~ s/^http:\/\///;
-        $results[$count] = $data;
-        $count++;
-    } # while
 
-    $sth->finish;
-    return($count, @results);
-} # sub getwebbiblioitems
+sub set_service_options {
+    my ($serviceType) = @_;
+    my $serviceOptions;
 
-sub char_decode {
+# FIXME: This needs to be an OID ... if we ever need 'syntax' this sub will need to change
+#   $serviceOptions->{ 'syntax' } = ''; #zebra doesn't support syntaxes other than xml
 
-    # converts ISO 5426 coded string to ISO 8859-1
-    # sloppy code : should be improved in next issue
-    my ( $string, $encoding ) = @_;
-    $_ = $string;
+    if ( $serviceType eq 'commit' ) {
 
-    #  $encoding = C4::Context->preference("marcflavour") unless $encoding;
-    if ( $encoding eq "UNIMARC" ) {
-#         s/\xe1/Æ/gm;
-        s/\xe2/Ð/gm;
-        s/\xe9/Ø/gm;
-        s/\xec/þ/gm;
-        s/\xf1/æ/gm;
-        s/\xf3/ð/gm;
-        s/\xf9/ø/gm;
-        s/\xfb/ß/gm;
-        s/\xc1\x61/à/gm;
-        s/\xc1\x65/è/gm;
-        s/\xc1\x69/ì/gm;
-        s/\xc1\x6f/ò/gm;
-        s/\xc1\x75/ù/gm;
-        s/\xc1\x41/À/gm;
-        s/\xc1\x45/È/gm;
-        s/\xc1\x49/Ì/gm;
-        s/\xc1\x4f/Ò/gm;
-        s/\xc1\x55/Ù/gm;
-        s/\xc2\x41/Á/gm;
-        s/\xc2\x45/É/gm;
-        s/\xc2\x49/Í/gm;
-        s/\xc2\x4f/Ó/gm;
-        s/\xc2\x55/Ú/gm;
-        s/\xc2\x59/Ý/gm;
-        s/\xc2\x61/á/gm;
-        s/\xc2\x65/é/gm;
-        s/\xc2\x69/í/gm;
-        s/\xc2\x6f/ó/gm;
-        s/\xc2\x75/ú/gm;
-        s/\xc2\x79/ý/gm;
-        s/\xc3\x41/Â/gm;
-        s/\xc3\x45/Ê/gm;
-        s/\xc3\x49/Î/gm;
-        s/\xc3\x4f/Ô/gm;
-        s/\xc3\x55/Û/gm;
-        s/\xc3\x61/â/gm;
-        s/\xc3\x65/ê/gm;
-        s/\xc3\x69/î/gm;
-        s/\xc3\x6f/ô/gm;
-        s/\xc3\x75/û/gm;
-        s/\xc4\x41/Ã/gm;
-        s/\xc4\x4e/Ñ/gm;
-        s/\xc4\x4f/Õ/gm;
-        s/\xc4\x61/ã/gm;
-        s/\xc4\x6e/ñ/gm;
-        s/\xc4\x6f/õ/gm;
-        s/\xc8\x41/Ä/gm;
-        s/\xc8\x45/Ë/gm;
-        s/\xc8\x49/Ï/gm;
-        s/\xc8\x61/ä/gm;
-        s/\xc8\x65/ë/gm;
-        s/\xc8\x69/ï/gm;
-        s/\xc8\x6F/ö/gm;
-        s/\xc8\x75/ü/gm;
-        s/\xc8\x76/ÿ/gm;
-        s/\xc9\x41/Ä/gm;
-        s/\xc9\x45/Ë/gm;
-        s/\xc9\x49/Ï/gm;
-        s/\xc9\x4f/Ö/gm;
-        s/\xc9\x55/Ü/gm;
-        s/\xc9\x61/ä/gm;
-        s/\xc9\x6f/ö/gm;
-        s/\xc9\x75/ü/gm;
-        s/\xca\x41/Å/gm;
-        s/\xca\x61/å/gm;
-        s/\xd0\x43/Ç/gm;
-        s/\xd0\x63/ç/gm;
+        # nothing to do
+    }
+    if ( $serviceType eq 'create' ) {
 
-        # this handles non-sorting blocks (if implementation requires this)
-        $string = nsb_clean($_);
+        # nothing to do
     }
-    elsif ( $encoding eq "USMARC" || $encoding eq "MARC21" ) {
-        if (/[\xc1-\xff]/) {
-            s/\xe1\x61/à/gm;
-            s/\xe1\x65/è/gm;
-            s/\xe1\x69/ì/gm;
-            s/\xe1\x6f/ò/gm;
-            s/\xe1\x75/ù/gm;
-            s/\xe1\x41/À/gm;
-            s/\xe1\x45/È/gm;
-            s/\xe1\x49/Ì/gm;
-            s/\xe1\x4f/Ò/gm;
-            s/\xe1\x55/Ù/gm;
-            s/\xe2\x41/Á/gm;
-            s/\xe2\x45/É/gm;
-            s/\xe2\x49/Í/gm;
-            s/\xe2\x4f/Ó/gm;
-            s/\xe2\x55/Ú/gm;
-            s/\xe2\x59/Ý/gm;
-            s/\xe2\x61/á/gm;
-            s/\xe2\x65/é/gm;
-            s/\xe2\x69/í/gm;
-            s/\xe2\x6f/ó/gm;
-            s/\xe2\x75/ú/gm;
-            s/\xe2\x79/ý/gm;
-            s/\xe3\x41/Â/gm;
-            s/\xe3\x45/Ê/gm;
-            s/\xe3\x49/Î/gm;
-            s/\xe3\x4f/Ô/gm;
-            s/\xe3\x55/Û/gm;
-            s/\xe3\x61/â/gm;
-            s/\xe3\x65/ê/gm;
-            s/\xe3\x69/î/gm;
-            s/\xe3\x6f/ô/gm;
-            s/\xe3\x75/û/gm;
-            s/\xe4\x41/Ã/gm;
-            s/\xe4\x4e/Ñ/gm;
-            s/\xe4\x4f/Õ/gm;
-            s/\xe4\x61/ã/gm;
-            s/\xe4\x6e/ñ/gm;
-            s/\xe4\x6f/õ/gm;
-            s/\xe8\x45/Ë/gm;
-            s/\xe8\x49/Ï/gm;
-            s/\xe8\x65/ë/gm;
-            s/\xe8\x69/ï/gm;
-            s/\xe8\x76/ÿ/gm;
-            s/\xe9\x41/Ä/gm;
-            s/\xe9\x4f/Ö/gm;
-            s/\xe9\x55/Ü/gm;
-            s/\xe9\x61/ä/gm;
-            s/\xe9\x6f/ö/gm;
-            s/\xe9\x75/ü/gm;
-            s/\xea\x41/Å/gm;
-            s/\xea\x61/å/gm;
-
-            # this handles non-sorting blocks (if implementation requires this)
-            $string = nsb_clean($_);
-        }
+    if ( $serviceType eq 'drop' ) {
+        die "ERROR: 'drop' not currently supported (by Zebra)";
     }
-    return ($string);
+    return $serviceOptions;
 }
 
-sub nsb_clean {
-    my $NSB = '\x88';    # NSB : begin Non Sorting Block
-    my $NSE = '\x89';    # NSE : Non Sorting Block end
-                         # handles non sorting blocks
-    my ($string) = @_;
-    $_ = $string;
-    s/$NSB/(/gm;
-    s/[ ]{0,1}$NSE/) /gm;
-    $string = $_;
-    return ($string);
-}
+=head2 GetItemsCount
 
-sub FindDuplicate {
-       my ($record)=@_;
-       my $dbh = C4::Context->dbh;
-       my $result = MARCmarc2koha($dbh,$record,'');
-       my $sth;
-       my ($biblionumber,$bibid,$title);
-       # search duplicate on ISBN, easy and fast...
-       if ($result->{isbn}) {
-               $sth = $dbh->prepare("select biblio.biblionumber,bibid,title from biblio,biblioitems,marc_biblio where biblio.biblionumber=biblioitems.biblionumber and marc_biblio.biblionumber=biblioitems.biblionumber and isbn=?");
-               $sth->execute($result->{'isbn'});
-               ($biblionumber,$bibid,$title) = $sth->fetchrow;
-               return $biblionumber,$bibid,$title if ($biblionumber);
-       }
-       # a more complex search : build a request for SearchMarc::catalogsearch()
-       my (@tags, @and_or, @excluding, @operator, @value, $offset,$length);
-       # search on biblio.title
-       my ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblio.title","");
-       if ($record->field($tag)) {
-               if ($record->field($tag)->subfields($subfield)) {
-                       push @tags, "'".$tag.$subfield."'";
-                       push @and_or, "and";
-                       push @excluding, "";
-                       push @operator, "contains";
-                       push @value, $record->field($tag)->subfield($subfield);
-#                      warn "for title, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
-               }
-       }
-       # ... and on biblio.author
-       ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblio.author","");
-       if ($record->field($tag)) {
-               if ($record->field($tag)->subfields($subfield)) {
-                       push @tags, "'".$tag.$subfield."'";
-                       push @and_or, "and";
-                       push @excluding, "";
-                       push @operator, "contains";
-                       push @value, $record->field($tag)->subfield($subfield);
-#                      warn "for author, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
-               }
-       }
-       # ... and on publicationyear.
-       ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblioitems.publicationyear","");
-       if ($record->field($tag)) {
-               if ($record->field($tag)->subfields($subfield)) {
-                       push @tags, "'".$tag.$subfield."'";
-                       push @and_or, "and";
-                       push @excluding, "";
-                       push @operator, "=";
-                       push @value, $record->field($tag)->subfield($subfield);
-#                      warn "for publicationyear, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
-               }
-       }
-       # ... and on size.
-       ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblioitems.size","");
-       if ($record->field($tag)) {
-               if ($record->field($tag)->subfields($subfield)) {
-                       push @tags, "'".$tag.$subfield."'";
-                       push @and_or, "and";
-                       push @excluding, "";
-                       push @operator, "=";
-                       push @value, $record->field($tag)->subfield($subfield);
-#                      warn "for size, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
-               }
-       }
-       # ... and on publisher.
-       ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblioitems.publishercode","");
-       if ($record->field($tag)) {
-               if ($record->field($tag)->subfields($subfield)) {
-                       push @tags, "'".$tag.$subfield."'";
-                       push @and_or, "and";
-                       push @excluding, "";
-                       push @operator, "=";
-                       push @value, $record->field($tag)->subfield($subfield);
-#                      warn "for publishercode, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
-               }
-       }
-       # ... and on volume.
-       ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblioitems.volume","");
-       if ($record->field($tag)) {
-               if ($record->field($tag)->subfields($subfield)) {
-                       push @tags, "'".$tag.$subfield."'";
-                       push @and_or, "and";
-                       push @excluding, "";
-                       push @operator, "=";
-                       push @value, $record->field($tag)->subfield($subfield);
-#                      warn "for volume, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
-               }
-       }
-
-       my ($finalresult,$nbresult) = C4::SearchMarc::catalogsearch($dbh,\@tags,\@and_or,\@excluding,\@operator,\@value,0,10);
-       # there is at least 1 result => return the 1st one
-       if ($nbresult) {
-#              warn "$nbresult => ".@$finalresult[0]->{biblionumber},@$finalresult[0]->{bibid},@$finalresult[0]->{title};
-               return @$finalresult[0]->{biblionumber},@$finalresult[0]->{bibid},@$finalresult[0]->{title};
-       }
-       # no result, returns nothing
-       return;
-}
-
-sub DisplayISBN {
-       my ($isbn)=@_;
-       my $seg1;
-       if(substr($isbn, 0, 1) <=7) {
-               $seg1 = substr($isbn, 0, 1);
-       } elsif(substr($isbn, 0, 2) <= 94) {
-               $seg1 = substr($isbn, 0, 2);
-       } elsif(substr($isbn, 0, 3) <= 995) {
-               $seg1 = substr($isbn, 0, 3);
-       } elsif(substr($isbn, 0, 4) <= 9989) {
-               $seg1 = substr($isbn, 0, 4);
-       } else {
-               $seg1 = substr($isbn, 0, 5);
-       }
-       my $x = substr($isbn, length($seg1));
-       my $seg2;
-       if(substr($x, 0, 2) <= 19) {
-#              if(sTmp2 < 10) sTmp2 = "0" sTmp2;
-               $seg2 = substr($x, 0, 2);
-       } elsif(substr($x, 0, 3) <= 699) {
-               $seg2 = substr($x, 0, 3);
-       } elsif(substr($x, 0, 4) <= 8399) {
-               $seg2 = substr($x, 0, 4);
-       } elsif(substr($x, 0, 5) <= 89999) {
-               $seg2 = substr($x, 0, 5);
-       } elsif(substr($x, 0, 6) <= 9499999) {
-               $seg2 = substr($x, 0, 6);
-       } else {
-               $seg2 = substr($x, 0, 7);
-       }
-       my $seg3=substr($x,length($seg2));
-       $seg3=substr($seg3,0,length($seg3)-1) ;
-       my $seg4 = substr($x, -1, 1);
-       return "$seg1-$seg2-$seg3-$seg4";
-}
+$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)
 
-=back
+1;
+
+__END__
 
 =head1 AUTHOR
 
@@ -3010,143 +4143,170 @@ Koha Developement team <info@koha.org>
 
 Paul POULAIN paul.poulain@free.fr
 
+Joshua Ferraro jmf@liblime.com
+
 =cut
 
 # $Id$
 # $Log$
-# Revision 1.144  2006/02/20 14:22:38  kados
-# typo
+# Revision 1.221  2007/07/31 16:01:11  toins
+# Some new functions.
+# TransformHTMLtoMarc rewrited.
 #
-# Revision 1.143  2006/02/20 13:26:11  kados
-# A new subroutine to handle Z39.50 extended services. You pass it a
-# connection object, service type, service options, and a record, and
-# it performs the service and handles any exception found.
+# Revision 1.220  2007/07/20 15:43:16  hdl
+# Bug Fixing GetMarcSubjects.
+# Links parameters were mixed.
 #
-# Revision 1.142  2006/02/16 20:49:56  kados
-# destroy a connection after we're done -- we really should just have one
-# connection object and not destroy it until the whole transaction is
-# finished -- but this will do for now
+# Revision 1.218  2007/07/19 07:40:08  hdl
+# Adding selection by location for inventory
 #
-# Revision 1.141  2006/02/16 19:47:22  rangi
-# Trying to error trap a little more.
+# 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.140  2006/02/14 21:36:03  kados
-# adding a 'use ZOOM' to biblio.pm, needed for non-mod_perl install.
-# also adding diagnostic error if not able to connect to Zebra
+# Revision 1.216  2007/07/03 09:40:58  tipaul
+# return itemtype description properly
 #
-# Revision 1.139  2006/02/14 19:53:25  rangi
-# Just a little missing my
+# 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
 #
-# Seems to be working great Paul, and I like what you did with zebradb
+# 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.138  2006/02/14 11:25:22  tipaul
-# road to 3.0 : updating a biblio in zebra seems to work. Still working on it, there are probably some bugs !
+# Revision 1.213  2007/06/25 15:01:45  tipaul
+# bugfixes on unimarc 100 handling (the field used for encoding)
 #
-# Revision 1.137  2006/02/13 16:34:26  tipaul
-# fixing some warnings (perl -w should be quiet)
+# Revision 1.212  2007/06/15 13:44:44  tipaul
+# some fixes (and only fixes)
 #
-# Revision 1.136  2006/01/10 17:01:29  tipaul
-# adding a XMLgetbiblio in Biblio.pm (1st draft, to use with zebra)
+# 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.135  2006/01/06 16:39:37  tipaul
-# synch'ing head and rel_2_2 (from 2.2.5, including npl templates)
-# Seems not to break too many things, but i'm probably wrong here.
-# at least, new features/bugfixes from 2.2.5 are here (tested on some features on my head local copy)
+# Revision 1.210  2007/06/13 13:03:34  toins
+# removing warn compilation.
 #
-# - removing useless directories (koha-html and koha-plucene)
+# Revision 1.209  2007/05/23 16:19:40  tipaul
+# various bugfixes (minor) and french translation updated
 #
-# Revision 1.134  2006/01/04 15:54:55  tipaul
-# utf8 is a : go for beta test in HEAD.
-# some explanations :
-# - updater/updatedatabase => will transform all tables in innoDB (not related to utf8, just to warn you) AND collate them in utf8 / utf8_general_ci. The SQL command is : ALTER TABLE tablename DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci.
-# - *-top.inc will show the pages in utf8
-# - THE HARD THING : for me, mysql-client and mysql-server were set up to communicate in iso8859-1, whatever the mysql collation ! Thus, pages were improperly shown, as datas were transmitted in iso8859-1 format ! After a full day of investigation, someone on usenet pointed "set NAMES 'utf8'" to explain that I wanted utf8. I could put this in my.cnf, but if I do that, ALL databases will "speak" in utf8, that's not what we want. Thus, I added a line in Context.pm : everytime a DB handle is opened, the communication is set to utf8.
-# - using marcxml field and no more the iso2709 raw marc biblioitems.marc field.
+# 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.133  2005/12/12 14:25:51  thd
+# 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
 #
-# Reverse array filled with elements from repeated subfields
-# to avoid last to first concatenation of elements in Koha DB.-
+# 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.132  2005-10-26 09:12:33  tipaul
-# big commit, still breaking things...
+# 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
 #
-# * synch with rel_2_2. Probably the last non manual synch, as rel_2_2 should not be modified deeply.
-# * code cleaning (cleaning warnings from perl -w) continued
+# 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.131  2005/09/22 10:01:45  tipaul
-# see mail on koha-devel : code cleaning on Search.pm + normalizing API + use of biblionumber everywhere (instead of bn, biblio, ...)
+# 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.130  2005/09/02 14:34:14  tipaul
-# continuing the work to move to zebra. Begin of work for MARC=OFF support.
-# IMPORTANT NOTE : the MARCkoha2marc sub API has been modified. Instead of biblionumber & biblioitemnumber, it now gets a hash.
-# The sub is used only in Biblio.pm, so the API change should be harmless (except for me, but i'm aware ;-) )
+# 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.129  2005/08/12 13:50:31  tipaul
-# removing useless sub declarations
+# Revision 1.201  2007/04/27 14:00:49  hdl
+# Removing $dbh from GetMarcFromKohaField (dbh is not used in this function.)
 #
-# Revision 1.128  2005/08/11 16:12:47  tipaul
-# Playing with the zebra...
+# 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
 #
-# * go to koha cvs home directory
-# * in misc/zebra there is a unimarc directory. I suggest that marc21 libraries create a marc21 directory
-# * put your zebra.cfg files here & create your database.
-# * from koha cvs home directory, ln -s misc/zebra/marc21 zebra (I mean create a symbolic link to YOUR zebra directory)
-# * now, everytime you add/modify a biblio/item your zebra DB is updated correctly.
+# Revision 1.199  2007/04/24 09:07:53  tipaul
+# moving dotransfer to Biblio.pm::ModItemTransfer + some CheckReserves fixes
 #
-# NOTE :
-# * this uses a system call in perl. CPU consumming, but we are waiting for indexdata Perl/zoom
-# * deletion still not work
-# * UNIMARC zebra config files are provided in misc/zebra/unimarc directory. The most important line being :
-# in zebra.cfg :
-# recordId: (bib1,Local-number)
-# storeKeys:1
+# Revision 1.198  2007/04/23 15:21:17  tipaul
+# renaming currenttransfers to transferstoreceive
 #
-# in .abs file :
-# elm 090            Local-number            -
-# elm 090/?          Local-number            -
-# elm 090/?/9        Local-number            !:w
+# Revision 1.197  2007/04/18 17:00:14  tipaul
+# removing all useless %env / $env
 #
-# (090$9 being the field mapped to biblio.biblionumber in Koha)
+# Revision 1.196  2007/04/17 08:48:00  tipaul
+# circulation cleaning continued: bufixing
 #
-# Revision 1.127  2005/08/11 14:37:32  tipaul
-# * POD documenting
-# * removing useless subs
-# * removing some subs that are also elsewhere
-# * renaming all OLDxxx subs to REALxxx subs (should not change anything, as OLDxxx, as well as REAL, are supposed to be for Biblio.pm internal use only)
+# Revision 1.195  2007/04/04 16:46:22  tipaul
+# HUGE COMMIT : code cleaning circulation.
 #
-# Revision 1.126  2005/08/11 09:13:28  tipaul
-# just removing useless subs (a lot !!!) for code cleaning
+# some stuff to do, i'll write a mail on koha-devel NOW !
 #
-# Revision 1.125  2005/08/11 09:00:07  tipaul
-# Ok guys, this time, it seems that item add and modif begin working as expected...
-# Still a lot of bugs to fix, of course
+# 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.124  2005/08/10 10:21:15  tipaul
-# continuing the road to zebra :
-# - the biblio add begins to work.
-# - the biblio modif begins to work.
+# Revision 1.193  2007/03/29 16:45:53  tipaul
+# Code cleaning of Biblio.pm (continued)
 #
-# (still without doing anything on zebra)
-# (no new change in updatedatabase)
+# All subs have be cleaned :
+# - removed useless
+# - merged some
+# - reordering Biblio.pm completly
+# - using only naming conventions
 #
-# Revision 1.123  2005/08/09 14:10:28  tipaul
-# 1st commit to go to zebra.
-# don't update your cvs if you want to have a working head...
+# 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.
 #
-# this commit contains :
-# * updater/updatedatabase : get rid with marc_* tables, but DON'T remove them. As a lot of things uses them, it would not be a good idea for instance to drop them. If you really want to play, you can rename them to test head without them but being still able to reintroduce them...
-# * Biblio.pm : modify MARCgetbiblio to find the raw marc record in biblioitems.marc field, not from marc_subfield_table, modify MARCfindframeworkcode to find frameworkcode in biblio.frameworkcode, modify some other subs to use biblio.biblionumber & get rid of bibid.
-# * other files : get rid of bibid and use biblionumber instead.
+# 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
 #
-# What is broken :
-# * does not do anything on zebra yet.
-# * if you rename marc_subfield_table, you can't search anymore.
-# * you can view a biblio & bibliodetails, go to MARC editor, but NOT save any modif.
-# * don't try to add a biblio, it would add data poorly... (don't try to delete either, it may work, but that would be a surprise ;-) )
+# == 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
 #
-# IMPORTANT NOTE : you need MARC::XML package (http://search.cpan.org/~esummers/MARC-XML-0.7/lib/MARC/File/XML.pm), that requires a recent version of MARC::Record
-# Updatedatabase stores the iso2709 data in biblioitems.marc field & an xml version in biblioitems.marcxml Not sure we will keep it when releasing the stable version, but I think it's a good idea to have something readable in sql, at least for development stage.
-
-# tipaul cutted previous commit notes
+# == 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.