[Koha-patches] [PATCH 1/1] Bug 7919 : Display of values depending on the connexion librairy

Jonathan Druart jonathan.druart at biblibre.com
Fri Apr 6 12:19:10 CEST 2012


In a librairies network, we would like to declare specific values just
for one (or more) librairy.
Here we implement the ability to associate categories, patron attributes
types and/or authorised_values with librairies (branches).

This patch adds 3 new association tables:
- categories_branches ( association table between categories and branches )
- authorised_values_branches ( association table between
  authorised_values and branches )
- borrower_attribute_types_branches (association table between
  borrower_attribute_types and branches )

Plan test:
  - Create (or modify) categories, patron attributes and
    authorised_values and link it with one (or more) library.
  - Set one of these librairies
  - Go to one of the multiple pages where this specific value must be displayed
    and check that it does appear.
  - Set a librairy not concerned.
  - Check on the same pages this value is doest not appear.

A page list:
cataloguing/addbiblio.pl
cataloguing/additems.pl
members/members-home.pl
members/memberentry.pl
acqui/neworderempty.pl
tools/import_borrowers.pl
and others :)

Please say me if filters don't work on some pages.
---
 C4/Budgets.pm                                      |   23 +++++--
 C4/Category.pm                                     |   25 +++++--
 C4/Input.pm                                        |   67 ++++++++++++--------
 C4/Koha.pm                                         |   54 +++++++++++-----
 C4/Members.pm                                      |   63 ++++++++++++------
 C4/Members/AttributeTypes.pm                       |   62 +++++++++++++++++-
 C4/Members/Attributes.pm                           |    2 +
 admin/authorised_values.pl                         |   58 ++++++++++++++++-
 admin/categorie.pl                                 |   46 ++++++++++++--
 admin/patron-attr-types.pl                         |   36 +++++++++-
 cataloguing/addbiblio.pl                           |   21 ++++--
 cataloguing/additem.pl                             |   13 ++--
 installer/data/mysql/kohastructure.sql             |   38 +++++++++++
 installer/data/mysql/updatedatabase.pl             |   17 +++++
 .../prog/en/modules/admin/authorised_values.tt     |   20 ++++++-
 .../prog/en/modules/admin/categorie.tt             |   21 ++++++-
 .../prog/en/modules/admin/patron-attr-types.tt     |   19 ++++++
 members/member.pl                                  |    4 +-
 tools/batchMod.pl                                  |   12 +++-
 tools/import_borrowers.pl                          |    2 +-
 20 files changed, 489 insertions(+), 114 deletions(-)

diff --git a/C4/Budgets.pm b/C4/Budgets.pm
index 7c867e0..8399b5b 100644
--- a/C4/Budgets.pm
+++ b/C4/Budgets.pm
@@ -354,12 +354,25 @@ sub GetBudgetAuthCats  {
 # -------------------------------------------------------------------
 sub GetAuthvalueDropbox {
     my ( $authcat, $default ) = @_;
+    my $branch_limit = C4::Context->userenv ? C4::Context->userenv->{"branch"} : "";
     my $dbh = C4::Context->dbh;
-    my $sth = $dbh->prepare(
-        'SELECT authorised_value,lib FROM authorised_values
-        WHERE category = ? ORDER BY lib'
-    );
-    $sth->execute( $authcat );
+
+    my $query = qq{
+        SELECT *
+        FROM authorised_values
+    };
+    $query .= qq{
+          LEFT JOIN authorised_values_branches ON ( id = av_id )
+    } if $branch_limit;
+    $query .= qq{
+        WHERE category = ?
+    };
+    $query .= " AND ( branchcode = ? OR branchcode IS NULL )" if $branch_limit;
+    $query .= " GROUP BY lib ORDER BY category, lib, lib_opac";
+    my $sth = $dbh->prepare($query);
+    $sth->execute( $authcat, $branch_limit ? $branch_limit : () );
+
+
     my $option_list = [];
     my @authorised_values = ( q{} );
     while (my ($value, $lib) = $sth->fetchrow_array) {
diff --git a/C4/Category.pm b/C4/Category.pm
index 8536128..f12b52f 100644
--- a/C4/Category.pm
+++ b/C4/Category.pm
@@ -71,13 +71,24 @@ C<description>.
 =cut
 
 sub all {
-    my $class = shift;
-    map {
-        utf8::encode($_->{description});
-        $class->new($_);
-    } @{C4::Context->dbh->selectall_arrayref(
-        "SELECT * FROM categories ORDER BY description", { Slice => {} }
-    )};
+    my ( $class ) = @_;
+    my $branch_limit = C4::Context->userenv ? C4::Context->userenv->{"branch"} : "";
+    my $dbh = C4::Context->dbh;
+    # The categories table is small enough for
+    # `SELECT *` to be harmless.
+    my $query = "SELECT * FROM categories";
+    $query .= qq{
+        LEFT JOIN categories_branches ON categories_branches.categorycode = categories.categorycode
+        WHERE categories_branches.branchcode = ? OR categories_branches.branchcode IS NULL
+    } if $branch_limit;
+    $query .= " ORDER BY description";
+    return map { $class->new($_) } @{
+        $dbh->selectall_arrayref(
+            $query,
+            { Slice => {} },
+            $branch_limit ? $branch_limit : ()
+        )
+    };
 }
 
 
diff --git a/C4/Input.pm b/C4/Input.pm
index 2ee07f3..6ba5ceb 100644
--- a/C4/Input.pm
+++ b/C4/Input.pm
@@ -119,33 +119,48 @@ Returns NULL if no authorised values found
 =cut
 
 sub buildCGIsort {
-	my ($name,$input_name,$data) = @_;
-	my $dbh=C4::Context->dbh;
-	my $query=qq{SELECT * FROM authorised_values WHERE category=? order by lib};
-	my $sth=$dbh->prepare($query);
-	$sth->execute($name);
-	my $CGISort;
-	if ($sth->rows>0){
-		my @values;
-		my %labels;
-
-		for (my $i =0;$i<$sth->rows;$i++){
-			my $results = $sth->fetchrow_hashref;
-			push @values, $results->{authorised_value};
-			$labels{$results->{authorised_value}}=$results->{lib};
-		}
-		$CGISort= CGI::scrolling_list(
-					-name => $input_name,
-					-id =>   $input_name,
-					-values => \@values,
-					-labels => \%labels,
-					-default=> $data,
-					-size => 1,
-					-multiple => 0);
-	}
-	$sth->finish;
-	return $CGISort;
+    my ( $name, $input_name, $data ) = @_;
+    my $branch_limit = C4::Context->userenv ? C4::Context->userenv->{"branch"} : "";
+
+    my $dbh=C4::Context->dbh;
+    my $query = qq{
+        SELECT *
+        FROM authorised_values
+    };
+    $query .= qq{
+          LEFT JOIN authorised_values_branches ON ( id = av_id )
+    } if $branch_limit;
+    $query .= qq{
+        WHERE category = ?
+    };
+    $query .= qq{ AND ( branchcode = ? OR branchcode IS NULL )} if $branch_limit;
+    $query .= qq{ GROUP BY lib ORDER BY lib};
+
+    my $sth=$dbh->prepare($query);
+    $sth->execute( $branch_limit ? $branch_limit : (), $name );
+    my $CGISort;
+    if ($sth->rows>0){
+        my @values;
+        my %labels;
+
+        for (my $i =0;$i<$sth->rows;$i++){
+            my $results = $sth->fetchrow_hashref;
+            push @values, $results->{authorised_value};
+            $labels{$results->{authorised_value}}=$results->{lib};
+        }
+        $CGISort= CGI::scrolling_list(
+                    -name => $input_name,
+                    -id =>   $input_name,
+                    -values => \@values,
+                    -labels => \%labels,
+                    -default=> $data,
+                    -size => 1,
+                    -multiple => 0);
+    }
+    $sth->finish;
+    return $CGISort;
 }
+
 END { }       # module clean-up code here (global destructor)
 
 1;
diff --git a/C4/Koha.pm b/C4/Koha.pm
index 0192989..050e8ae 100644
--- a/C4/Koha.pm
+++ b/C4/Koha.pm
@@ -1007,25 +1007,45 @@ C<$opac> If set to a true value, displays OPAC descriptions rather than normal o
 =cut
 
 sub GetAuthorisedValues {
-    my ($category,$selected,$opac) = @_;
-	my @results;
+    my ( $category, $selected, $opac ) = @_;
+    my $branch_limit = C4::Context->userenv ? C4::Context->userenv->{"branch"} : "";
+    my @results;
     my $dbh      = C4::Context->dbh;
-    my $query    = "SELECT * FROM authorised_values";
-    $query .= " WHERE category = '" . $category . "'" if $category;
-    $query .= " ORDER BY category, lib, lib_opac";
+    my $query = qq{
+        SELECT *
+        FROM authorised_values
+    };
+    $query .= qq{
+          LEFT JOIN authorised_values_branches ON ( id = av_id )
+    } if $branch_limit;
+    my @where_strings;
+    my @where_args;
+    if($category) {
+        push @where_strings, "category = ?";
+        push @where_args, $category;
+    }
+    if($branch_limit) {
+        push @where_strings, "( branchcode = ? OR branchcode IS NULL )";
+        push @where_args, $branch_limit;
+    }
+    if(@where_strings > 0) {
+        $query .= " WHERE " . join(" AND ", @where_strings);
+    }
+    $query .= " GROUP BY lib ORDER BY category, lib, lib_opac";
+
     my $sth = $dbh->prepare($query);
-    $sth->execute;
-	while (my $data=$sth->fetchrow_hashref) {
-	    if ($selected && $selected eq $data->{'authorised_value'} ) {
-		    $data->{'selected'} = 1;
-	    }
-	    if ($opac && $data->{'lib_opac'}) {
-		$data->{'lib'} = $data->{'lib_opac'};
-	    }
-	    push @results, $data;
-	}
-    #my $data = $sth->fetchall_arrayref({});
-    return \@results; #$data;
+    $sth->execute( @where_args );
+    while (my $data=$sth->fetchrow_hashref) {
+        if ($selected && $selected eq $data->{'authorised_value'} ) {
+            $data->{'selected'} = 1;
+        }
+        if ($opac && $data->{'lib_opac'}) {
+            $data->{'lib'} = $data->{'lib_opac'};
+        }
+        push @results, $data;
+    }
+    $sth->finish;
+    return \@results;
 }
 
 =head2 GetAuthorisedValueCategories
diff --git a/C4/Members.pm b/C4/Members.pm
index 056f7e4..2d50ef4 100644
--- a/C4/Members.pm
+++ b/C4/Members.pm
@@ -1373,20 +1373,35 @@ to category descriptions.
 
 #'
 sub GetborCatFromCatType {
-    my ( $category_type, $action ) = @_;
-	# FIXME - This API  seems both limited and dangerous. 
+    my ( $category_type, $action, $no_branch_limit ) = @_;
+
+    my $branch_limit = $no_branch_limit
+        ? 0
+        : C4::Context->userenv ? C4::Context->userenv->{"branch"} : "";
+
+    # FIXME - This API  seems both limited and dangerous. 
     my $dbh     = C4::Context->dbh;
-    my $request = qq|   SELECT categorycode,description 
-            FROM categories 
-            $action
-            ORDER BY categorycode|;
-    my $sth = $dbh->prepare($request);
-	if ($action) {
-        $sth->execute($category_type);
-    }
-    else {
-        $sth->execute();
+
+    my $request = qq{
+        SELECT categories.categorycode, categories.description
+        FROM categories
+    };
+    $request .= qq{
+        LEFT JOIN categories_branches ON categories.categorycode = categories_branches.categorycode
+    } if $branch_limit;
+    if($action) {
+        $request .= " $action ";
+        $request .= " AND (branchcode = ? OR branchcode IS NULL) GROUP BY description" if $branch_limit;
+    } else {
+        $request .= " WHERE branchcode = ? OR branchcode IS NULL GROUP BY description" if $branch_limit;
     }
+    $request .= " ORDER BY categorycode";
+
+    my $sth = $dbh->prepare($request);
+    $sth->execute(
+        $action ? $category_type : (),
+        $branch_limit ? $branch_limit : ()
+    );
 
     my %labels;
     my @codes;
@@ -1395,6 +1410,7 @@ sub GetborCatFromCatType {
         push @codes, $data->{'categorycode'};
         $labels{ $data->{'categorycode'} } = $data->{'description'};
     }
+    $sth->finish;
     return ( \@codes, \%labels );
 }
 
@@ -1437,16 +1453,21 @@ If no category code provided, the function returns all the categories.
 =cut
 
 sub GetBorrowercategoryList {
+    my $no_branch_limit = @_ ? shift : 0;
+    my $branch_limit = $no_branch_limit
+        ? 0
+        : C4::Context->userenv ? C4::Context->userenv->{"branch"} : "";
     my $dbh       = C4::Context->dbh;
-    my $sth       =
-    $dbh->prepare(
-    "SELECT * 
-    FROM categories 
-    ORDER BY description"
-        );
-    $sth->execute;
-    my $data =
-    $sth->fetchall_arrayref({});
+    my $query = "SELECT * FROM categories";
+    $query .= qq{
+        LEFT JOIN categories_branches ON categories.categorycode = categories_branches.categorycode
+        WHERE branchcode = ? OR branchcode IS NULL GROUP BY description
+    } if $branch_limit;
+    $query .= " ORDER BY description";
+    my $sth = $dbh->prepare( $query );
+    $sth->execute( $branch_limit ? $branch_limit : () );
+    my $data = $sth->fetchall_arrayref( {} );
+    $sth->finish;
     return $data;
 }    # sub getborrowercategory
 
diff --git a/C4/Members/AttributeTypes.pm b/C4/Members/AttributeTypes.pm
index 8c96e54..eb48883 100644
--- a/C4/Members/AttributeTypes.pm
+++ b/C4/Members/AttributeTypes.pm
@@ -69,12 +69,24 @@ If $all_fields is true, then each hashref also contains the other fields from bo
 =cut
 
 sub GetAttributeTypes {
-    my ($all) = @_;
-    my $select = $all ? '*' : 'code, description, class';
+    my $all    = @_   ? shift : 0;
+    my $no_branch_limit = @_ ? shift : 0;
+    my $branch_limit = $no_branch_limit
+        ? 0
+        : C4::Context->userenv ? C4::Context->userenv->{"branch"} : 0;
+    my $select = $all ? '*'   : 'DISTINCT(code), description';
+
     my $dbh = C4::Context->dbh;
-    my $sth = $dbh->prepare("SELECT $select FROM borrower_attribute_types ORDER by code");
-    $sth->execute();
+    my $query = "SELECT $select FROM borrower_attribute_types";
+    $query .= qq{
+        LEFT JOIN borrower_attribute_types_branches ON bat_code = code
+        WHERE b_branchcode = ? OR b_branchcode IS NULL
+    } if $branch_limit;
+    $query .= " ORDER BY code";
+    my $sth    = $dbh->prepare($query);
+    $sth->execute( $branch_limit ? $branch_limit : () );
     my $results = $sth->fetchall_arrayref({});
+    $sth->finish;
     return @$results;
 }
 
@@ -166,6 +178,13 @@ sub fetch {
     $self->{'category_description'}      = $row->{'category_description'};
     $self->{'class'}                     = $row->{'class'};
 
+    $sth = $dbh->prepare("SELECT branchcode, branchname FROM borrower_attribute_types_branches, branches WHERE b_branchcode = branchcode AND bat_code = ?;");
+    $sth->execute( $code );
+    while ( my $data = $sth->fetchrow_hashref ) {
+        push @{ $self->{branches} }, $data;
+    }
+    $sth->finish();
+
     bless $self, $class;
     return $self;
 }
@@ -219,6 +238,22 @@ sub store {
     $sth->bind_param(11, $self->{'code'});
     $sth->execute;
 
+    if ( defined $$self{branches} ) {
+        $sth = $dbh->prepare("DELETE FROM borrower_attribute_types_branches WHERE bat_code = ?");
+        $sth->execute( $$self{code} );
+        $sth = $dbh->prepare(
+            "INSERT INTO borrower_attribute_types_branches
+                        ( bat_code, b_branchcode )
+                        VALUES ( ?, ? )"
+        );
+        for my $branchcode ( @{$$self{branches}} ) {
+            next if not $branchcode;
+            $sth->bind_param( 1, $$self{code} );
+            $sth->bind_param( 2, $branchcode );
+            $sth->execute;
+        }
+    }
+    $sth->finish;
 }
 
 =head2 code
@@ -250,6 +285,24 @@ sub description {
     @_ ? $self->{'description'} = shift : $self->{'description'};
 }
 
+=head2 branches
+
+=over 4
+
+my $branches = $attr_type->branches();
+$attr_type->branches($branches);
+
+=back
+
+Accessor.
+
+=cut
+
+sub branches {
+    my $self = shift;
+    @_ ? $self->{branches} = shift : $self->{branches};
+}
+
 =head2 repeatable
 
   my $repeatable = $attr_type->repeatable();
@@ -432,6 +485,7 @@ sub delete {
     my $dbh = C4::Context->dbh;
     my $sth = $dbh->prepare_cached("DELETE FROM borrower_attribute_types WHERE code = ?");
     $sth->execute($code);
+    $sth->finish;
 }
 
 =head2 num_patrons
diff --git a/C4/Members/Attributes.pm b/C4/Members/Attributes.pm
index 33d2407..cecb630 100644
--- a/C4/Members/Attributes.pm
+++ b/C4/Members/Attributes.pm
@@ -70,6 +70,7 @@ marked for OPAC display are returned.
 sub GetBorrowerAttributes {
     my $borrowernumber = shift;
     my $opac_only = @_ ? shift : 0;
+    my $branch_limit = @_ ? shift : 0;
 
     my $dbh = C4::Context->dbh();
     my $query = "SELECT code, description, attribute, lib, password, display_checkout, category_code, class
@@ -94,6 +95,7 @@ sub GetBorrowerAttributes {
             class             => $row->{'class'},
         }
     }
+    $sth->finish;
     return \@results;
 }
 
diff --git a/admin/authorised_values.pl b/admin/authorised_values.pl
index 1545f0e..e808e1d 100755
--- a/admin/authorised_values.pl
+++ b/admin/authorised_values.pl
@@ -22,6 +22,7 @@ use warnings;
 
 use CGI;
 use C4::Auth;
+use C4::Branch;
 use C4::Context;
 use C4::Koha;
 use C4::Output;
@@ -67,13 +68,32 @@ $template->param(  script_name => $script_name,
 # called by default. Used to create form to add or  modify a record
 if ($op eq 'add_form') {
 	my $data;
+    my @selected_branches;
 	if ($id) {
 		my $sth=$dbh->prepare("select id, category, authorised_value, lib, lib_opac, imageurl from authorised_values where id=?");
 		$sth->execute($id);
 		$data=$sth->fetchrow_hashref;
+        $sth = $dbh->prepare("SELECT b.branchcode, b.branchname FROM authorised_values_branches AS avb, branches AS b WHERE avb.branchcode = b.branchcode AND avb.av_id = ?;");
+        $sth->execute( $id );
+        while ( my $branch = $sth->fetchrow_hashref ) {
+            push @selected_branches, $branch;
+        }
 	} else {
 		$data->{'category'} = $input->param('category');
 	}
+
+    my $branches = GetBranches;
+    my @branches_loop;
+
+    foreach my $branch (sort keys %$branches) {
+        my $selected = ( grep {$_->{branchcode} eq $branch} @selected_branches ) ? 1 : 0;
+        push @branches_loop, {
+            branchcode => $branches->{$branch}{branchcode},
+            branchname => $branches->{$branch}{branchname},
+            selected => $selected,
+        };
+    }
+
 	if ($id) {
 		$template->param(action_modify => 1);
 		$template->param('heading_modify_authorized_value_p' => 1);
@@ -92,6 +112,7 @@ if ($op eq 'add_form') {
                          id               => $data->{'id'},
                          imagesets        => C4::Koha::getImageSets( checked => $data->{'imageurl'} ),
                          offset           => $offset,
+                         branches_loop    => \@branches_loop,
                      );
                           
 ################## ADD_VALIDATE ##################################
@@ -102,6 +123,7 @@ if ($op eq 'add_form') {
     my $imageurl     = $input->param( 'imageurl' ) || '';
 	$imageurl = '' if $imageurl =~ /removeImage/;
     my $duplicate_entry = 0;
+    my @branches = $input->param('branches');
 
     if ( $id ) { # Update
         my $sth = $dbh->prepare( "SELECT category, authorised_value FROM authorised_values WHERE id = ? ");
@@ -125,7 +147,21 @@ if ($op eq 'add_form') {
             my $lib_opac = $input->param('lib_opac');
             undef $lib if ($lib eq ""); # to insert NULL instead of a blank string
             undef $lib_opac if ($lib_opac eq ""); # to insert NULL instead of a blank string
-            $sth->execute($new_category, $new_authorised_value, $lib, $lib_opac, $imageurl, $id);          
+            $sth->execute($new_category, $new_authorised_value, $lib, $lib_opac, $imageurl, $id);
+            if ( @branches ) {
+                $sth = $dbh->prepare("DELETE FROM authorised_values_branches WHERE av_id = ?");
+                $sth->execute( $id );
+                $sth = $dbh->prepare(
+                    "INSERT INTO authorised_values_branches
+                                ( av_id, branchcode )
+                                VALUES ( ?, ? )"
+                );
+                for my $branchcode ( @branches ) {
+                    next if not $branchcode;
+                    $sth->execute($id, $branchcode);
+                }
+            }
+            $sth->finish;
             print "Content-Type: text/html\n\n<META HTTP-EQUIV=Refresh CONTENT=\"0; URL=authorised_values.pl?searchfield=".$new_category."&offset=$offset\"></html>";
             exit;
         }
@@ -137,13 +173,25 @@ if ($op eq 'add_form') {
         ($duplicate_entry) = $sth->fetchrow_array();
         unless ( $duplicate_entry ) {
             my $sth=$dbh->prepare( 'INSERT INTO authorised_values
-                                    ( id, category, authorised_value, lib, lib_opac, imageurl )
-                                    values (?, ?, ?, ?, ?, ?)' );
+                                    ( category, authorised_value, lib, lib_opac, imageurl )
+                                    values (?, ?, ?, ?, ?)' );
     	    my $lib = $input->param('lib');
     	    my $lib_opac = $input->param('lib_opac');
     	    undef $lib if ($lib eq ""); # to insert NULL instead of a blank string
     	    undef $lib_opac if ($lib_opac eq ""); # to insert NULL instead of a blank string
-    	    $sth->execute($id, $new_category, $new_authorised_value, $lib, $lib_opac, $imageurl );
+            $sth->execute( $new_category, $new_authorised_value, $lib, $lib_opac, $imageurl );
+            $id = $dbh->{'mysql_insertid'};
+            if ( @branches ) {
+                $sth = $dbh->prepare(
+                    "INSERT INTO authorised_values_branches
+                                ( av_id, branchcode )
+                                VALUES ( ?, ? )"
+                );
+                for my $branchcode ( @branches ) {
+                    next if not $branchcode;
+                    $sth->execute($id, $branchcode);
+                }
+            }
     	    print "Content-Type: text/html\n\n<META HTTP-EQUIV=Refresh CONTENT=\"0; URL=authorised_values.pl?searchfield=".$input->param('category')."&offset=$offset\"></html>";
     	    exit;
         }
@@ -176,6 +224,8 @@ if ($op eq 'add_form') {
 	my $id = $input->param('id');
 	my $sth=$dbh->prepare("delete from authorised_values where id=?");
 	$sth->execute($id);
+    $sth = $dbh->prepare("DELETE FROM authorised_values_branches WHERE id = ?");
+    $sth->execute($id);
 	print "Content-Type: text/html\n\n<META HTTP-EQUIV=Refresh CONTENT=\"0; URL=authorised_values.pl?searchfield=$searchfield&offset=$offset\"></html>";
 	exit;
 													# END $OP eq DELETE_CONFIRMED
diff --git a/admin/categorie.pl b/admin/categorie.pl
index 521346b..e93d0b3 100755
--- a/admin/categorie.pl
+++ b/admin/categorie.pl
@@ -36,11 +36,12 @@
 # with Koha; if not, write to the Free Software Foundation, Inc.,
 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
-use strict;
-#use warnings; FIXME - Bug 2505
+use Modern::Perl;
+
 use CGI;
 use C4::Context;
 use C4::Auth;
+use C4::Branch;
 use C4::Output;
 use C4::Dates;
 use C4::Form::MessagingPreferences;
@@ -90,16 +91,34 @@ if ($op eq 'add_form') {
 	
 	#---- if primkey exists, it's a modify action, so read values to modify...
 	my $data;
+    my @selected_branches;
 	if ($categorycode) {
 		my $dbh = C4::Context->dbh;
 		my $sth=$dbh->prepare("select categorycode,description,enrolmentperiod,enrolmentperioddate,upperagelimit,dateofbirthrequired,enrolmentfee,issuelimit,reservefee,hidelostitems,overduenoticerequired,category_type from categories where categorycode=?");
 		$sth->execute($categorycode);
 		$data=$sth->fetchrow_hashref;
-		$sth->finish;
-	}
+
+        $sth = $dbh->prepare("SELECT b.branchcode, b.branchname FROM categories_branches AS cb, branches AS b WHERE cb.branchcode = b.branchcode AND cb.categorycode = ?");
+        $sth->execute( $categorycode );
+        while ( my $branch = $sth->fetchrow_hashref ) {
+            push @selected_branches, $branch;
+        }
+        $sth->finish;
+    }
 
     $data->{'enrolmentperioddate'} = undef if ($data->{'enrolmentperioddate'} eq '0000-00-00');
 
+    my $branches = GetBranches;
+    my @branches_loop;
+    foreach my $branch (sort keys %$branches) {
+        my $selected = ( grep {$$_{branchcode} eq $branch} @selected_branches ) ? 1 : 0;
+        push @branches_loop, {
+            branchcode => $$branches{$branch}{branchcode},
+            branchname => $$branches{$branch}{branchname},
+            selected => $selected,
+        };
+    }
+
 	$template->param(description        => $data->{'description'},
 				enrolmentperiod         => $data->{'enrolmentperiod'},
 				enrolmentperioddate     => C4::Dates::format_date($data->{'enrolmentperioddate'}),
@@ -113,7 +132,8 @@ if ($op eq 'add_form') {
 				category_type           => $data->{'category_type'},
 				DHTMLcalendar_dateformat => C4::Dates->DHTMLcalendar(),
 				"type_".$data->{'category_type'} => 1,
-				SMSSendDriver => C4::Context->preference("SMSSendDriver")
+				SMSSendDriver => C4::Context->preference("SMSSendDriver"),
+                branches_loop           => \@branches_loop,
 				);
     if (C4::Context->preference('EnhancedMessagingPreferences')) {
         C4::Form::MessagingPreferences::set_form_values({ categorycode => $categorycode } , $template);
@@ -132,6 +152,22 @@ if ($op eq 'add_form') {
 	if ($is_a_modif) {
             my $sth=$dbh->prepare("UPDATE categories SET description=?,enrolmentperiod=?, enrolmentperioddate=?,upperagelimit=?,dateofbirthrequired=?,enrolmentfee=?,reservefee=?,hidelostitems=?,overduenoticerequired=?,category_type=? WHERE categorycode=?");
             $sth->execute(map { $input->param($_) } ('description','enrolmentperiod','enrolmentperioddate','upperagelimit','dateofbirthrequired','enrolmentfee','reservefee','hidelostitems','overduenoticerequired','category_type','categorycode'));
+            my @branches = $input->param("branches");
+            if ( @branches ) {
+                $sth = $dbh->prepare("DELETE FROM categories_branches WHERE categorycode = ?");
+                $sth->execute( $input->param( "categorycode" ) );
+                $sth = $dbh->prepare(
+                    "INSERT INTO categories_branches
+                                ( categorycode, branchcode )
+                                VALUES ( ?, ? )"
+                );
+                for my $branchcode ( @branches ) {
+                    next if not $branchcode;
+                    $sth->bind_param( 1, $input->param( "categorycode" ) );
+                    $sth->bind_param( 2, $branchcode );
+                    $sth->execute;
+                }
+            }
             $sth->finish;
         } else {
             my $sth=$dbh->prepare("INSERT INTO categories  (categorycode,description,enrolmentperiod,enrolmentperioddate,upperagelimit,dateofbirthrequired,enrolmentfee,reservefee,hidelostitems,overduenoticerequired,category_type) values (?,?,?,?,?,?,?,?,?,?,?)");
diff --git a/admin/patron-attr-types.pl b/admin/patron-attr-types.pl
index 638456e..108b6a4 100755
--- a/admin/patron-attr-types.pl
+++ b/admin/patron-attr-types.pl
@@ -19,12 +19,13 @@
 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 #
 
-use strict;
-use warnings;
+use Modern::Perl;
+
 use CGI;
 use List::MoreUtils qw/uniq/;
 
 use C4::Auth;
+use C4::Branch;
 use C4::Context;
 use C4::Output;
 use C4::Koha;
@@ -82,10 +83,20 @@ exit 0;
 sub add_attribute_type_form {
     my $template = shift;
 
+    my $branches = GetBranches;
+    my @branches_loop;
+    foreach my $branch (sort keys %$branches) {
+        push @branches_loop, {
+            branchcode => $$branches{$branch}{branchcode},
+            branchname => $$branches{$branch}{branchname},
+        };
+    }
+
     $template->param(
         attribute_type_form => 1,
         confirm_op => 'add_attribute_type_confirmed',
         categories => GetBorrowercategoryList,
+        branches_loop => \@branches_loop,
     );
     authorised_value_category_list($template);
     pa_classes($template);
@@ -162,6 +173,8 @@ sub add_update_attribute_type {
     $attr_type->display_checkout($display_checkout);
     $attr_type->category_code($input->param('category_code'));
     $attr_type->class($input->param('class'));
+    my @branches = $input->param('branches');
+    $attr_type->branches( \@branches );
 
     if ($op eq 'edit') {
         $template->param(edited_attribute_type => $attr_type->code());
@@ -244,6 +257,20 @@ sub edit_attribute_type_form {
     authorised_value_category_list($template, $attr_type->authorised_value_category());
     pa_classes( $template, $attr_type->class );
 
+
+    my $branches = GetBranches;
+    my @branches_loop;
+    my $selected_branches = $attr_type->branches;
+    foreach my $branch (sort keys %$branches) {
+        my $selected = ( grep {$$_{branchcode} eq $branch} @$selected_branches ) ? 1 : 0;
+        push @branches_loop, {
+            branchcode => $branches->{$branch}{branchcode},
+            branchname => $branches->{$branch}{branchname},
+            selected => $selected,
+        };
+    }
+    $template->param( branches_loop => \@branches_loop );
+
     $template->param ( category_code => $attr_type->category_code );
     $template->param ( category_description => $attr_type->category_description );
 
@@ -259,8 +286,9 @@ sub edit_attribute_type_form {
 sub patron_attribute_type_list {
     my $template = shift;
 
-    my @attr_types = C4::Members::AttributeTypes::GetAttributeTypes();
-    my @classes = uniq( map {$_->{class}} @attr_types );
+    my @attr_types = C4::Members::AttributeTypes::GetAttributeTypes( 1, 1 );
+
+    my @classes = uniq( map { $_->{class} } @attr_types );
     @classes = sort @classes;
 
     my @attributes_loop;
diff --git a/cataloguing/addbiblio.pl b/cataloguing/addbiblio.pl
index d5778a4..b9581f1 100755
--- a/cataloguing/addbiblio.pl
+++ b/cataloguing/addbiblio.pl
@@ -221,8 +221,11 @@ sub build_authorized_values_list {
         #---- "true" authorised value
     }
     else {
+        my $branch_limit = C4::Context->userenv ? C4::Context->userenv->{"branch"} : "";
         $authorised_values_sth->execute(
-            $tagslib->{$tag}->{$subfield}->{authorised_value} );
+            $branch_limit ? $branch_limit : (),
+            $tagslib->{$tag}->{$subfield}->{authorised_value}
+        );
 
         push @authorised_values, ""
           unless ( $tagslib->{$tag}->{$subfield}->{mandatory} );
@@ -232,6 +235,7 @@ sub build_authorized_values_list {
             $authorised_lib{$value} = $lib;
         }
     }
+    $authorised_values_sth->finish;
     return CGI::scrolling_list(
         -name     => "tag_".$tag."_subfield_".$subfield."_".$index_tag."_".$index_subfield,
         -values   => \@authorised_values,
@@ -523,12 +527,14 @@ sub build_tabs {
     my @loop_data = ();
     my $tag;
 
-    my $authorised_values_sth = $dbh->prepare(
-        "select authorised_value,lib
-        from authorised_values
-        where category=? order by lib"
-    );
-    
+    my $branch_limit = C4::Context->userenv ? C4::Context->userenv->{"branch"} : "";
+    my $query = "SELECT authorised_value, lib
+                FROM authorised_values";
+    $query .= qq{ JOIN authorised_values_branches ON ( id = av_id AND ( branchcode = ? OR branchcode IS NULL ) )} if $branch_limit;
+    $query .= " WHERE category = ?";
+    $query .= " GROUP BY lib ORDER BY lib, lib_opac";
+    my $authorised_values_sth = $dbh->prepare( $query );
+
     # in this array, we will push all the 10 tabs
     # to avoid having 10 tabs in the template : they will all be in the same BIG_LOOP
     my @BIG_LOOP;
@@ -713,6 +719,7 @@ sub build_tabs {
             };
         }
     }
+    $authorised_values_sth->finish;
     $template->param( BIG_LOOP => \@BIG_LOOP );
 }
 
diff --git a/cataloguing/additem.pl b/cataloguing/additem.pl
index 9c8120e..847434c 100755
--- a/cataloguing/additem.pl
+++ b/cataloguing/additem.pl
@@ -104,8 +104,7 @@ sub generate_subfield_form {
   
   my $frameworkcode = &GetFrameworkCode($biblionumber);
         my %subfield_data;
-        my $dbh = C4::Context->dbh;        
-        my $authorised_values_sth = $dbh->prepare("SELECT authorised_value,lib FROM authorised_values WHERE category=? ORDER BY lib");
+        my $dbh = C4::Context->dbh;
         
         my $index_subfield = int(rand(1000000)); 
         if ($subfieldtag eq '@'){
@@ -200,11 +199,11 @@ sub generate_subfield_form {
                   #---- "true" authorised value
             }
             else {
-                  push @authorised_values, "" unless ( $subfieldlib->{mandatory} );
-                  $authorised_values_sth->execute( $subfieldlib->{authorised_value} );
-                  while ( my ( $value, $lib ) = $authorised_values_sth->fetchrow_array ) {
-                      push @authorised_values, $value;
-                      $authorised_lib{$value} = $lib;
+                  push @authorised_values, qq{} unless ( $subfieldlib->{mandatory} );
+                  my $av = GetAuthorisedValues( $subfieldlib->{authorised_value} );
+                  for my $r ( @$av ) {
+                      push @authorised_values, $r->{authorised_value};
+                      $authorised_lib{$r->{authorised_value}} = $r->{lib};
                   }
             }
 
diff --git a/installer/data/mysql/kohastructure.sql b/installer/data/mysql/kohastructure.sql
index 4912e19..f921ce8 100644
--- a/installer/data/mysql/kohastructure.sql
+++ b/installer/data/mysql/kohastructure.sql
@@ -2810,6 +2810,44 @@ CREATE TABLE IF NOT EXISTS `social_data` (
   PRIMARY KEY  (`isbn`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
 
+--
+-- Table structure for table categories_branches
+--
+
+DROP TABLE IF EXISTS categories_branches;
+CREATE TABLE categories_branches( -- association table between categories and branches
+    categorycode VARCHAR(10),
+    branchcode VARCHAR(10),
+    FOREIGN KEY (categorycode) REFERENCES categories(categorycode) ON DELETE CASCADE,
+    FOREIGN KEY (branchcode) REFERENCES branches(branchcode) ON DELETE CASCADE
+) ENGINE=INNODB DEFAULT CHARSET=utf8;
+
+--
+-- Table structure for table authorised_values_branches
+--
+
+DROP TABLE IF EXISTS authorised_values_branches;
+CREATE TABLE authorised_values_branches( -- association table between authorised_values and branches
+    av_id INTEGER,
+    branchcode VARCHAR(10),
+    FOREIGN KEY (av_id) REFERENCES authorised_values(id) ON DELETE CASCADE,
+    FOREIGN KEY (branchcode) REFERENCES branches(branchcode) ON DELETE CASCADE
+) ENGINE=INNODB DEFAULT CHARSET=utf8;
+
+
+--
+-- Table structure for table borrower_attribute_types_branches
+--
+
+DROP TABLE IF EXISTS borrower_attribute_types_branches;
+CREATE TABLE borrower_attribute_types_branches( -- association table between borrower_attribute_types and branches
+    bat_code VARCHAR(10),
+    b_branchcode VARCHAR(10),
+    FOREIGN KEY (bat_code) REFERENCES borrower_attribute_types(code) ON DELETE CASCADE,
+    FOREIGN KEY (b_branchcode) REFERENCES branches(branchcode) ON DELETE CASCADE
+) ENGINE=INNODB DEFAULT CHARSET=utf8;
+
+
 /*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
 /*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
 /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
diff --git a/installer/data/mysql/updatedatabase.pl b/installer/data/mysql/updatedatabase.pl
index 503c8ee..f9e287e 100755
--- a/installer/data/mysql/updatedatabase.pl
+++ b/installer/data/mysql/updatedatabase.pl
@@ -5146,6 +5146,23 @@ if ( C4::Context->preference("Version") < TransformToNum($DBversion) ) {
     SetVersion($DBversion);
 }
 
+
+
+
+
+
+$DBversion = "3.06.00.XXX";
+if ( C4::Context->preference("Version") < TransformToNum($DBversion) ) {
+    $dbh->do(qq{CREATE TABLE borrower_attribute_types_branches(bat_code VARCHAR(10), b_branchcode VARCHAR(10),FOREIGN KEY (bat_code) REFERENCES borrower_attribute_types(code) ON DELETE CASCADE,FOREIGN KEY (b_branchcode) REFERENCES branches(branchcode) ON DELETE CASCADE ) ENGINE=INNODB DEFAULT CHARSET=utf8;});
+
+    $dbh->do(qq{CREATE TABLE categories_branches(categorycode VARCHAR(10), branchcode VARCHAR(10), FOREIGN KEY (categorycode) REFERENCES categories(categorycode) ON DELETE CASCADE, FOREIGN KEY (branchcode) REFERENCES branches(branchcode) ON DELETE CASCADE ) ENGINE=INNODB DEFAULT CHARSET=utf8;});
+
+    $dbh->do(qq{CREATE TABLE authorised_values_branches(av_id INTEGER, branchcode VARCHAR(10), FOREIGN KEY (av_id) REFERENCES authorised_values(id) ON DELETE CASCADE, FOREIGN KEY  (branchcode) REFERENCES branches(branchcode) ON DELETE CASCADE ) ENGINE=INNODB DEFAULT CHARSET=utf8;});
+
+    print "Upgrade to $DBversion done (Add 3 associations tables with branches)\n";
+    SetVersion($DBversion);
+}
+
 =head1 FUNCTIONS
 
 =head2 DropAllForeignKeys($table)
diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/authorised_values.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/authorised_values.tt
index 0c806ce..728615a 100644
--- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/authorised_values.tt
+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/authorised_values.tt
@@ -13,7 +13,10 @@
 		sortList: [[1,0]],
 		headers: { 4: { sorter: false}, 5: { sorter: false}}
 		   		}).tablesorterPager({container: $("#pagertable_authorized_values"),positionFixed: false,size: 50});
-	
+
+    if ( $("#branches option:selected").length < 1 ) {
+        $("#branches option:first").attr("selected", "selected");
+    }
 }); </script>
 
 <script type="text/JavaScript" language="JavaScript">
@@ -77,6 +80,21 @@
             <label for="lib_opac">Description (OPAC)</label>
             <input type="text" name="lib_opac" id="lib_opac" value="[% lib_opac %]" maxlength="80" />
         </li>
+        <li><label for="branches">Branches limitation: </label>
+            <select id="branches" name="branches" multiple size="10">
+                <option value="">All branches</option>
+                [% FOREACH branch IN branches_loop %]
+                  [% IF ( branch.selected ) %]
+                    <option selected="selected" value="[% branch.branchcode %]">[% branch.branchname %]</option>
+                  [% ELSE %]
+                    <option value="[% branch.branchcode %]">[% branch.branchname %]</option>
+                  [% END %]
+                [% END %]
+            </select>
+            <span>Select All if this authorised value must to be displayed all the time. Otherwise select librairies you want to associate with this value.
+            </span>
+        </li>
+
 		</ol>
 		<div id="icons" class="toptabs">
 		<h5 style="margin-left:10px;">Choose an Icon:</h5>
diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/categorie.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/categorie.tt
index d2c353e..881f545 100644
--- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/categorie.tt
+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/categorie.tt
@@ -12,6 +12,10 @@
 		widgets: ['zebra'],
 		headers: { 11: { sorter: false}}
 	}).tablesorterPager({container: $("#pagertable_categorie"),positionFixed: false,size: 20});
+
+    if ( $("#branches option:selected").length < 1 ) {
+        $("#branches option:first").attr("selected", "selected");
+    }
 }); </script>
 [% INCLUDE 'calendar.inc' %]
 <script type="text/javascript">
@@ -179,7 +183,22 @@
 					[% IF ( type_P ) %]<option value="P" selected="selected">Professional</option>[% ELSE %]<option value="P">Professional</option>[% END %]
 					[% IF ( type_X ) %]<option value="X" selected="selected">Statistical</option>[% ELSE %]<option value="X">Statistical</option>[% END %]
 					</select>
-	</li></ol>
+    </li>
+    <li><label for="branches">Branches limitation: </label>
+        <select id="branches" name="branches" multiple size="10">
+            <option value="">All branches</option>
+            [% FOREACH branch IN branches_loop %]
+              [% IF ( branch.selected ) %]
+                <option selected="selected" value="[% branch.branchcode %]">[% branch.branchname %]</option>
+              [% ELSE %]
+                <option value="[% branch.branchcode %]">[% branch.branchname %]</option>
+              [% END %]
+            [% END %]
+        </select>
+        <span>Select All if this category type must to be displayed all the time. Otherwise select librairies you want to associate with this value.
+        </span>
+    </li>
+    </ol>
 </fieldset>
 
     [% IF ( EnhancedMessagingPreferences ) %]
diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/patron-attr-types.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/patron-attr-types.tt
index 54bd8f2..3c61a98 100644
--- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/patron-attr-types.tt
+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/patron-attr-types.tt
@@ -15,6 +15,11 @@
 
 <script type="text/javascript">
 //<![CDATA[
+$(document).ready(function() {
+    if ( $("#branches option:selected").length < 1 ) {
+        $("#branches option:first").attr("selected", "selected");
+    }
+} );
 
 function DoCancel(f) {
   f.op.value='';
@@ -186,6 +191,20 @@ function CheckAttributeTypeForm(f) {
                   to be chosen from the authorized value list.  However, an authorized value list is not 
                   enforced during batch patron import.</span>
         </li>
+        <li><label for="branches">Branches limitation: </label>
+            <select id="branches" name="branches" multiple size="10">
+                <option value="">All branches</option>
+                [% FOREACH branch IN branches_loop %]
+                  [% IF ( branch.selected ) %]
+                    <option selected="selected" value="[% branch.branchcode %]">[% branch.branchname %]</option>
+                  [% ELSE %]
+                    <option value="[% branch.branchcode %]">[% branch.branchname %]</option>
+                  [% END %]
+                [% END %]
+            </select>
+            <span>Select All if this attribute type must to be displayed all the time. Otherwise select librairies you want to associate with this value.
+            </span>
+        </li>
         <li>
             <label for="category">Category: </label>
             <select name="category_code" id="category">
diff --git a/members/member.pl b/members/member.pl
index 9b793f4..0b4a4c9 100755
--- a/members/member.pl
+++ b/members/member.pl
@@ -134,8 +134,8 @@ foreach my $borrower(@$results[$from..$to-1]){
 
   my %row = (
     count => $index++,
-	%$borrower,
-	%{$categories_dislay{$$borrower{categorycode}}},
+    %$borrower,
+    (defined $categories_dislay{ $borrower->{categorycode} }?   %{ $categories_dislay{ $borrower->{categorycode} } }:()),
     overdues => $od,
     issues => $issue,
     odissue => "$od/$issue",
diff --git a/tools/batchMod.pl b/tools/batchMod.pl
index 9d59e3a..e1f5627 100755
--- a/tools/batchMod.pl
+++ b/tools/batchMod.pl
@@ -259,7 +259,13 @@ if ($op eq "show"){
 # now, build the item form for entering a new item
 my @loop_data =();
 my $i=0;
-my $authorised_values_sth = $dbh->prepare("SELECT authorised_value,lib FROM authorised_values WHERE category=? ORDER BY lib");
+my $query = qq{
+    SELECT authorised_value, lib FROM authorised_values
+    JOIN authorised_values_branches ON ( id = av_id AND ( branchcode = ? OR branchcode IS NULL ) )
+    WHERE category = ?
+    GROUP BY lib ORDER BY lib, lib_opac
+};
+my $authorised_values_sth = $dbh->prepare( $query );
 
 my $branches = GetBranchesLoop();  # build once ahead of time, instead of multiple times later.
 
@@ -352,7 +358,7 @@ foreach my $tag (sort keys %{$tagslib}) {
       }
       else {
           push @authorised_values, ""; # unless ( $tagslib->{$tag}->{$subfield}->{mandatory} );
-          $authorised_values_sth->execute( $tagslib->{$tag}->{$subfield}->{authorised_value} );
+          $authorised_values_sth->execute( C4::Context->userenv ? C4::Context->userenv->{"branch"} : "", $tagslib->{$tag}->{$subfield}->{authorised_value} );
           while ( my ( $value, $lib ) = $authorised_values_sth->fetchrow_array ) {
               push @authorised_values, $value;
               $authorised_lib{$value} = $lib;
@@ -420,6 +426,8 @@ foreach my $tag (sort keys %{$tagslib}) {
     $i++
   }
 } # -- End foreach tag
+$authorised_values_sth->finish;
+
 
 
     # what's the next op ? it's what we are not in : an add if we're editing, otherwise, and edit.
diff --git a/tools/import_borrowers.pl b/tools/import_borrowers.pl
index 83db522..78353c9 100755
--- a/tools/import_borrowers.pl
+++ b/tools/import_borrowers.pl
@@ -304,7 +304,7 @@ if ( $uploadborrowers && length($uploadborrowers) > 0 ) {
 } else {
     if ($extended) {
         my @matchpoints = ();
-        my @attr_types = C4::Members::AttributeTypes::GetAttributeTypes();
+        my @attr_types = C4::Members::AttributeTypes::GetAttributeTypes(undef, 1);
         foreach my $type (@attr_types) {
             my $attr_type = C4::Members::AttributeTypes->fetch($type->{code});
             if ($attr_type->unique_id()) {
-- 
1.7.7.3



More information about the Koha-patches mailing list