Bug Fixing.
[koha.git] / C4 / BookShelves.pm
index b5144bd..ce8810c 100755 (executable)
@@ -24,13 +24,12 @@ package C4::BookShelves;
 
 use strict;
 require Exporter;
-use DBI;
 use C4::Context;
-use C4::Circulation::Circ2;
+use C4::Circulation;
 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 ); };
 
 =head1 NAME
 
@@ -52,14 +51,22 @@ items to and from bookshelves.
 
 =cut
 
-@ISA = qw(Exporter);
-@EXPORT = qw(&GetShelfList &GetShelfContents &AddToShelf &RemoveFromShelf &AddShelf &RemoveShelf);
+@ISA    = qw(Exporter);
+@EXPORT = qw(
+        &GetShelves &GetShelfContents &GetShelf
+
+        &AddToShelf &AddToShelfFromBiblio &AddShelf
+
+        &ModShelf
+        &ShelfPossibleAction
+        &DelFromShelf &DelShelf
+);
 
 my $dbh = C4::Context->dbh;
 
-=item GetShelfList
+=item GetShelves
 
-  $shelflist = &GetShelfList();
+  $shelflist = &GetShelves($owner, $mincategory);
   ($shelfnumber, $shelfhash) = each %{$shelflist};
 
 Looks up the virtual bookshelves, and returns a summary. C<$shelflist>
@@ -67,6 +74,9 @@ is a reference-to-hash. The keys are the bookshelf numbers
 (C<$shelfnumber>, above), and the values (C<$shelfhash>, above) are
 themselves references-to-hash, with the following keys:
 
+C<mincategory> : 2 if the list is for "look". 3 if the list is for "Select bookshelf for adding a book".
+bookshelves of the owner are always selected, whatever the category
+
 =over 4
 
 =item C<$shelfhash-E<gt>{shelfname}>
@@ -80,210 +90,322 @@ The number of books on that bookshelf.
 =back
 
 =cut
+
 #'
 # FIXME - Wouldn't it be more intuitive to return a list, rather than
 # a reference-to-hash? The shelf number can be just another key in the
 # hash.
-sub GetShelfList {
-    # FIXME - These two database queries can be combined into one:
-    #  SELECT          bookshelf.shelfnumber, bookshelf.shelfname,
-    #                  count(shelfcontents.itemnumber)
-    #  FROM            bookshelf
-    #  LEFT JOIN       shelfcontents
-    #  ON              bookshelf.shelfnumber = shelfcontents.shelfnumber
-    #  GROUP BY        bookshelf.shelfnumber
-    my $sth=$dbh->prepare("select shelfnumber,shelfname from bookshelf");
-    $sth->execute;
+
+sub GetShelves {
+    my ( $owner, $mincategory ) = @_;
+
+    my $query = qq(
+        SELECT bookshelf.shelfnumber, bookshelf.shelfname,owner,surname,firstname,bookshelf.category,
+               count(shelfcontents.itemnumber) as count
+        FROM   bookshelf
+            LEFT JOIN   shelfcontents ON bookshelf.shelfnumber = shelfcontents.shelfnumber
+            LEFT JOIN   borrowers ON bookshelf.owner = borrowers.borrowernumber
+        WHERE  owner=? OR category>=?
+        GROUP BY bookshelf.shelfnumber
+        ORDER BY bookshelf.category, bookshelf.shelfname, borrowers.firstname, borrowers.surname
+    );
+    my $sth = $dbh->prepare($query);
+    $sth->execute( $owner, $mincategory );
     my %shelflist;
-    while (my ($shelfnumber, $shelfname) = $sth->fetchrow) {
-       my $sti=$dbh->prepare("select count(*) from shelfcontents where shelfnumber=$shelfnumber");
-               # FIXME - Should there be an "order by" in here somewhere?
-       $sti->execute;
-       my ($count) = $sti->fetchrow;
-       $shelflist{$shelfnumber}->{'shelfname'}=$shelfname;
-       $shelflist{$shelfnumber}->{'count'}=$count;
+    while (
+        my (
+            $shelfnumber, $shelfname, $owner, $surname,
+            $firstname,   $category,  $count
+        )
+        = $sth->fetchrow
+      )
+    {
+        $shelflist{$shelfnumber}->{'shelfname'} = $shelfname;
+        $shelflist{$shelfnumber}->{'count'}     = $count;
+        $shelflist{$shelfnumber}->{'category'}  = $category;
+        $shelflist{$shelfnumber}->{'owner'}     = $owner;
+        $shelflist{$shelfnumber}->{'surname'}     = $surname;
+        $shelflist{$shelfnumber}->{'firstname'}   = $firstname;
     }
-    return(\%shelflist);
+    return ( \%shelflist );
+}
+
+=item GetShef
+
+  (shelfnumber,shelfname,owner,category) = &GetShelf($shelfnumber);
+
+Looks up information about the contents of virtual bookshelf number
+C<$shelfnumber>
+
+Returns the database's information on 'bookshelf' table.
+
+=cut
+
+sub GetShelf {
+    my ($shelfnumber) = @_;
+    my $query = qq(
+        SELECT shelfnumber,shelfname,owner,category
+        FROM   bookshelf
+        WHERE  shelfnumber=?
+    );
+    my $sth = $dbh->prepare($query);
+    $sth->execute($shelfnumber);
+    return $sth->fetchrow;
 }
 
 =item GetShelfContents
 
-  $itemlist = &GetShelfContents($env, $shelfnumber);
+  $itemlist = &GetShelfContents($shelfnumber);
 
 Looks up information about the contents of virtual bookshelf number
 C<$shelfnumber>.
 
 Returns a reference-to-array, whose elements are references-to-hash,
-as returned by C<&getiteminformation>.
-
-I don't know what C<$env> is.
+as returned by C<C4::Biblio::GetBiblioFromItemNumber>.
 
 =cut
+
 #'
 sub GetShelfContents {
-    my ($env, $shelfnumber) = @_;
+    my ( $shelfnumber ) = @_;
     my @itemlist;
-    my $sth=$dbh->prepare("select itemnumber from shelfcontents where shelfnumber=$shelfnumber order by itemnumber");
-    $sth->execute;
-    while (my ($itemnumber) = $sth->fetchrow) {
-       my ($item) = getiteminformation($env, $itemnumber, 0);
-       push (@itemlist, $item);
+    my $query =
+       " SELECT itemnumber
+         FROM   shelfcontents
+         WHERE  shelfnumber=?
+         ORDER BY itemnumber
+       ";
+    my $sth = $dbh->prepare($query);
+    $sth->execute($shelfnumber);
+    my $sth2 = $dbh->prepare("
+        SELECT biblio.*,biblioitems.* FROM items 
+            LEFT JOIN biblio on items.biblionumber=biblio.biblionumber
+            LEFT JOIN biblioitems on items.biblionumber=biblioitems.biblionumber
+        WHERE items.itemnumber=?"
+    );
+    while ( my ($itemnumber) = $sth->fetchrow ) {
+        $sth2->execute($itemnumber);
+        my $item = $sth2->fetchrow_hashref;
+        $item->{'itemnumber'}=$itemnumber;
+        push( @itemlist, $item );
+    }
+    return ( \@itemlist );
+}
+
+=item AddShelf
+
+  $shelfnumber = &AddShelf( $shelfname, $owner, $category);
+
+Creates a new virtual bookshelf with name C<$shelfname>, owner C<$owner> and category
+C<$category>.
+
+Returns a code to know what's happen.
+    * -1 : if this bookshelf already exist.
+    * $shelfnumber : if success.
+
+=cut
+
+sub AddShelf {
+    my ( $shelfname, $owner, $category ) = @_;
+    my $query = qq(
+        SELECT *
+        FROM   bookshelf
+        WHERE  shelfname=? AND owner=?
+    );
+    my $sth = $dbh->prepare($query);
+    $sth->execute($shelfname,$owner);
+    if ( $sth->rows ) {
+        return (-1);
+    }
+    else {
+        my $query = qq(
+            INSERT INTO bookshelf
+                (shelfname,owner,category)
+            VALUES (?,?,?)
+        );
+        $sth = $dbh->prepare($query);
+        $sth->execute( $shelfname, $owner, $category );
+        my $shelfnumber = $dbh->{'mysql_insertid'};
+        return ($shelfnumber);
     }
-    return (\@itemlist);
-               # FIXME - Wouldn't it be more intuitive to return a list,
-               # rather than a reference-to-list?
 }
 
 =item AddToShelf
 
-  &AddToShelf($env, $itemnumber, $shelfnumber);
+  &AddToShelf($itemnumber, $shelfnumber);
 
 Adds item number C<$itemnumber> to virtual bookshelf number
 C<$shelfnumber>, unless that item is already on that shelf.
 
-C<$env> is ignored.
-
 =cut
+
 #'
 sub AddToShelf {
-    my ($env, $itemnumber, $shelfnumber) = @_;
-    my $sth=$dbh->prepare("select * from shelfcontents
-       where shelfnumber=? and itemnumber=?");
-
-    $sth->execute($shelfnumber, $itemnumber);
-    if ($sth->rows) {
-# already on shelf
-    } else {
-       $sth=$dbh->prepare("insert into shelfcontents
-               (shelfnumber, itemnumber, flags) values (?, ?, 0)");
-
-                       # FIXME - The default for 'flags' is NULL.
-                       # Why set it to 0?
-       $sth->execute($shelfnumber, $itemnumber);
+    my ( $itemnumber, $shelfnumber ) = @_;
+    return unless $itemnumber;
+    my $query = qq(
+        SELECT *
+        FROM   shelfcontents
+        WHERE  shelfnumber=? AND itemnumber=?
+    );
+    my $sth = $dbh->prepare($query);
+
+    $sth->execute( $shelfnumber, $itemnumber );
+    unless ( $sth->rows ) {
+        # already on shelf
+        my $query = qq(
+            INSERT INTO shelfcontents
+                (shelfnumber, itemnumber, flags)
+            VALUES
+                (?, ?, 0)
+        );
+        $sth = $dbh->prepare($query);
+        $sth->execute( $shelfnumber, $itemnumber );
     }
 }
 
-=item RemoveFromShelf
+=item AddToShelfFromBiblio
+    &AddToShelfFromBiblio($biblionumber, $shelfnumber)
 
-  &RemoveFromShelf($env, $itemnumber, $shelfnumber);
+    this function allow to add a book into the shelf number $shelfnumber
+    from biblionumber.
 
-Removes item number C<$itemnumber> from virtual bookshelf number
-C<$shelfnumber>. If the item wasn't on that bookshelf to begin with,
-nothing happens.
+=cut
+
+sub AddToShelfFromBiblio {
+    my ( $biblionumber, $shelfnumber ) = @_;
+    return unless $biblionumber;
+    my $query = qq(
+        SELECT itemnumber
+        FROM   items
+        WHERE  biblionumber=?
+    );
+    my $sth = $dbh->prepare($query);
+    $sth->execute($biblionumber);
+    my ($itemnumber) = $sth->fetchrow;
+    $query = qq(
+        SELECT *
+        FROM   shelfcontents
+        WHERE  shelfnumber=? AND itemnumber=?
+    );
+    $sth = $dbh->prepare($query);
+    $sth->execute( $shelfnumber, $itemnumber );
+    unless ( $sth->rows ) {
+        # "already on shelf";
+        my $query =qq(
+            INSERT INTO shelfcontents
+                (shelfnumber, itemnumber, flags)
+            VALUES
+                (?, ?, 0)
+        );
+        $sth = $dbh->prepare($query);
+        $sth->execute( $shelfnumber, $itemnumber );
+    }
+}
+
+=item ModShelf
+
+ModShelf($shelfnumber, $shelfname, $owner, $category )
 
-C<$env> is ignored.
+Modify the value into bookshelf table with values given on input arg.
 
 =cut
-#'
-sub RemoveFromShelf {
-    my ($env, $itemnumber, $shelfnumber) = @_;
-    my $sth=$dbh->prepare("delete from shelfcontents where shelfnumber=$shelfnumber and itemnumber=$itemnumber");
-    $sth->execute;
+
+sub ModShelf {
+    my ( $shelfnumber, $shelfname, $owner, $category ) = @_;
+    my $query = qq(
+        UPDATE bookshelf
+        SET    shelfname=?,owner=?,category=?
+        WHERE  shelfnumber=?
+    );
+    my $sth = $dbh->prepare($query);
+    $sth->execute( $shelfname, $owner, $category, $shelfnumber );
 }
 
-=item AddShelf
+=item DelShelf
 
-  ($status, $msg) = &AddShelf($env, $shelfname);
+  ($status) = &DelShelf($shelfnumber);
 
-Creates a new virtual bookshelf with name C<$shelfname>.
+Deletes virtual bookshelf number C<$shelfnumber>. The bookshelf must
+be empty.
 
 Returns a two-element array, where C<$status> is 0 if the operation
 was successful, or non-zero otherwise. C<$msg> is "Done" in case of
 success, or an error message giving the reason for failure.
 
-C<$env> is ignored.
+=cut
+
+
+=item ShelfPossibleAction
+
+ShelfPossibleAction($loggedinuser, $shelfnumber, $action);
+
+C<$loggedinuser,$shelfnumber,$action>
+
+$action can be "view" or "manage".
+
+Returns 1 if the user can do the $action in the $shelfnumber shelf.
+Returns 0 otherwise.
 
 =cut
-#'
-# FIXME - Perhaps this could/should return the number of the new bookshelf
-# as well?
-sub AddShelf {
-    my ($env, $shelfname) = @_;
-    my $q_shelfname=$dbh->quote($shelfname);
-    my $sth=$dbh->prepare("select * from bookshelf where shelfname=$q_shelfname");
-    $sth->execute;
-    if ($sth->rows) {
-       return(1, "Shelf \"$shelfname\" already exists");
-    } else {
-       $sth=$dbh->prepare("insert into bookshelf (shelfname) values ($q_shelfname)");
-       $sth->execute;
-       return (0, "Done");
-    }
+
+sub ShelfPossibleAction {
+    my ( $user, $shelfnumber, $action ) = @_;
+    my $query = qq(
+        SELECT owner,category
+        FROM   bookshelf
+        WHERE  shelfnumber=?
+    );
+    my $sth = $dbh->prepare($query);
+    $sth->execute($shelfnumber);
+    my ( $owner, $category ) = $sth->fetchrow;
+    return 1 if (($category >= 3 or $owner eq $user) && $action eq 'manage' );
+    return 1 if (($category >= 2 or $owner eq $user) && $action eq 'view' );
+    return 0;
 }
 
-=item RemoveShelf
+=item DelFromShelf
 
-  ($status, $msg) = &RemoveShelf($env, $shelfnumber);
+  &DelFromShelf( $itemnumber, $shelfnumber);
 
-Deletes virtual bookshelf number C<$shelfnumber>. The bookshelf must
-be empty.
+Removes item number C<$itemnumber> from virtual bookshelf number
+C<$shelfnumber>. If the item wasn't on that bookshelf to begin with,
+nothing happens.
 
-Returns a two-element array, where C<$status> is 0 if the operation
-was successful, or non-zero otherwise. C<$msg> is "Done" in case of
-success, or an error message giving the reason for failure.
+=cut
 
-C<$env> is ignored.
+#'
+sub DelFromShelf {
+    my ( $itemnumber, $shelfnumber ) = @_;
+    my $query = qq(
+        DELETE FROM shelfcontents
+        WHERE  shelfnumber=? AND itemnumber=?
+    );
+    my $sth = $dbh->prepare($query);
+    $sth->execute( $shelfnumber, $itemnumber );
+}
+
+=head2 DelShelf
+
+  $Number = DelShelf($shelfnumber);
+
+    this function delete the shelf number, and all of it's content
 
 =cut
+
 #'
-sub RemoveShelf {
-    my ($env, $shelfnumber) = @_;
-    my $sth=$dbh->prepare("select count(*) from shelfcontents where shelfnumber=$shelfnumber");
-    $sth->execute;
-    my ($count)=$sth->fetchrow;
-    if ($count) {
-       return (1, "Shelf has $count items on it.  Please remove all items before deleting this shelf.");
-    } else {
-       $sth=$dbh->prepare("delete from bookshelf where shelfnumber=$shelfnumber");
-       $sth->execute;
-       return (0, "Done");
-    }
+sub DelShelf {
+    my ( $shelfnumber ) = @_;
+        my $sth = $dbh->prepare("DELETE FROM bookshelf WHERE shelfnumber=?");
+        $sth->execute($shelfnumber);
+        return 0;
 }
 
-END { }       # module clean-up code here (global destructor)
+END { }    # module clean-up code here (global destructor)
 
 1;
 
-#
-# $Log$
-# Revision 1.10  2003/02/05 10:05:02  acli
-# Converted a few SQL statements to use ? to fix a few strange SQL errors
-# Noted correct tab size
-#
-# Revision 1.9  2002/10/13 08:29:18  arensb
-# Deleted unused variables.
-# Removed trailing whitespace.
-#
-# Revision 1.8  2002/10/10 04:32:44  arensb
-# Simplified references.
-#
-# Revision 1.7  2002/10/05 09:50:10  arensb
-# Merged with arensb-context branch: use C4::Context->dbh instead of
-# &C4Connect, and generally prefer C4::Context over C4::Database.
-#
-# Revision 1.6.2.1  2002/10/04 02:24:43  arensb
-# Use C4::Connect instead of C4::Database, C4::Connect->dbh instead
-# C4Connect.
-#
-# Revision 1.6  2002/09/23 13:50:30  arensb
-# Fixed missing bit in POD.
-#
-# Revision 1.5  2002/09/22 17:29:17  arensb
-# Added POD.
-# Added some FIXME comments.
-# Removed useless trailing whitespace.
-#
-# Revision 1.4  2002/08/14 18:12:51  tonnesen
-# Added copyright statement to all .pl and .pm files
-#
-# Revision 1.3  2002/07/02 17:48:06  tonnesen
-# Merged in updates from rel-1-2
-#
-# Revision 1.2.2.1  2002/06/26 20:46:48  tonnesen
-# Inserting some changes I made locally a while ago.
-#
-#
-
 __END__
 
 =back
@@ -297,3 +419,53 @@ Koha Developement team <info@koha.org>
 C4::Circulation::Circ2(3)
 
 =cut
+
+#
+# $Log$
+# Revision 1.21  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.20  2007/03/09 14:31:47  tipaul
+# rel_3_0 moved to HEAD
+#
+# Revision 1.15.8.10  2007/01/25 13:18:15  tipaul
+# checking that a bookshelf with the same name AND OWNER does not exist before creating it
+#
+# Revision 1.15.8.9  2006/12/15 17:37:52  toins
+# removing a function used only once.
+#
+# Revision 1.15.8.8  2006/12/14 17:22:55  toins
+# bookshelves work perfectly with mod_perl and are cleaned.
+#
+# Revision 1.15.8.7  2006/12/13 19:46:41  hdl
+# Some bug fixing.
+#
+# Revision 1.15.8.6  2006/12/11 17:10:06  toins
+# fixing some bugs on bookshelves.
+#
+# Revision 1.15.8.5  2006/12/07 16:45:43  toins
+# removing warn compilation. (perl -wc)
+#
+# Revision 1.15.8.4  2006/11/23 09:05:01  tipaul
+# enable removal of a bookshelf even if there are items inside
+#
+# Revision 1.15.8.3  2006/10/30 09:50:20  tipaul
+# removing getiteminformations (using direct SQL, as we are in a .pm, so it's "legal")
+#
+# Revision 1.15.8.2  2006/08/31 16:03:52  toins
+# Add Pod to DelShelf
+#
+# Revision 1.15.8.1  2006/08/30 15:59:14  toins
+# Code cleaned according to coding guide lines.
+#
+# Revision 1.15  2004/12/16 11:30:58  tipaul
+# adding bookshelf features :
+# * create bookshelf on the fly
+# * modify a bookshelf name & status
+#
+# Revision 1.14  2004/12/15 17:28:23  tipaul
+# adding bookshelf features :
+# * create bookshelf on the fly
+# * modify a bookshelf (this being not finished, will commit the rest soon)