LDAP - further integration
[koha_fer] / C4 / Biblio.pm
old mode 100644 (file)
new mode 100755 (executable)
index 11df070..83ddd6d
@@ -27,13 +27,14 @@ use MARC::File::USMARC;
 use MARC::File::XML;
 use ZOOM;
 use C4::Koha;
-use C4::Date;
+use C4::Dates qw/format_date/;
 use C4::Log; # logaction
+use C4::ClassSource;
 
 use vars qw($VERSION @ISA @EXPORT);
 
-# set the version for version checking
-$VERSION = do { my @v = '$Revision$' =~ /\d+/g; shift(@v).".".join( "_", map { sprintf "%03d", $_ } @v ); };
+# TODO: fix version
+# $VERSION = ?;
 
 @ISA = qw( Exporter );
 
@@ -107,8 +108,6 @@ push @EXPORT, qw(
 push @EXPORT, qw(
   &ModBiblioMarc
   &AddItemInMarc
-  &calculatelc
-  &itemcalculator
 );
 
 # Others functions
@@ -209,70 +208,15 @@ Exported function (core API) for adding a new biblio to koha.
 
 sub AddBiblio {
     my ( $record, $frameworkcode ) = @_;
-    my $biblionumber;
-    my $biblioitemnumber;
+       my ($biblionumber,$biblioitemnumber,$error);
     my $dbh = C4::Context->dbh;
     # transform the data into koha-table style data
     my $olddata = TransformMarcToKoha( $dbh, $record, $frameworkcode );
-    $biblionumber = _koha_add_biblio( $dbh, $olddata, $frameworkcode );
+    ($biblionumber,$error) = _koha_add_biblio( $dbh, $olddata, $frameworkcode );
     $olddata->{'biblionumber'} = $biblionumber;
-    $biblioitemnumber = _koha_add_biblioitem( $dbh, $olddata );
+    ($biblioitemnumber,$error) = _koha_add_biblioitem( $dbh, $olddata );
 
-    # we must add bibnum and bibitemnum in MARC::Record...
-    # we build the new field with biblionumber and biblioitemnumber
-    # we drop the original field
-    # we add the new builded field.
-    ( my $biblio_tag, my $biblio_subfield ) = GetMarcFromKohaField("biblio.biblionumber",$frameworkcode);
-    ( my $biblioitem_tag, my $biblioitem_subfield ) = GetMarcFromKohaField("biblioitems.biblioitemnumber",$frameworkcode);
-
-    my $newfield;
-
-    # biblionumber & biblioitemnumber are in different fields
-    if ( $biblio_tag != $biblioitem_tag ) {
-
-        # deal with biblionumber
-        if ( $biblio_tag < 10 ) {
-            $newfield = MARC::Field->new( $biblio_tag, $biblionumber );
-        }
-        else {
-            $newfield =
-              MARC::Field->new( $biblio_tag, '', '',
-                "$biblio_subfield" => $biblionumber );
-        }
-
-        # drop old field and create new one...
-        my $old_field = $record->field($biblio_tag);
-        $record->delete_field($old_field);
-        $record->append_fields($newfield);
-
-        # deal with biblioitemnumber
-        if ( $biblioitem_tag < 10 ) {
-            $newfield = MARC::Field->new( $biblioitem_tag, $biblioitemnumber, );
-        }
-        else {
-            $newfield =
-              MARC::Field->new( $biblioitem_tag, '', '',
-                "$biblioitem_subfield" => $biblioitemnumber, );
-        }
-        # drop old field and create new one...
-        $old_field = $record->field($biblioitem_tag);
-        $record->delete_field($old_field);
-        $record->insert_fields_ordered($newfield);
-
-# biblionumber & biblioitemnumber are in the same field (can't be <10 as fields <10 have only 1 value)
-    }
-    else {
-        my $newfield = MARC::Field->new(
-            $biblio_tag, '', '',
-            "$biblio_subfield" => $biblionumber,
-            "$biblioitem_subfield" => $biblioitemnumber
-        );
-
-        # drop old field and create new one...
-        my $old_field = $record->field($biblio_tag);
-        $record->delete_field($old_field);
-        $record->insert_fields_ordered($newfield);
-    }
+    _koha_marc_update_bib_ids($record, $frameworkcode, $biblionumber, $biblioitemnumber);
 
     # now add the record
     $biblionumber = ModBiblioMarc( $record, $biblionumber, $frameworkcode );
@@ -306,15 +250,15 @@ sub AddItem {
     $item->{'biblionumber'} = $biblionumber;
     my $sth =
       $dbh->prepare(
-        "select biblioitemnumber,itemtype from biblioitems where biblionumber=?"
+        "SELECT biblioitemnumber,itemtype FROM biblioitems WHERE biblionumber=?"
       );
     $sth->execute( $item->{'biblionumber'} );
     my $itemtype;
     ( $item->{'biblioitemnumber'}, $itemtype ) = $sth->fetchrow;
     $sth =
       $dbh->prepare(
-        "select notforloan from itemtypes where itemtype='$itemtype'");
-    $sth->execute();
+        "SELECT notforloan FROM itemtypes WHERE itemtype=?");
+    $sth->execute( C4::Context->preference('item-level_itypes') ? $item->{'itype'} : $itemtype );
     my $notforloan = $sth->fetchrow;
     ##Change the notforloan field if $notforloan found
     if ( $notforloan > 0 ) {
@@ -333,19 +277,20 @@ sub AddItem {
         $item->{'dateaccessioned'} = $date;
         &MARCitemchange( $record, "items.dateaccessioned", $date );
     }
-    my ( $itemnumber, $error ) =
-      &_koha_new_items( $dbh, $item, $item->{barcode} );
-
+    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=?"
+"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");
     
@@ -392,14 +337,15 @@ sub ModBiblio {
         $record->append_fields($field);
     }
     
-    # adding biblionumber
-    my ($tag_biblionumber, $subfield_biblionumber) = GetMarcFromKohaField('biblio.biblionumber',$frameworkcode);
-    $record->append_fields(
-           MARC::Field->new(
-                   $tag_biblionumber,'','',$subfield_biblionumber => $biblionumber
-           )
-    ) unless ($record->subfield($tag_biblionumber,$subfield_biblionumber));
-    
+    # update biblionumber and biblioitemnumber in MARC
+    # FIXME - this is assuming a 1 to 1 relationship between
+    # biblios and biblioitems
+    my $sth =  $dbh->prepare("select biblioitemnumber from biblioitems where biblionumber=?");
+    $sth->execute($biblionumber);
+    my ($biblioitemnumber) = $sth->fetchrow;
+    $sth->finish();
+    _koha_marc_update_bib_ids($record, $frameworkcode, $biblionumber, $biblioitemnumber);
+
     # update the MARC record (that now contains biblio and items) with the new record data
     &ModBiblioMarc( $record, $biblionumber, $frameworkcode );
     
@@ -407,8 +353,8 @@ sub ModBiblio {
     my $oldbiblio = TransformMarcToKoha( $dbh, $record, $frameworkcode );
 
     # modify the other koha tables
-    _koha_modify_biblio( $dbh, $oldbiblio );
-    _koha_modify_biblioitem( $dbh, $oldbiblio );
+    _koha_modify_biblio( $dbh, $oldbiblio, $frameworkcode );
+    _koha_modify_biblioitem_nonmarc( $dbh, $oldbiblio );
     return 1;
 }
 
@@ -438,7 +384,13 @@ sub ModItem {
     if ($record) {
         my $frameworkcode = GetFrameworkCode( $biblionumber );
         ModItemInMarc( $record, $biblionumber, $itemnumber, $frameworkcode );
-        my $olditem       = TransformMarcToKoha( $dbh, $record, $frameworkcode );
+        my $olditem       = TransformMarcToKoha( $dbh, $record, $frameworkcode,'items');
+        $olditem->{'biblionumber'} = $biblionumber;
+        my $sth =  $dbh->prepare("select biblioitemnumber from biblioitems where biblionumber=?");
+        $sth->execute($biblionumber);
+        my ($biblioitemnumber) = $sth->fetchrow;
+        $sth->finish(); 
+        $olditem->{'biblioitemnumber'} = $biblioitemnumber;
         _koha_modify_item( $dbh, $olditem );
         return $biblionumber;
     }
@@ -458,11 +410,11 @@ sub ModItemTransfer {
     #new entry in branchtransfers....
     my $sth = $dbh->prepare(
         "INSERT INTO branchtransfers (itemnumber, frombranch, datesent, tobranch)
-        VALUES (?, ?, now(), ?)");
+        VALUES (?, ?, NOW(), ?)");
     $sth->execute($itemnumber, $frombranch, $tobranch);
     #update holdingbranch in items .....
      $sth= $dbh->prepare(
-          "UPDATE items set holdingbranch = ? WHERE items.itemnumber = ?");
+          "UPDATE items SET holdingbranch = ? WHERE items.itemnumber = ?");
     $sth->execute($tobranch,$itemnumber);
     &ModDateLastSeen($itemnumber);
     $sth = $dbh->prepare(
@@ -487,9 +439,9 @@ sub ModBiblioframework {
     my ( $biblionumber, $frameworkcode ) = @_;
     my $dbh = C4::Context->dbh;
     my $sth = $dbh->prepare(
-        "UPDATE biblio SET frameworkcode=? WHERE biblionumber=$biblionumber"
+        "UPDATE biblio SET frameworkcode=? WHERE biblionumber=?"
     );
-    $sth->execute($frameworkcode);
+    $sth->execute($frameworkcode, $biblionumber);
     return 1;
 }
 
@@ -513,14 +465,22 @@ sub ModItemInMarconefield {
 
     my $record = GetMarcItem( $biblionumber, $itemnumber );
     my ($tagfield, $tagsubfield) = GetMarcFromKohaField( $itemfield,'');
-    if ($tagfield && $tagsubfield) {
+    # FIXME - the condition is done this way because GetMarcFromKohaField
+    # returns (0, 0) if it can't field a MARC tag for the kohafield.  However,
+    # some fields like items.wthdrawn are mapped to subfield $0, making the
+    # customary test of "if ($tagfield && $tagsubfield)" incorrect.
+    # GetMarcFromKohaField should probably be returning (undef, undef), making
+    # the correct test "if (defined $tagfield && defined $tagsubfield)", but
+    # this would be a large change and consequently deferred for after 3.0.
+    if (not(int($tagfield) == 0 && int($tagsubfield) == 0)) { 
         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 );
+            my $frameworkcode = GetFrameworkCode( $biblionumber );
+            &ModItemInMarc( $record, $biblionumber, $itemnumber, $frameworkcode );
         }
     }
 }
@@ -529,7 +489,7 @@ sub ModItemInMarconefield {
 
 =over
 
-&ModItemInMarc( $record, $biblionumber, $itemnumber )
+&ModItemInMarc( $record, $biblionumber, $itemnumber, $frameworkcode )
 
 =back
 
@@ -551,7 +511,7 @@ sub ModItemInMarc {
         }
     }
     # save the record
-    my $sth = $dbh->prepare("update biblioitems set marc=?,marcxml=?  where biblionumber=?");
+    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);
@@ -570,7 +530,7 @@ sub ModDateLastSeen {
     my $dbh       = C4::Context->dbh;
     my $sth       =
       $dbh->prepare(
-          "update items set itemlost=0, datelastseen  = now() where items.itemnumber = ?"
+          "UPDATE items SET itemlost=0,datelastseen  = NOW() WHERE items.itemnumber = ?"
       );
     $sth->execute($itemnum);
     return;
@@ -611,10 +571,7 @@ sub DelBiblio {
     # - we need to read the biblio if NoZebra is set (to remove it from the indexes
     # - if something goes wrong, the biblio may be deleted from Koha but not from zebra
     #   and we would have no way to remove it (except manually in zebra, but I bet it would be very hard to handle the problem)
-    ModZebra($biblionumber, "delete_record", "biblioserver", undef);
-
-    # delete biblio from Koha tables and save in deletedbiblio
-    $error = &_koha_delete_biblio( $dbh, $biblionumber );
+    ModZebra($biblionumber, "recordDelete", "biblioserver", undef);
 
     # delete biblioitems and items from Koha tables and save in deletedbiblioitems,deleteditems
     $sth =
@@ -624,9 +581,16 @@ sub DelBiblio {
     while ( my $biblioitemnumber = $sth->fetchrow ) {
 
         # delete this biblioitem
-        $error = &_koha_delete_biblioitems( $dbh, $biblioitemnumber );
+        $error = _koha_delete_biblioitems( $dbh, $biblioitemnumber );
         return $error if $error;
     }
+
+    # delete biblio from Koha tables and save in deletedbiblio
+    # must do this *after* _koha_delete_biblioitems, otherwise
+    # delete cascade will prevent deletedbiblioitems rows
+    # from being generated by _koha_delete_biblioitems
+    $error = _koha_delete_biblio( $dbh, $biblionumber );
+
     &logaction(C4::Context->userenv->{'number'},"CATALOGUING","DELETE",$biblionumber,"") 
         if C4::Context->preference("CataloguingLog");
     return;
@@ -644,25 +608,25 @@ Exported function (core API) for deleting an item record in Koha.
 =cut
 
 sub DelItem {
-    my ( $biblionumber, $itemnumber ) = @_;
-    my $dbh = C4::Context->dbh;
+    my ( $dbh, $biblionumber, $itemnumber ) = @_;
        
        # check the item has no current issues
        
        
     &_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=?");
+    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 ) {
@@ -696,14 +660,21 @@ sub GetBiblioData {
     my ( $bibnum ) = @_;
     my $dbh = C4::Context->dbh;
 
-    my $query = "
-        SELECT * , biblioitems.notes AS bnotes, itemtypes.notforloan as bi_notforloan, biblio.notes
-        FROM biblio
+  #  my $query =  C4::Context->preference('item-level_itypes') ? 
+       #       " SELECT * , biblioitems.notes AS bnotes, biblio.notes
+    #          FROM biblio
+    #        LEFT JOIN biblioitems ON biblio.biblionumber = biblioitems.biblionumber
+    #          WHERE biblio.biblionumber = ?
+    #        AND biblioitems.biblionumber = biblio.biblionumber
+    #";
+       
+       my $query = " SELECT * , biblioitems.notes AS bnotes, itemtypes.notforloan as bi_notforloan, biblio.notes
+               FROM biblio
             LEFT JOIN biblioitems ON biblio.biblionumber = biblioitems.biblionumber
             LEFT JOIN itemtypes ON biblioitems.itemtype = itemtypes.itemtype
-        WHERE biblio.biblionumber = ?
-            AND biblioitems.biblionumber = biblio.biblionumber
-    ";
+               WHERE biblio.biblionumber = ?
+            AND biblioitems.biblionumber = biblio.biblionumber ";
+                
     my $sth = $dbh->prepare($query);
     $sth->execute($bibnum);
     my $data;
@@ -770,25 +741,25 @@ sub GetItemsInfo {
     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
-                 ";
+                 LEFT JOIN biblioitems ON biblioitems.biblioitemnumber = items.biblioitemnumber";
+       $query .=  (C4::Context->preference('item-level_itypes')) ?
+                                        " LEFT JOIN itemtypes on items.itype = itemtypes.itemtype "
+                                       : " LEFT JOIN itemtypes on biblioitems.itemtype = itemtypes.itemtype ";
+       $query .= "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 );
 
+    my $isth    = $dbh->prepare(
+        "SELECT issues.*,borrowers.cardnumber,borrowers.surname,borrowers.firstname,borrowers.branchcode as bcode
+        FROM   issues LEFT JOIN borrowers ON issues.borrowernumber=borrowers.borrowernumber
+        WHERE  itemnumber = ?
+            AND returndate IS NULL"
+       );
     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};
@@ -796,13 +767,18 @@ sub GetItemsInfo {
             $data->{surname}     = $idata->{surname};
             $data->{firstname}     = $idata->{firstname};
             $datedue                = format_date( $idata->{'date_due'} );
+           if (C4::Context->preference("IndependantBranches")){
+               my $userenv = C4::Context->userenv;
+               if ( ($userenv) && ( $userenv->{flags} != 1 ) ) { 
+                   $data->{'NOTSAMEBRANCH'} = 1 if ($idata->{'bcode'} ne $userenv->{branch});
+               }
+           }
         }
         if ( $datedue eq '' ) {
             #$datedue="Available";
             my ( $restype, $reserves ) =
               C4::Reserves::CheckReserves( $data->{'itemnumber'} );
             if ($restype) {
-
                 #$datedue=$restype;
                 $count_reserves = $restype;
             }
@@ -923,13 +899,22 @@ sub GetItemStatus {
     if ( $tag and $subfield ) {
         my $sth =
           $dbh->prepare(
-"select authorised_value from marc_subfield_structure where tagfield=? and tagsubfield=? and frameworkcode=?"
+                       "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"
+                               "SELECT authorised_value,lib
+                               FROM authorised_values 
+                               WHERE category=? 
+                               ORDER BY lib
+                               "
               );
             $authvalsth->execute($authorisedvaluecat);
             while ( my ( $authorisedvalue, $lib ) = $authvalsth->fetchrow ) {
@@ -1002,13 +987,20 @@ sub GetItemLocation {
     if ( $tag and $subfield ) {
         my $sth =
           $dbh->prepare(
-"select authorised_value from marc_subfield_structure where tagfield=? and tagsubfield=? and frameworkcode=?"
+                       "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"
+                               "SELECT authorised_value,lib
+                               FROM authorised_values
+                               WHERE category=?
+                               ORDER BY lib"
               );
             $authvalsth->execute($authorisedvaluecat);
             while ( my ( $authorisedvalue, $lib ) = $authvalsth->fetchrow ) {
@@ -1163,13 +1155,14 @@ that C<biblioitems.notes> is given as C<$itemdata-E<gt>{bnotes}>.
 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 $query = "SELECT *,biblioitems.notes AS bnotes
+               FROM biblio, biblioitems ";
+       unless(C4::Context->preference('item-level_itypes')) { 
+               $query .= "LEFT JOIN itemtypes on biblioitems.itemtype=itemtypes.itemtype ";
+       }        
+       $query .= " WHERE biblio.biblionumber = biblioitems.biblionumber 
+               AND biblioitemnumber = ? ";
+    my $sth       =  $dbh->prepare($query);
     my $data;
     $sth->execute($biblioitemnumber);
     $data = $sth->fetchrow_hashref;
@@ -1192,7 +1185,7 @@ sub GetItemnumberFromBarcode {
     my $dbh = C4::Context->dbh;
 
     my $rq =
-      $dbh->prepare("SELECT itemnumber from items where items.barcode=?");
+      $dbh->prepare("SELECT itemnumber FROM items WHERE items.barcode=?");
     $rq->execute($barcode);
     my ($result) = $rq->fetchrow;
     return ($result);
@@ -1211,7 +1204,7 @@ NOTE : This function has been copy/paste from C4/Biblio.pm from head before zebr
 sub GetBiblioItemByBiblioNumber {
     my ($biblionumber) = @_;
     my $dbh = C4::Context->dbh;
-    my $sth = $dbh->prepare("Select * from biblioitems where biblionumber = ?");
+    my $sth = $dbh->prepare("Select * FROM biblioitems WHERE biblionumber = ?");
     my $count = 0;
     my @results;
 
@@ -1229,9 +1222,9 @@ sub GetBiblioItemByBiblioNumber {
 
 =over 4
 
-$item = &GetBiblioFromItemNumber($itemnumber);
+$item = &GetBiblioFromItemNumber($itemnumber,$barcode);
 
-Looks up the item with the given itemnumber.
+Looks up the item with the given itemnumber. if undef, try the barcode.
 
 C<&itemnodata> returns a reference-to-hash whose keys are the fields
 from the C<biblio>, C<biblioitems>, and C<items> tables in the Koha
@@ -1243,16 +1236,22 @@ database.
 
 #'
 sub GetBiblioFromItemNumber {
-    my ( $itemnumber ) = @_;
+    my ( $itemnumber, $barcode ) = @_;
     my $dbh = C4::Context->dbh;
-    my $sth = $dbh->prepare(
-        "SELECT * FROM items 
-        LEFT JOIN biblio ON biblio.biblionumber = items.biblionumber
-        LEFT JOIN biblioitems ON biblioitems.biblioitemnumber = items.biblioitemnumber
-         WHERE items.itemnumber = ?"
-    );
-
-    $sth->execute($itemnumber);
+    my $sth;
+    if($itemnumber) {
+               $sth=$dbh->prepare(  "SELECT * FROM items 
+           LEFT JOIN biblio ON biblio.biblionumber = items.biblionumber
+           LEFT JOIN biblioitems ON biblioitems.biblioitemnumber = items.biblioitemnumber
+                WHERE items.itemnumber = ?") ; 
+       $sth->execute($itemnumber);
+       } else {
+               $sth=$dbh->prepare(  "SELECT * FROM items 
+           LEFT JOIN biblio ON biblio.biblionumber = items.biblionumber
+           LEFT JOIN biblioitems ON biblioitems.biblioitemnumber = items.biblioitemnumber
+                WHERE items.barcode = ?") ; 
+       $sth->execute($barcode);
+       }
     my $data = $sth->fetchrow_hashref;
     $sth->finish;
     return ($data);
@@ -1271,7 +1270,7 @@ sub GetBiblioFromItemNumber {
 sub GetBiblio {
     my ($biblionumber) = @_;
     my $dbh = C4::Context->dbh;
-    my $sth = $dbh->prepare("Select * from biblio where biblionumber = ?");
+    my $sth = $dbh->prepare("SELECT * FROM biblio WHERE biblionumber = ?");
     my $count = 0;
     my @results;
     $sth->execute($biblionumber);
@@ -1487,13 +1486,16 @@ sub GetMarcStructure {
     # check that framework exists
     $sth =
       $dbh->prepare(
-        "select count(*) from marc_tag_structure where frameworkcode=?");
+        "SELECT COUNT(*) FROM marc_tag_structure WHERE frameworkcode=?");
     $sth->execute($frameworkcode);
     my ($total) = $sth->fetchrow;
     $frameworkcode = "" unless ( $total > 0 );
     $sth =
       $dbh->prepare(
-"select tagfield,liblibrarian,libopac,mandatory,repeatable from marc_tag_structure where frameworkcode=? order by tagfield"
+               "SELECT tagfield,liblibrarian,libopac,mandatory,repeatable 
+               FROM marc_tag_structure 
+               WHERE frameworkcode=? 
+               ORDER BY tagfield"
       );
     $sth->execute($frameworkcode);
     my ( $liblibrarian, $libopac, $tag, $res, $tab, $mandatory, $repeatable );
@@ -1503,16 +1505,18 @@ sub GetMarcStructure {
     {
         $res->{$tag}->{lib} =
           ( $forlibrarian or !$libopac ) ? $liblibrarian : $libopac;
-          # why the hell do we need to explicitly decode utf8 ? 
-          # that's a good question, but we must do it...
-        $res->{$tab}->{tab}        = "";            # XXX
+        $res->{$tab}->{tab}        = "";
         $res->{$tag}->{mandatory}  = $mandatory;
         $res->{$tag}->{repeatable} = $repeatable;
     }
 
     $sth =
       $dbh->prepare(
-"select tagfield,tagsubfield,liblibrarian,libopac,tab, mandatory, repeatable,authorised_value,authtypecode,value_builder,kohafield,seealso,hidden,isurl,link,defaultvalue from marc_subfield_structure where frameworkcode=? order by tagfield,tagsubfield"
+                       "SELECT tagfield,tagsubfield,liblibrarian,libopac,tab,mandatory,repeatable,authorised_value,authtypecode,value_builder,kohafield,seealso,hidden,isurl,link,defaultvalue 
+                               FROM marc_subfield_structure 
+                       WHERE frameworkcode=? 
+                               ORDER BY tagfield,tagsubfield
+                       "
     );
     
     $sth->execute($frameworkcode);
@@ -1627,7 +1631,7 @@ sub GetMarcBiblio {
     my $biblionumber = shift;
     my $dbh          = C4::Context->dbh;
     my $sth          =
-      $dbh->prepare("select marcxml from biblioitems where biblionumber=? ");
+      $dbh->prepare("SELECT marcxml FROM biblioitems WHERE biblionumber=? ");
     $sth->execute($biblionumber);
      my ($marcxml) = $sth->fetchrow;
      MARC::File::XML->default_record_format(C4::Context->preference('marcflavour'));
@@ -1638,11 +1642,14 @@ sub GetMarcBiblio {
      $marcxml =~ s/\x0c//g;  
 #   warn $marcxml;
     my $record = MARC::Record->new();
-     
-      $record = eval {MARC::Record::new_from_xml( $marcxml, "utf8",C4::Context->preference('marcflavour'))} if ($marcxml);
-     if ($@) {warn $@;}
+    if ($marcxml) {
+        $record = eval {MARC::Record::new_from_xml( $marcxml, "utf8", C4::Context->preference('marcflavour'))};
+        if ($@) {warn $@;}
 #      $record = MARC::Record::new_from_usmarc( $marc) if $marc;
-    return $record;
+        return $record;
+    } else {
+        return undef;
+    }
 }
 
 =head2 GetXmlBiblio
@@ -1662,7 +1669,7 @@ sub GetXmlBiblio {
     my ( $biblionumber ) = @_;
     my $dbh = C4::Context->dbh;
     my $sth =
-      $dbh->prepare("select marcxml from biblioitems where biblionumber=? ");
+      $dbh->prepare("SELECT marcxml FROM biblioitems WHERE biblionumber=? ");
     $sth->execute($biblionumber);
     my ($marcxml) = $sth->fetchrow;
     return $marcxml;
@@ -1699,7 +1706,7 @@ sub GetAuthorisedValueDesc {
     if ( $category ne "" ) {
         my $sth =
           $dbh->prepare(
-            "select lib from authorised_values where category = ? and authorised_value = ?"
+            "SELECT lib FROM authorised_values WHERE category = ? AND authorised_value = ?"
           );
         $sth->execute( $category, $value );
         my $data = $sth->fetchrow_hashref;
@@ -1722,23 +1729,49 @@ Returns MARC::Record of the item passed in parameter.
 
 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;
+
+    # GetMarcItem has been revised so that it does the following:
+    #  1. Gets the item information from the items table.
+    #  2. Converts it to a MARC field for storage in the bib record.
+    #
+    # The previous behavior was:
+    #  1. Get the bib record.
+    #  2. Return the MARC tag corresponding to the item record.
+    #
+    # The difference is that one treats the items row as authoritative,
+    # while the other treats the MARC representation as authoritative
+    # under certain circumstances.
+    #
+    # FIXME - a big one
+    #
+    # As of 2007-11-27, this change hopefully does not introduce
+    # any bugs.  However, it does mean that for code that uses
+    # ModItemInMarconefield to update one subfield (corresponding to
+    # an items column) is now less efficient.
+    #
+    # The API needs to be shifted to the following:
+    #  1. User updates items record.
+    #  2. Linked bib is sent for indexing.
+    # 
+    # The missing step 1.5 is updating the item tag in the bib MARC record
+    # so that the indexes are updated.  Depending on performance considerations,
+    # this may ultimately mean of of the following:
+    #  a. MARC field for item is updated right away.
+    #  b. MARC field for item is updated only as part of indexing.
+    #  c. MARC field for item is never actually stored in bib record; instead
+    #     it is generated only when needed for indexing, item export, and
+    #     (maybe) OPAC display.
+    #
+
+    my $itemrecord = GetItem($itemnumber);
+
+    # Tack on 'items.' prefix to column names so that TransformKohaToMarc will work.
+    # Also, don't emit a subfield if the underlying field is blank.
+    my $mungeditem = { map {  $itemrecord->{$_} ne '' ? ("items.$_" => $itemrecord->{$_}) : ()  } keys %{ $itemrecord } };
+
+    my $itemmarc = TransformKohaToMarc($mungeditem);
+    return $itemmarc;
+
 }
 
 
@@ -1810,48 +1843,49 @@ sub GetMarcSubjects {
         $mintag = "600";
         $maxtag = "611";
     }
+       
+    my @marcsubjects;
+       my $subject = "";
+       my $subfield = "";
+       my $marcsubject;
 
-    my @marcsubjcts;
-
-    foreach my $field ( $record->fields ) {
+    foreach my $field ( $record->field('6..' )) {
         next unless $field->tag() >= $mintag && $field->tag() <= $maxtag;
+               my @subfields_loop;
         my @subfields = $field->subfields();
-        my $link = "su:";
-        my $label;
-        my $flag = 0;
-        my $authoritysep=C4::Context->preference("authoritysep");
-        for my $subject_subfield ( @subfields ) {
-            if (
-                $marcflavour ne 'MARC21'
-                and (
-                    ($subject_subfield->[0] eq '3') or
-                    ($subject_subfield->[0] eq '4') or
-                    ($subject_subfield->[0] eq '5')
-                )
-            )
-            {
-                next;
-            }
-            my $code = $subject_subfield->[0];
-            $label .= $subject_subfield->[1].$authoritysep unless ( $code == 9 );
-            $link  .= " and su-to:".$subject_subfield->[1]  unless ( $code == 9 );
-            if ( $code == 9 ) {
-                $link = "an:".$subject_subfield->[1];
-                $flag = 1;
-            }
-            elsif ( ! $flag ) {
-                $link =~ s/ and\ssu-to:$//;
+               my $counter = 0;
+               my @link_loop;
+               # if there is an authority link, build the link with an= subfield9
+               my $subfield9 = $field->subfield('9');
+               for my $subject_subfield (@subfields ) {
+                       # don't load unimarc subfields 3,4,5
+                       next if (($marcflavour eq "UNIMARC") and ($subject_subfield->[0] =~ (3|4|5) ) );
+                       my $code = $subject_subfield->[0];
+                       my $value = $subject_subfield->[1];
+                       my $linkvalue = $value;
+                       $linkvalue =~ s/(\(|\))//g;
+                       my $operator = " and " unless $counter==0;
+                       if ($subfield9) {
+                @link_loop = ({'limit' => 'an' ,link => "$subfield9" });
+            } else {
+                push @link_loop, {'limit' => 'su', link => $linkvalue, operator => $operator };
             }
-        }
-         $label =~ s/$authoritysep$//;
-        push @marcsubjcts,
-          {
-            label => $label,
-            link  => $link
-          }
-    }
-    return \@marcsubjcts;
-}    #end GetMarcSubjects
+                       my $separator = C4::Context->preference("authoritysep") unless $counter==0;
+                       # ignore $9
+                       push @subfields_loop, {code => $code, value => $value, link_loop => \@link_loop, separator => $separator} unless ($subject_subfield->[0] == 9 );
+                       # this needs to be added back in in a way that the template can expose it properly
+                       #if ( $code == 9 ) {
+            #    $link = "an:".$subject_subfield->[1];
+            #    $flag = 1;
+            #}
+                       $counter++;
+               }
+                
+               push @marcsubjects, { MARCSUBJECT_SUBFIELDS_LOOP => \@subfields_loop };
+        
+       }
+        return \@marcsubjects;
+}  #end getMARCsubjects
 
 =head2 GetMarcAuthors
 
@@ -1871,14 +1905,16 @@ sub GetMarcAuthors {
     # tagslib useful for UNIMARC author reponsabilities
     my $tagslib = &GetMarcStructure( 1, '' ); # FIXME : we don't have the framework available, we take the default framework. May be bugguy on some setups, will be usually correct.
     if ( $marcflavour eq "MARC21" ) {
-        $mintag = "100";
-        $maxtag = "111"; 
+        $mintag = "700";
+        $maxtag = "720"; 
     }
-    else {    # assume unimarc if not marc21
-        $mintag = "701";
+    elsif ( $marcflavour eq "UNIMARC" ) {    # assume unimarc if not marc21
+        $mintag = "700";
         $maxtag = "712";
     }
-
+       else {
+               return;
+       }
     my @marcauthors;
 
     foreach my $field ( $record->fields ) {
@@ -1886,31 +1922,14 @@ sub GetMarcAuthors {
         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++;
+                       #unimarc-specific line
+            next if ($marcflavour eq 'UNIMARC' and (($authors_subfield->[0] eq '3') or ($authors_subfield->[0] eq '5')));
             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 ).")";
+                       if ( $marcflavour eq 'UNIMARC' and ($authors_subfield->[0] eq '4')) {
+               $value = "(".GetAuthorisedValueDesc( $field->tag(), $authors_subfield->[0], $authors_subfield->[1], '', $tagslib ).")";
             } else {
                 $value        = $authors_subfield->[1];
             }
@@ -2044,7 +2063,7 @@ sub GetMarcSeries {
 sub GetFrameworkCode {
     my ( $biblionumber ) = @_;
     my $dbh = C4::Context->dbh;
-    my $sth = $dbh->prepare("select frameworkcode from biblio where biblionumber=?");
+    my $sth = $dbh->prepare("SELECT frameworkcode FROM biblio WHERE biblionumber=?");
     $sth->execute($biblionumber);
     my ($frameworkcode) = $sth->fetchrow;
     return $frameworkcode;
@@ -2099,7 +2118,7 @@ sub TransformKohaToMarc {
     my $dbh = C4::Context->dbh;
     my $sth =
     $dbh->prepare(
-        "select tagfield,tagsubfield from marc_subfield_structure where frameworkcode=? and kohafield=?"
+        "SELECT tagfield,tagsubfield FROM marc_subfield_structure WHERE frameworkcode=? AND kohafield=?"
     );
     my $record = MARC::Record->new();
     foreach (keys %{$hash}) {
@@ -2128,7 +2147,7 @@ sub TransformKohaToMarcOneField {
     if ( !defined $sth ) {
         my $dbh = C4::Context->dbh;
         $sth = $dbh->prepare(
-            "select tagfield,tagsubfield from marc_subfield_structure where frameworkcode=? and kohafield=?"
+            "SELECT tagfield,tagsubfield FROM marc_subfield_structure WHERE frameworkcode=? AND kohafield=?"
         );
     }
     $sth->execute( $frameworkcode, $kohafieldname );
@@ -2396,64 +2415,162 @@ sub TransformHtmlToMarc {
 =cut
 
 sub TransformMarcToKoha {
-    my ( $dbh, $record, $frameworkcode ) = @_;
-    
-    #  FIXME :: This query is unused..
-    #    my $sth =
-    #      $dbh->prepare(
-    #"select tagfield,tagsubfield from marc_subfield_structure where frameworkcode=? and kohafield=?"
-    #      );
-    
+    my ( $dbh, $record, $frameworkcode, $table ) = @_;
+
     my $result;
-    my $sth2 = $dbh->prepare("SHOW COLUMNS from biblio");
-    $sth2->execute;
-    my $field;
-    while ( ($field) = $sth2->fetchrow ) {
-        $result =
-          &TransformMarcToKohaOneField( "biblio", $field, $record, $result,
-            $frameworkcode );
-    }
-    my $sth2 = $dbh->prepare("SHOW COLUMNS from biblioitems");
-    $sth2->execute;
-    while ( ($field) = $sth2->fetchrow ) {
-        if ( $field eq 'notes' ) { $field = 'bnotes'; }
-        $result =
-          &TransformMarcToKohaOneField( "biblioitems", $field, $record, $result,
-            $frameworkcode );
-    }
-    $sth2 = $dbh->prepare("SHOW COLUMNS from items");
-    $sth2->execute;
-    while ( ($field) = $sth2->fetchrow ) {
-        $result =
-          &TransformMarcToKohaOneField( "items", $field, $record, $result,
-            $frameworkcode );
-    }
 
-    #
-    # 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;
+    # sometimes we only want to return the items data
+    if ($table eq 'items') {
+        my $sth = $dbh->prepare("SHOW COLUMNS FROM items");
+        $sth->execute();
+        while ( (my $field) = $sth->fetchrow ) {
+            my $value = get_koha_field_from_marc($table,$field,$record,$frameworkcode);
+            my $key = _disambiguate($table, $field);
+            if ($result->{$key}) {
+                $result->{$key} .= " | " . $value;
+            } else {
+                $result->{$key} = $value;
+            }
+        }
+        return $result;
+    } else {
+        my @tables = ('biblio','biblioitems','items');
+        foreach my $table (@tables){
+            my $sth2 = $dbh->prepare("SHOW COLUMNS from $table");
+            $sth2->execute;
+            while (my ($field) = $sth2->fetchrow){
+                # FIXME use of _disambiguate is a temporary hack
+                # $result->{_disambiguate($table, $field)} = get_koha_field_from_marc($table,$field,$record,$frameworkcode);
+                my $value = get_koha_field_from_marc($table,$field,$record,$frameworkcode);
+                my $key = _disambiguate($table, $field);
+                if ($result->{$key}) {
+                    # FIXME - hack to not bring in duplicates of the same value
+                    unless (($key eq "biblionumber" or $key eq "biblioitemnumber") and ($value eq "")) {
+                        $result->{$key} .= " | " . $value;
+                    }
+                } else {
+                    $result->{$key} = $value;
+                }
+            }
+            $sth2->finish();
+        }
+        # 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;
+        }
+    
+        # 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;
     }
+}
 
-    # 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;
+
+=head2 _disambiguate
+
+=over 4
+
+$newkey = _disambiguate($table, $field);
+
+This is a temporary hack to distinguish between the
+following sets of columns when using TransformMarcToKoha.
+
+items.cn_source & biblioitems.cn_source
+items.cn_sort & biblioitems.cn_sort
+
+Columns that are currently NOT distinguished (FIXME
+due to lack of time to fully test) are:
+
+biblio.notes and biblioitems.notes
+biblionumber
+timestamp
+biblioitemnumber
+
+FIXME - this is necessary because prefixing each column
+name with the table name would require changing lots
+of code and templates, and exposing more of the DB
+structure than is good to the UI templates, particularly
+since biblio and bibloitems may well merge in a future
+version.  In the future, it would also be good to 
+separate DB access and UI presentation field names
+more.
+
+=back
+
+=cut
+
+sub _disambiguate {
+    my ($table, $column) = @_;
+    if ($column eq "cn_sort" or $column eq "cn_source") {
+        return $table . '.' . $column;
+    } else {
+        return $column;
     }
-    return $result;
+
 }
 
+=head2 get_koha_field_from_marc
+
+=over 4
+
+$result->{_disambiguate($table, $field)} = get_koha_field_from_marc($table,$field,$record,$frameworkcode);
+
+Internal function to map data from the MARC record to a specific non-MARC field.
+FIXME: this is meant to replace TransformMarcToKohaOneField after more testing.
+
+=back
+
+=cut
+
+sub get_koha_field_from_marc {
+    my ($koha_table,$koha_column,$record,$frameworkcode) = @_;
+    my ( $tagfield, $subfield ) = GetMarcFromKohaField( $koha_table.'.'.$koha_column, $frameworkcode );  
+    my $kohafield;
+    foreach my $field ( $record->field($tagfield) ) {
+        if ( $field->tag() < 10 ) {
+            if ( $kohafield ) {
+                $kohafield .= " | " . $field->data();
+            }
+            else {
+                $kohafield = $field->data();
+            }
+        }
+        else {
+            if ( $field->subfields ) {
+                my @subfields = $field->subfields();
+                foreach my $subfieldcount ( 0 .. $#subfields ) {
+                    if ( $subfields[$subfieldcount][0] eq $subfield ) {
+                        if ( $kohafield ) {
+                            $kohafield .=
+                              " | " . $subfields[$subfieldcount][1];
+                        }
+                        else {
+                            $kohafield =
+                              $subfields[$subfieldcount][1];
+                        }
+                    }
+                }
+            }
+        }
+    }
+    return $kohafield;
+} 
+
+
 =head2 TransformMarcToKohaOneField
 
 =over 4
@@ -2727,7 +2844,7 @@ sub PrepareItemrecordDisplay {
     my @loop_data;
     my $authorised_values_sth =
       $dbh->prepare(
-"select authorised_value,lib from authorised_values where category=? order by lib"
+"SELECT authorised_value,lib FROM authorised_values WHERE category=? ORDER BY lib"
       );
     foreach my $tag ( sort keys %{$tagslib} ) {
         my $previous_tag = '';
@@ -2789,7 +2906,7 @@ sub PrepareItemrecordDisplay {
                         {
                             my $sth =
                               $dbh->prepare(
-"select branchcode,branchname from branches where branchcode = ? order by branchname"
+                                                               "SELECT branchcode,branchname FROM branches WHERE branchcode = ? ORDER BY branchname"
                               );
                             $sth->execute( C4::Context->userenv->{branch} );
                             push @authorised_values, ""
@@ -2805,7 +2922,7 @@ sub PrepareItemrecordDisplay {
                         else {
                             my $sth =
                               $dbh->prepare(
-"select branchcode,branchname from branches order by branchname"
+                                                               "SELECT branchcode,branchname FROM branches ORDER BY branchname"
                               );
                             $sth->execute;
                             push @authorised_values, ""
@@ -2826,7 +2943,7 @@ sub PrepareItemrecordDisplay {
                     {
                         my $sth =
                           $dbh->prepare(
-"select itemtype,description from itemtypes order by description"
+                                                       "SELECT itemtype,description FROM itemtypes ORDER BY description"
                           );
                         $sth->execute;
                         push @authorised_values, ""
@@ -2989,7 +3106,7 @@ sub ModZebra {
         #
         # we use zebra, just fill zebraqueue table
         #
-        my $sth=$dbh->prepare("insert into zebraqueue  (biblio_auth_number ,server,operation) values(?,?,?)");
+        my $sth=$dbh->prepare("INSERT INTO zebraqueue  (biblio_auth_number,server,operation) VALUES(?,?,?)");
         $sth->execute($biblionumber,$server,$op);
         $sth->finish;
     }
@@ -3008,10 +3125,13 @@ sub GetNoZebraIndexes {
     my %indexes;
     foreach my $line (split /('|"),/,$index) {
         $line =~ /(.*)=>(.*)/;
+warn $line;
         my $index = substr($1,1); # get the index, don't forget to remove initial ' or "
         my $fields = $2;
-        $index =~ s/'|"| //g;
-        $fields =~ s/'|"| //g;
+        $index =~ s/'|"|\s//g;
+
+
+        $fields =~ s/'|"|\s//g;
         $indexes{$index}=$fields;
     }
     return %indexes;
@@ -3266,45 +3386,6 @@ sub MARCitemchange {
         }
     }
 }
-
-=head2 _koha_add_biblio
-
-=over 4
-
-_koha_add_biblio($dbh,$biblioitem);
-
-Internal function to add a biblio ($biblio is a hash with the values)
-
-=back
-
-=cut
-
-sub _koha_add_biblio {
-    my ( $dbh, $biblio, $frameworkcode ) = @_;
-    my $sth = $dbh->prepare("Select max(biblionumber) from biblio");
-    $sth->execute;
-    my $data         = $sth->fetchrow_arrayref;
-    my $biblionumber = $$data[0] + 1;
-    my $series       = 0;
-
-    if ( $biblio->{'seriestitle'} ) { $series = 1 }
-    $sth->finish;
-    $sth = $dbh->prepare(
-        "INSERT INTO biblio
-    SET datecreated=NOW(), 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 _find_value
 
 =over 4
@@ -3350,11 +3431,139 @@ sub _find_value {
     return ( $indicator, @result );
 }
 
+=head2 _koha_marc_update_bib_ids
+
+=over 4
+
+_koha_marc_update_bib_ids($record, $frameworkcode, $biblionumber, $biblioitemnumber);
+
+Internal function to add or update biblionumber and biblioitemnumber to
+the MARC XML.
+
+=back
+
+=cut
+
+sub _koha_marc_update_bib_ids {
+    my ($record, $frameworkcode, $biblionumber, $biblioitemnumber) = @_;
+
+    # we must add bibnum and bibitemnum in MARC::Record...
+    # we build the new field with biblionumber and biblioitemnumber
+    # we drop the original field
+    # we add the new builded field.
+    my ($biblio_tag, $biblio_subfield ) = GetMarcFromKohaField("biblio.biblionumber",$frameworkcode);
+    my ($biblioitem_tag, $biblioitem_subfield ) = GetMarcFromKohaField("biblioitems.biblioitemnumber",$frameworkcode);
+
+    if ($biblio_tag != $biblioitem_tag) {
+        # biblionumber & biblioitemnumber are in different fields
+
+        # deal with biblionumber
+        my ($new_field, $old_field);
+        if ($biblio_tag < 10) {
+            $new_field = MARC::Field->new( $biblio_tag, $biblionumber );
+        } else {
+            $new_field =
+              MARC::Field->new( $biblio_tag, '', '',
+                "$biblio_subfield" => $biblionumber );
+        }
+
+        # drop old field and create new one...
+        $old_field = $record->field($biblio_tag);
+        $record->delete_field($old_field);
+        $record->append_fields($new_field);
+
+        # deal with biblioitemnumber
+        if ($biblioitem_tag < 10) {
+            $new_field = MARC::Field->new( $biblioitem_tag, $biblioitemnumber, );
+        } else {
+            $new_field =
+              MARC::Field->new( $biblioitem_tag, '', '',
+                "$biblioitem_subfield" => $biblioitemnumber, );
+        }
+        # drop old field and create new one...
+        $old_field = $record->field($biblioitem_tag);
+        $record->delete_field($old_field);
+        $record->insert_fields_ordered($new_field);
+
+    } else {
+        # biblionumber & biblioitemnumber are in the same field (can't be <10 as fields <10 have only 1 value)
+        my $new_field = MARC::Field->new(
+            $biblio_tag, '', '',
+            "$biblio_subfield" => $biblionumber,
+            "$biblioitem_subfield" => $biblioitemnumber
+        );
+
+        # drop old field and create new one...
+        my $old_field = $record->field($biblio_tag);
+        $record->delete_field($old_field);
+        $record->insert_fields_ordered($new_field);
+    }
+}
+
+=head2 _koha_add_biblio
+
+=over 4
+
+my ($biblionumber,$error) = _koha_add_biblio($dbh,$biblioitem);
+
+Internal function to add a biblio ($biblio is a hash with the values)
+
+=back
+
+=cut
+
+sub _koha_add_biblio {
+    my ( $dbh, $biblio, $frameworkcode ) = @_;
+
+       my $error;
+
+       # set the series flag
+    my $serial = 0;
+    if ( $biblio->{'seriestitle'} ) { $serial = 1 };
+
+       my $query = 
+        "INSERT INTO biblio
+               SET frameworkcode = ?,
+                       author = ?,
+                       title = ?,
+                       unititle =?,
+                       notes = ?,
+                       serial = ?,
+                       seriestitle = ?,
+                       copyrightdate = ?,
+                       datecreated=NOW(),
+                       abstract = ?
+               ";
+    my $sth = $dbh->prepare($query);
+    $sth->execute(
+               $frameworkcode,
+        $biblio->{'author'},
+        $biblio->{'title'},
+               $biblio->{'unititle'},
+        $biblio->{'notes'},
+               $serial,
+        $biblio->{'seriestitle'},
+               $biblio->{'copyrightdate'},
+        $biblio->{'abstract'}
+    );
+
+    my $biblionumber = $dbh->{'mysql_insertid'};
+       if ( $dbh->errstr ) {
+               $error.="ERROR in _koha_add_biblio $query".$dbh->errstr;
+        warn $error;
+    }
+
+    $sth->finish();
+       #warn "LEAVING _koha_add_biblio: ".$biblionumber."\n";
+    return ($biblionumber,$error);
+}
+
 =head2 _koha_modify_biblio
 
 =over 4
 
-$biblionumber = _koha_modify_biblio($dbh,$biblio);
+my ($biblionumber,$error) == _koha_modify_biblio($dbh,$biblio,$frameworkcode);
+
 Internal function for updating the biblio table
 
 =back
@@ -3362,117 +3571,141 @@ Internal function for updating the biblio table
 =cut
 
 sub _koha_modify_biblio {
-    my ( $dbh, $biblio ) = @_;
-    # FIXME: this code could be made more portable by not hard-coding
-    #        the values that are supposed to be in biblio table
-    my $query = qq{
+    my ( $dbh, $biblio, $frameworkcode ) = @_;
+       my $error;
+
+    my $query = "
         UPDATE biblio
-        SET    title = ?,
-               author = ?,
-               abstract = ?,
-               copyrightdate = ?,
-               seriestitle = ?,
-               serial = ?,
-               unititle = ?,
-               notes = ?
+        SET    frameworkcode = ?,
+                          author = ?,
+                          title = ?,
+                          unititle = ?,
+                          notes = ?,
+                          serial = ?,
+                          seriestitle = ?,
+                          copyrightdate = ?,
+               abstract = ?
         WHERE  biblionumber = ?
-    };
+               "
+       ;
     my $sth = $dbh->prepare($query);
     
     $sth->execute(
-        $biblio->{'title'},
+               $frameworkcode,
         $biblio->{'author'},
-        $biblio->{'abstract'},
-        $biblio->{'copyrightdate'},
-        $biblio->{'seriestitle'},
-        $biblio->{'serial'},
+        $biblio->{'title'},
         $biblio->{'unititle'},
         $biblio->{'notes'},
+        $biblio->{'serial'},
+        $biblio->{'seriestitle'},
+        $biblio->{'copyrightdate'},
+               $biblio->{'abstract'},
         $biblio->{'biblionumber'}
     ) if $biblio->{'biblionumber'};
-    
-    warn $sth->err if $sth->err;
-    warn "BIG ERROR :: No biblionumber for $biblio->{title}" if $biblio->{biblionumber} !~ /\d+/; # if it is not a number
-    return ( $biblio->{'biblionumber'} );
+
+    if ( $dbh->errstr || !$biblio->{'biblionumber'} ) {
+               $error.="ERROR in _koha_modify_biblio $query".$dbh->errstr;
+        warn $error;
+    }
+    return ( $biblio->{'biblionumber'},$error );
 }
 
-=head2 _koha_modify_biblioitem
+=head2 _koha_modify_biblioitem_nonmarc
 
 =over 4
 
-_koha_modify_biblioitem( $dbh, $biblioitem );
+my ($biblioitemnumber,$error) = _koha_modify_biblioitem_nonmarc( $dbh, $biblioitem );
+
+Updates biblioitems row except for marc and marcxml, which should be changed
+via ModBiblioMarc
 
 =back
 
 =cut
 
-sub _koha_modify_biblioitem {
+sub _koha_modify_biblioitem_nonmarc {
     my ( $dbh, $biblioitem ) = @_;
-    my $query;
-##Recalculate LC in case it changed --TG
-
-    $biblioitem->{'itemtype'}      = $dbh->quote( $biblioitem->{'itemtype'} );
-    $biblioitem->{'url'}           = $dbh->quote( $biblioitem->{'url'} );
-    $biblioitem->{'isbn'}          = $dbh->quote( $biblioitem->{'isbn'} );
-    $biblioitem->{'issn'}          = $dbh->quote( $biblioitem->{'issn'} );
-    $biblioitem->{'publishercode'} =
-      $dbh->quote( $biblioitem->{'publishercode'} );
-    $biblioitem->{'publicationyear'} =
-      $dbh->quote( $biblioitem->{'publicationyear'} );
-    $biblioitem->{'classification'} =
-      $dbh->quote( $biblioitem->{'classification'} );
-    $biblioitem->{'dewey'}        = $dbh->quote( $biblioitem->{'dewey'} );
-    $biblioitem->{'subclass'}     = $dbh->quote( $biblioitem->{'subclass'} );
-    $biblioitem->{'illus'}        = $dbh->quote( $biblioitem->{'illus'} );
-    $biblioitem->{'pages'}        = $dbh->quote( $biblioitem->{'pages'} );
-    $biblioitem->{'volumeddesc'}  = $dbh->quote( $biblioitem->{'volumeddesc'} );
-    $biblioitem->{'bnotes'}       = $dbh->quote( $biblioitem->{'bnotes'} );
-    $biblioitem->{'size'}         = $dbh->quote( $biblioitem->{'size'} );
-    $biblioitem->{'place'}        = $dbh->quote( $biblioitem->{'place'} );
-    $biblioitem->{'collectiontitle'}        = $dbh->quote( $biblioitem->{'collectiontitle'} );
-    $biblioitem->{'collectionissn'}         = $dbh->quote( $biblioitem->{'collectionissn'} );
-    $biblioitem->{'collectionvolume'}       = $dbh->quote( $biblioitem->{'collectionvolume'} );
-    $biblioitem->{'editionstatement'}       = $dbh->quote( $biblioitem->{'editionstatement'} );
-    $biblioitem->{'editionresponsibility'}  = $dbh->quote( $biblioitem->{'editionresponsibility'} );
-    $biblioitem->{'ccode'}        = $dbh->quote( $biblioitem->{'ccode'} );
-    $biblioitem->{'biblionumber'} =
-      $dbh->quote( $biblioitem->{'biblionumber'} );
-
-    $query = "UPDATE biblioitems SET
-        itemtype        = $biblioitem->{'itemtype'},
-        url             = $biblioitem->{'url'},
-        isbn            = $biblioitem->{'isbn'},
-        issn            = $biblioitem->{'issn'},
-        publishercode   = $biblioitem->{'publishercode'},
-        publicationyear = $biblioitem->{'publicationyear'},
-        classification  = $biblioitem->{'classification'},
-        dewey           = $biblioitem->{'dewey'},
-        subclass        = $biblioitem->{'subclass'},
-        illus           = $biblioitem->{'illus'},
-        pages           = $biblioitem->{'pages'},
-        volumeddesc     = $biblioitem->{'volumeddesc'},
-        notes           = $biblioitem->{'bnotes'},
-        size            = $biblioitem->{'size'},
-        place           = $biblioitem->{'place'},
-        collectiontitle = $biblioitem->{'collectiontitle'},
-        collectionissn  = $biblioitem->{'collectionissn'},
-        collectionvolume= $biblioitem->{'collectionvolume'},
-        editionstatement= $biblioitem->{'editionstatement'},
-        editionresponsibility= $biblioitem->{'editionresponsibility'},
-        ccode           = $biblioitem->{'ccode'}
-        where biblionumber = $biblioitem->{'biblionumber'}";
-
-    $dbh->do($query);
+       my $error;
+
+       # re-calculate the cn_sort, it may have changed
+       my ($cn_sort) = GetClassSort($biblioitem->{'biblioitems.cn_source'}, $biblioitem->{'cn_class'}, $biblioitem->{'cn_item'} );
+
+       my $query = 
+       "UPDATE biblioitems 
+       SET biblionumber        = ?,
+               volume                  = ?,
+               number                  = ?,
+        itemtype        = ?,
+        isbn            = ?,
+        issn            = ?,
+               publicationyear = ?,
+        publishercode   = ?,
+               volumedate      = ?,
+               volumedesc      = ?,
+               collectiontitle = ?,
+               collectionissn  = ?,
+               collectionvolume= ?,
+               editionstatement= ?,
+               editionresponsibility = ?,
+               illus                   = ?,
+               pages                   = ?,
+               notes                   = ?,
+               size                    = ?,
+               place                   = ?,
+               lccn                    = ?,
+               url                     = ?,
+        cn_source              = ?,
+        cn_class        = ?,
+        cn_item                = ?,
+               cn_suffix       = ?,
+               cn_sort         = ?,
+               totalissues     = ?
+        where biblioitemnumber = ?
+               ";
+       my $sth = $dbh->prepare($query);
+       $sth->execute(
+               $biblioitem->{'biblionumber'},
+               $biblioitem->{'volume'},
+               $biblioitem->{'number'},
+               $biblioitem->{'itemtype'},
+               $biblioitem->{'isbn'},
+               $biblioitem->{'issn'},
+               $biblioitem->{'publicationyear'},
+               $biblioitem->{'publishercode'},
+               $biblioitem->{'volumedate'},
+               $biblioitem->{'volumedesc'},
+               $biblioitem->{'collectiontitle'},
+               $biblioitem->{'collectionissn'},
+               $biblioitem->{'collectionvolume'},
+               $biblioitem->{'editionstatement'},
+               $biblioitem->{'editionresponsibility'},
+               $biblioitem->{'illus'},
+               $biblioitem->{'pages'},
+               $biblioitem->{'bnotes'},
+               $biblioitem->{'size'},
+               $biblioitem->{'place'},
+               $biblioitem->{'lccn'},
+               $biblioitem->{'url'},
+               $biblioitem->{'biblioitems.cn_source'},
+               $biblioitem->{'cn_class'},
+               $biblioitem->{'cn_item'},
+               $biblioitem->{'cn_suffix'},
+               $cn_sort,
+               $biblioitem->{'totalissues'},
+               $biblioitem->{'biblioitemnumber'}
+       );
     if ( $dbh->errstr ) {
-        warn "ERROR in _koha_modify_biblioitem $query";
+               $error.="ERROR in _koha_modify_biblioitem_nonmarc $query".$dbh->errstr;
+        warn $error;
     }
+       return ($biblioitem->{'biblioitemnumber'},$error);
 }
 
 =head2 _koha_add_biblioitem
 
 =over 4
 
-_koha_add_biblioitem( $dbh, $biblioitem );
+my ($biblioitemnumber,$error) = _koha_add_biblioitem( $dbh, $biblioitem );
 
 Internal function to add a biblioitem
 
@@ -3482,66 +3715,87 @@ Internal function to add a biblioitem
 
 sub _koha_add_biblioitem {
     my ( $dbh, $biblioitem ) = @_;
-
-    #  my $dbh   = C4Connect;
-    my $sth = $dbh->prepare("SELECT max(biblioitemnumber) FROM biblioitems");
-    my $data;
-    my $bibitemnum;
-
-    $sth->execute;
-    $data       = $sth->fetchrow_arrayref;
-    $bibitemnum = $$data[0] + 1;
-
-    $sth->finish;
-
-    $sth = $dbh->prepare(
-        "INSERT INTO biblioitems SET
-            biblioitemnumber = ?, biblionumber    = ?,
-            volume           = ?, number          = ?,
-            classification   = ?, itemtype        = ?,
-            url              = ?, isbn            = ?,
-            issn             = ?, dewey           = ?,
-            subclass         = ?, publicationyear = ?,
-            publishercode    = ?, volumedate      = ?,
-            volumeddesc      = ?, illus           = ?,
-            pages            = ?, notes           = ?,
-            size             = ?, lccn            = ?,
-            marc             = ?, lcsort          = ?,
-            place            = ?, ccode           = ?,
-            collectiontitle  = ?, collectionissn  = ?,
-            collectionvolume = ?, editionstatement= ?,
-            editionresponsibility= ?
-          "
-    );
-    my ($lcsort) =
-      calculatelc( $biblioitem->{'classification'} )
-      . $biblioitem->{'subclass'};
+       my $error;
+
+       my ($cn_sort) = GetClassSort($biblioitem->{'biblioitems.cn_source'}, $biblioitem->{'cn_class'}, $biblioitem->{'cn_item'} );
+    my $query =
+    "INSERT INTO biblioitems SET
+        biblionumber    = ?,
+        volume          = ?,
+        number          = ?,
+        itemtype        = ?,
+        isbn            = ?,
+        issn            = ?,
+        publicationyear = ?,
+        publishercode   = ?,
+        volumedate      = ?,
+        volumedesc      = ?,
+        collectiontitle = ?,
+        collectionissn  = ?,
+        collectionvolume= ?,
+        editionstatement= ?,
+        editionresponsibility = ?,
+        illus           = ?,
+        pages           = ?,
+        notes           = ?,
+        size            = ?,
+        place           = ?,
+        lccn            = ?,
+        marc            = ?,
+        url             = ?,
+        cn_source       = ?,
+        cn_class        = ?,
+        cn_item         = ?,
+        cn_suffix       = ?,
+        cn_sort         = ?,
+        totalissues     = ?
+        ";
+       my $sth = $dbh->prepare($query);
     $sth->execute(
-        $bibitemnum,                     $biblioitem->{'biblionumber'},
-        $biblioitem->{'volume'},         $biblioitem->{'number'},
-        $biblioitem->{'classification'}, $biblioitem->{'itemtype'},
-        $biblioitem->{'url'},            $biblioitem->{'isbn'},
-        $biblioitem->{'issn'},           $biblioitem->{'dewey'},
-        $biblioitem->{'subclass'},       $biblioitem->{'publicationyear'},
-        $biblioitem->{'publishercode'},  $biblioitem->{'volumedate'},
-        $biblioitem->{'volumeddesc'},    $biblioitem->{'illus'},
-        $biblioitem->{'pages'},          $biblioitem->{'bnotes'},
-        $biblioitem->{'size'},           $biblioitem->{'lccn'},
-        $biblioitem->{'marc'},           $biblioitem->{'place'},
-        $lcsort,                         $biblioitem->{'ccode'},
-        $biblioitem->{'collectiontitle'},$biblioitem->{'collectionissn'},
-        $biblioitem->{'collectionvolume'},$biblioitem->{'editionstatement'},
-        $biblioitem->{'editionresponsibility'}
+        $biblioitem->{'biblionumber'},
+        $biblioitem->{'volume'},
+        $biblioitem->{'number'},
+        $biblioitem->{'itemtype'},
+        $biblioitem->{'isbn'},
+        $biblioitem->{'issn'},
+        $biblioitem->{'publicationyear'},
+        $biblioitem->{'publishercode'},
+        $biblioitem->{'volumedate'},
+        $biblioitem->{'volumedesc'},
+        $biblioitem->{'collectiontitle'},
+        $biblioitem->{'collectionissn'},
+        $biblioitem->{'collectionvolume'},
+        $biblioitem->{'editionstatement'},
+        $biblioitem->{'editionresponsibility'},
+        $biblioitem->{'illus'},
+        $biblioitem->{'pages'},
+        $biblioitem->{'bnotes'},
+        $biblioitem->{'size'},
+        $biblioitem->{'place'},
+        $biblioitem->{'lccn'},
+        $biblioitem->{'marc'},
+        $biblioitem->{'url'},
+        $biblioitem->{'biblioitems.cn_source'},
+        $biblioitem->{'cn_class'},
+        $biblioitem->{'cn_item'},
+        $biblioitem->{'cn_suffix'},
+        $cn_sort,
+        $biblioitem->{'totalissues'}
     );
-    $sth->finish;
-    return ($bibitemnum);
+    my $bibitemnum = $dbh->{'mysql_insertid'};
+    if ( $dbh->errstr ) {
+               $error.="ERROR in _koha_add_biblioitem $query".$dbh->errstr;
+               warn $error;
+    }
+    $sth->finish();
+    return ($bibitemnum,$error);
 }
 
 =head2 _koha_new_items
 
 =over 4
 
-_koha_new_items( $dbh, $item, $barcode );
+my ($itemnumber,$error) = _koha_new_items( $dbh, $item, $barcode );
 
 =back
 
@@ -3549,94 +3803,88 @@ _koha_new_items( $dbh, $item, $barcode );
 
 sub _koha_new_items {
     my ( $dbh, $item, $barcode ) = @_;
+       my $error;
 
-    #  my $dbh   = C4Connect;
-    my $sth = $dbh->prepare("Select max(itemnumber) from items");
-    my $data;
-    my $itemnumber;
-    my $error = "";
-
-    $sth->execute;
-    $data       = $sth->fetchrow_hashref;
-    $itemnumber = $data->{'max(itemnumber)'} + 1;
-    $sth->finish;
-## Now calculate lccalnumber
-    my ($cutterextra) = itemcalculator(
-        $dbh,
-        $item->{'biblioitemnumber'},
-        $item->{'itemcallnumber'}
-    );
-
-# FIXME the "notforloan" field seems to be named "loan" in some places. workaround bugfix.
-    if ( $item->{'loan'} ) {
-        $item->{'notforloan'} = $item->{'loan'};
-    }
+    my ($items_cn_sort) = GetClassSort($item->{'items.cn_source'}, $item->{'itemcallnumber'}, "");
 
     # 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'},
+               my $today = C4::Dates->new();    
+               $item->{'dateaccessioned'} =  $today->output("iso"); #TODO: check time issues
+       }
+       my $query = 
+           "INSERT INTO items SET
+                       biblionumber            = ?,
+            biblioitemnumber    = ?,
+                       barcode                 = ?,
+                       dateaccessioned         = ?,
+                       booksellerid        = ?,
+            homebranch          = ?,
+            price               = ?,
+                       replacementprice        = ?,
+            replacementpricedate = NOW(),
+                       datelastborrowed        = ?,
+                       datelastseen            = NOW(),
+                       stack                   = ?,
+                       notforloan                      = ?,
+                       damaged                         = ?,
+            itemlost           = ?,
+                       wthdrawn                = ?,
+                       itemcallnumber          = ?,
+                       restricted                      = ?,
+                       itemnotes                       = ?,
+                       holdingbranch           = ?,
+            paidfor            = ?,
+                       location                        = ?,
+                       onloan                          = ?,
+                       issues                          = ?,
+                       renewals                        = ?,
+                       reserves                        = ?,
+                       cn_source                       = ?,
+                       cn_sort                         = ?,
+                       ccode                           = ?,
+                       itype                           = ?,
+                       materials                       = ?,
+                       uri                             = ?
+          ";
+    my $sth = $dbh->prepare($query);
+       $sth->execute(
+                       $item->{'biblionumber'},
                        $item->{'biblioitemnumber'},
-            $barcode,                   $item->{'booksellerid'},
-            $item->{'homebranch'},      $item->{'holdingbranch'},
-            $item->{'price'},           $item->{'replacementprice'},
+            $barcode,
+                       $item->{'dateaccessioned'},
+                       $item->{'booksellerid'},
+            $item->{'homebranch'},
+            $item->{'price'},
+                       $item->{'replacementprice'},
+                       $item->{datelastborrowed},
                        $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
-        );
-    }
+                       $item->{'notforloan'},
+                       $item->{'damaged'},
+            $item->{'itemlost'},
+                       $item->{'wthdrawn'},
+                       $item->{'itemcallnumber'},
+            $item->{'restricted'},
+                       $item->{'itemnotes'},
+                       $item->{'holdingbranch'},
+                       $item->{'paidfor'},
+                       $item->{'location'},
+                       $item->{'onloan'},
+                       $item->{'issues'},
+                       $item->{'renewals'},
+                       $item->{'reserves'},
+                       $item->{'items.cn_source'},
+                       $items_cn_sort,
+                       $item->{'ccode'},
+                       $item->{'itype'},
+                       $item->{'materials'},
+                       $item->{'uri'},
+    );
+    my $itemnumber = $dbh->{'mysql_insertid'};
     if ( defined $sth->errstr ) {
-        $error .= $sth->errstr;
+        $error.="ERROR in _koha_new_items $query".$sth->errstr;
     }
+       $sth->finish();
     return ( $itemnumber, $error );
 }
 
@@ -3644,75 +3892,36 @@ sub _koha_new_items {
 
 =over 4
 
-_koha_modify_item( $dbh, $item, $op );
+my ($itemnumber,$error) =_koha_modify_item( $dbh, $item, $op );
 
 =back
 
 =cut
 
 sub _koha_modify_item {
-    my ( $dbh, $item, $op ) = @_;
-    $item->{'itemnum'} = $item->{'itemnumber'} unless $item->{'itemnum'};
+    my ( $dbh, $item ) = @_;
+       my $error;
 
-    # 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'} );
-
-    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/;
+       # calculate items.cn_sort
+    $item->{'cn_sort'} = GetClassSort($item->{'items.cn_source'}, $item->{'itemcallnumber'}, "");
+
+    my $query = "UPDATE items SET ";
+       my @bind;
+       for my $key ( keys %$item ) {
+               $query.="$key=?,";
+               push @bind, $item->{$key};
     }
+       $query =~ s/,$//;
+    $query .= " WHERE itemnumber=?";
+    push @bind, $item->{'itemnumber'};
     my $sth = $dbh->prepare($query);
     $sth->execute(@bind);
-    $sth->finish;
+    if ( $dbh->errstr ) {
+        $error.="ERROR in _koha_modify_item $query".$dbh->errstr;
+        warn $error;
+    }
+    $sth->finish();
+       return ($item->{'itemnumber'},$error);
 }
 
 =head2 _koha_delete_biblio
@@ -3832,115 +4041,31 @@ Internal function to delete an item record from the koha tables
 sub _koha_delete_item {
     my ( $dbh, $itemnum ) = @_;
 
-    my $sth = $dbh->prepare("select * from items where itemnumber=?");
+       # save the deleted item to deleteditems table
+    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 $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} );
+    foreach my $key ( keys %$data ) {
+        $query .= "$key = ?,";
+        push( @bind, $data->{$key} );
     }
     $query =~ s/\,$//;
-
-    #  print $query;
     $sth = $dbh->prepare($query);
     $sth->execute(@bind);
-    $sth->finish;
-    $sth = $dbh->prepare("Delete from items where itemnumber=?");
+    $sth->finish();
+
+       # delete from items table
+    $sth = $dbh->prepare("DELETE FROM items WHERE itemnumber=?");
     $sth->execute($itemnum);
-    $sth->finish;
+    $sth->finish();
+       return undef;
 }
 
 =head1 UNEXPORTED FUNCTIONS
 
-=over 4
-
-=head2 calculatelc
-
-$lc = calculatelc($classification);
-
-=back
-
-=cut
-
-sub calculatelc {
-    my ($classification) = @_;
-    $classification =~ s/^\s+|\s+$//g;
-    my $i = 0;
-    my $lc2;
-    my $lc1;
-
-    for ( $i = 0 ; $i < length($classification) ; $i++ ) {
-        my $c = ( substr( $classification, $i, 1 ) );
-        if ( $c ge '0' && $c le '9' ) {
-
-            $lc2 = substr( $classification, $i );
-            last;
-        }
-        else {
-            $lc1 .= substr( $classification, $i, 1 );
-
-        }
-    }    #while
-
-    my $other = length($lc1);
-    if ( !$lc1 ) {
-        $other = 0;
-    }
-
-    my $extras;
-    if ( $other < 4 ) {
-        for ( 1 .. ( 4 - $other ) ) {
-            $extras .= "0";
-        }
-    }
-    $lc1 .= $extras;
-    $lc2 =~ s/^ //g;
-
-    $lc2 =~ s/ //g;
-    $extras = "";
-    ##Find the decimal part of $lc2
-    my $pos = index( $lc2, "." );
-    if ( $pos < 0 ) { $pos = length($lc2); }
-    if ( $pos >= 0 && $pos < 5 ) {
-        ##Pad lc2 with zeros to create a 5digit decimal needed in marc record to sort as numeric
-
-        for ( 1 .. ( 5 - $pos ) ) {
-            $extras .= "0";
-        }
-    }
-    $lc2 = $extras . $lc2;
-    return ( $lc1 . $lc2 );
-}
-
-=head2 itemcalculator
-
-=over 4
-
-$cutterextra = itemcalculator( $dbh, $biblioitem, $callnumber );
-
-=back
-
-=cut
-
-sub itemcalculator {
-    my ( $dbh, $biblioitem, $callnumber ) = @_;
-    my $sth =
-      $dbh->prepare(
-"select classification, subclass from biblioitems where biblioitemnumber=?"
-      );
-
-    $sth->execute($biblioitem);
-    my ( $classification, $subclass ) = $sth->fetchrow;
-    my $all         = $classification . " " . $subclass;
-    my $total       = length($all);
-    my $cutterextra = substr( $callnumber, $total - 1 );
-
-    return $cutterextra;
-}
-
 =head2 ModBiblioMarc
 
     &ModBiblioMarc($newrec,$biblionumber,$frameworkcode);
@@ -3988,7 +4113,7 @@ sub ModBiblioMarc {
     ModZebra($biblionumber,"specialUpdate","biblioserver",$record);
     $sth =
       $dbh->prepare(
-        "update biblioitems set marc=?,marcxml=?  where biblionumber=?");
+        "UPDATE biblioitems SET marc=?,marcxml=? WHERE biblionumber=?");
     $sth->execute( $record->as_usmarc(), $record->as_xml_record($encoding),
         $biblionumber );
     $sth->finish;
@@ -4144,9 +4269,9 @@ this function return count of item with $biblionumber
 sub GetItemsCount {
     my ( $biblionumber ) = @_;
     my $dbh = C4::Context->dbh;
-    my $query = qq|SELECT count(*)
+    my $query = "SELECT count(*)
                  FROM  items 
-                 WHERE biblionumber=?|;
+                 WHERE biblionumber=?";
     my $sth = $dbh->prepare($query);
     $sth->execute($biblionumber);
     my $count = $sth->fetchrow;  
@@ -4169,167 +4294,3 @@ Paul POULAIN paul.poulain@free.fr
 Joshua Ferraro jmf@liblime.com
 
 =cut
-
-# $Id$
-# $Log$
-# Revision 1.221  2007/07/31 16:01:11  toins
-# Some new functions.
-# TransformHTMLtoMarc rewrited.
-#
-# Revision 1.220  2007/07/20 15:43:16  hdl
-# Bug Fixing GetMarcSubjects.
-# Links parameters were mixed.
-#
-# Revision 1.218  2007/07/19 07:40:08  hdl
-# Adding selection by location for inventory
-#
-# Revision 1.217  2007/07/03 13:47:44  tipaul
-# fixing some display bugs (itemtype not properly returned and a html table bug that makes items appear strangely
-#
-# Revision 1.216  2007/07/03 09:40:58  tipaul
-# return itemtype description properly
-#
-# Revision 1.215  2007/07/03 09:33:05  tipaul
-# if you just replace su by a space in subjects, you'll replace jesus by je s, which is strange for users. this fix solves the problem and introduces authoritysep systempref as separator of subfields, for a better identification of where the authority starts and end
-#
-# Revision 1.214  2007/07/02 09:13:22  tipaul
-# unimarc bugfix : the encoding is in field 100 in UNIMARC. when TransformHTMLtoXML on an item, you must not automatically add a 100 field in items, otherwise there will be 2 100 fields in the biblio, which is wrong
-#
-# Revision 1.213  2007/06/25 15:01:45  tipaul
-# bugfixes on unimarc 100 handling (the field used for encoding)
-#
-# Revision 1.212  2007/06/15 13:44:44  tipaul
-# some fixes (and only fixes)
-#
-# Revision 1.211  2007/06/15 09:40:06  toins
-# do not get $3 $4 and $5 on GetMarcSubjects GetMarcAuthors on unimarc flavour.
-#
-# Revision 1.210  2007/06/13 13:03:34  toins
-# removing warn compilation.
-#
-# Revision 1.209  2007/05/23 16:19:40  tipaul
-# various bugfixes (minor) and french translation updated
-#
-# Revision 1.208  2007/05/22 09:13:54  tipaul
-# Bugfixes & improvements (various and minor) :
-# - updating templates to have tmpl_process3.pl running without any errors
-# - adding a drupal-like css for prog templates (with 3 small images)
-# - fixing some bugs in circulation & other scripts
-# - updating french translation
-# - fixing some typos in templates
-#
-# Revision 1.207  2007/05/22 08:51:19  hdl
-# Changing GetMarcStructure signature.
-# Deleting first parameter $dbh
-#
-# Revision 1.206  2007/05/21 08:44:17  btoumi
-# add security when u delete biblio :
-# u must delete linked items before delete biblio
-#
-# Revision 1.205  2007/05/11 16:04:03  btoumi
-# bug fix:
-# problem in  displayed label link  with subject in detail.tmpl
-# ex: label random => rdom
-#
-# Revision 1.204  2007/05/10 14:45:15  tipaul
-# Koha NoZebra :
-# - support for authorities
-# - some bugfixes in ordering and "CCL" parsing
-# - support for authorities <=> biblios walking
-#
-# Seems I can do what I want now, so I consider its done, except for bugfixes that will be needed i m sure !
-#
-# Revision 1.203  2007/05/03 15:16:02  tipaul
-# BUGFIX for : NoZebra
-# - NoZebra features : seems they work fine now (adding, modifying, deleting)
-# - Biblio edition major bugfix : before this commit editing a biblio resulted in an item removal in marcxml field
-#
-# Revision 1.202  2007/05/02 16:44:31  tipaul
-# NoZebra SQL index management :
-# * adding 3 subs in Biblio.pm
-# - GetNoZebraIndexes, that get the index structure in a new systempreference (added with this commit)
-# - _DelBiblioNoZebra, that retrieve all index entries for a biblio and remove in a variable the biblio reference
-# - _AddBiblioNoZebra, that add index entries for a biblio.
-# Note that the 2 _Add and _Del subs work only in a hash variable, to speed up things in case of a modif (ie : delete+add). The effective SQL update is done in the ModZebra sub (that existed before, and dealed with zebra index).
-# I think the code has to be more deeply tested, but it works at least partially.
-#
-# Revision 1.201  2007/04/27 14:00:49  hdl
-# Removing $dbh from GetMarcFromKohaField (dbh is not used in this function.)
-#
-# Revision 1.200  2007/04/25 16:26:42  tipaul
-# Koha 3.0 nozebra 1st commit : the script misc/migration_tools/rebuild_nozebra.pl build the nozebra table, and, if you set NoZebra to Yes, queries will be done through zebra. TODO :
-# - add nozebra table management on biblio editing
-# - the index table content is hardcoded. I still have to add some specific systempref to let the library update it
-# - manage pagination (next/previous)
-# - manage facets
-# WHAT works :
-# - NZgetRecords : has exactly the same API & returns as zebra getQuery, except that some parameters are unused
-# - search & sort works quite good
-# - CQL parser is better that what I thought I could do : title="harry and sally" and publicationyear>2000 not itemtype=LIVR should work fine
-#
-# Revision 1.199  2007/04/24 09:07:53  tipaul
-# moving dotransfer to Biblio.pm::ModItemTransfer + some CheckReserves fixes
-#
-# Revision 1.198  2007/04/23 15:21:17  tipaul
-# renaming currenttransfers to transferstoreceive
-#
-# Revision 1.197  2007/04/18 17:00:14  tipaul
-# removing all useless %env / $env
-#
-# Revision 1.196  2007/04/17 08:48:00  tipaul
-# circulation cleaning continued: bufixing
-#
-# Revision 1.195  2007/04/04 16:46:22  tipaul
-# HUGE COMMIT : code cleaning circulation.
-#
-# some stuff to do, i'll write a mail on koha-devel NOW !
-#
-# Revision 1.194  2007/03/30 12:00:42  tipaul
-# why the hell do we need to explicitly utf8 decode this string ? I really don't know, but it seems it's mandatory, otherwise, tag descriptions are not properly encoded...
-#
-# Revision 1.193  2007/03/29 16:45:53  tipaul
-# Code cleaning of Biblio.pm (continued)
-#
-# All subs have be cleaned :
-# - removed useless
-# - merged some
-# - reordering Biblio.pm completly
-# - using only naming conventions
-#
-# Seems to have broken nothing, but it still has to be heavily tested.
-# Note that Biblio.pm is now much more efficient than previously & probably more reliable as well.
-#
-# Revision 1.192  2007/03/29 13:30:31  tipaul
-# Code cleaning :
-# == Biblio.pm cleaning (useless) ==
-# * some sub declaration dropped
-# * removed modbiblio sub
-# * removed moditem sub
-# * removed newitems. It was used only in finishrecieve. Replaced by a TransformKohaToMarc+AddItem, that is better.
-# * removed MARCkoha2marcItem
-# * removed MARCdelsubfield declaration
-# * removed MARCkoha2marcBiblio
-#
-# == Biblio.pm cleaning (naming conventions) ==
-# * MARCgettagslib renamed to GetMarcStructure
-# * MARCgetitems renamed to GetMarcItem
-# * MARCfind_frameworkcode renamed to GetFrameworkCode
-# * MARCmarc2koha renamed to TransformMarcToKoha
-# * MARChtml2marc renamed to TransformHtmlToMarc
-# * MARChtml2xml renamed to TranformeHtmlToXml
-# * zebraop renamed to ModZebra
-#
-# == MARC=OFF ==
-# * removing MARC=OFF related scripts (in cataloguing directory)
-# * removed checkitems (function related to MARC=off feature, that is completly broken in head. If someone want to reintroduce it, hard work coming...)
-# * removed getitemsbybiblioitem (used only by MARC=OFF scripts, that is removed as well)
-#
-# Revision 1.191  2007/03/29 09:42:13  tipaul
-# adding default value new feature into cataloguing. The system (definition) part has already been added by toins
-#
-# Revision 1.190  2007/03/29 08:45:19  hdl
-# Deleting ignore_errors(1) pour MARC::Charset
-#
-# Revision 1.189  2007/03/28 10:39:16  hdl
-# removing $dbh as a parameter in AuthoritiesMarc functions
-# And reporting all differences into the scripts taht relies on those functions.