[Koha-patches] [PATCH 1/1] Bug 7154: Modification in borrower attributes

Jonathan Druart jonathan.druart at biblibre.com
Fri Feb 10 10:00:37 CET 2012


* group some attributes for a more friendly display

* allow a link between a borrower category and an attribute to display
  it only for the specified category

* Attr classes filled with AV 'PA_CLASS' category (you have to create AV
  with a new category 'PA_CLASS' to fill class list)

this patch add 2 fields in borrower_attribute_types :
    category_type
    class
---
 C4/Members/AttributeTypes.pm                       |   83 +++++++++-
 C4/Members/Attributes.pm                           |    4 +-
 admin/patron-attr-types.pl                         |   41 +++++-
 installer/data/mysql/kohastructure.sql             |    2 +
 installer/data/mysql/updatedatabase.pl             |   10 ++
 .../prog/en/modules/admin/patron-attr-types.tt     |   73 +++++++--
 .../prog/en/modules/members/memberentrygen.tt      |  172 ++++++++++++--------
 .../prog/en/modules/members/moremember.tt          |   43 ++++--
 members/memberentry.pl                             |   21 ++-
 members/moremember.pl                              |   21 ++-
 10 files changed, 358 insertions(+), 112 deletions(-)

diff --git a/C4/Members/AttributeTypes.pm b/C4/Members/AttributeTypes.pm
index e36557b..8c96e54 100644
--- a/C4/Members/AttributeTypes.pm
+++ b/C4/Members/AttributeTypes.pm
@@ -70,7 +70,7 @@ If $all_fields is true, then each hashref also contains the other fields from bo
 
 sub GetAttributeTypes {
     my ($all) = @_;
-    my $select = $all ? '*' : 'code, description';
+    my $select = $all ? '*' : 'code, description, class';
     my $dbh = C4::Context->dbh;
     my $sth = $dbh->prepare("SELECT $select FROM borrower_attribute_types ORDER by code");
     $sth->execute();
@@ -120,6 +120,9 @@ sub new {
     $self->{'staff_searchable'} = 0;
     $self->{'display_checkout'} = 0;
     $self->{'authorised_value_category'} = '';
+    $self->{'category_code'} = '';
+    $self->{'category_description'} = '';
+    $self->{'class'} = '';
 
     bless $self, $class;
     return $self;
@@ -140,11 +143,15 @@ sub fetch {
     my $self = {};
     my $dbh = C4::Context->dbh();
 
-    my $sth = $dbh->prepare_cached("SELECT * FROM borrower_attribute_types WHERE code = ?");
+    my $sth = $dbh->prepare_cached("
+        SELECT borrower_attribute_types.*, categories.description AS category_description
+        FROM borrower_attribute_types
+        LEFT JOIN categories ON borrower_attribute_types.category_code=categories.categorycode
+        WHERE code =?");
     $sth->execute($code);
     my $row = $sth->fetchrow_hashref;
     $sth->finish();
-    return undef unless defined $row;    
+    return undef unless defined $row;
 
     $self->{'code'}                      = $row->{'code'};
     $self->{'description'}               = $row->{'description'};
@@ -155,6 +162,9 @@ sub fetch {
     $self->{'staff_searchable'}          = $row->{'staff_searchable'};
     $self->{'display_checkout'}          = $row->{'display_checkout'};
     $self->{'authorised_value_category'} = $row->{'authorised_value_category'};
+    $self->{'category_code'}             = $row->{'category_code'};
+    $self->{'category_description'}      = $row->{'category_description'};
+    $self->{'class'}                     = $row->{'class'};
 
     bless $self, $class;
     return $self;
@@ -185,14 +195,16 @@ sub store {
                                          password_allowed = ?,
                                          staff_searchable = ?,
                                          authorised_value_category = ?,
-                                         display_checkout = ?
+                                         display_checkout = ?,
+                                         category_code = ?,
+                                         class = ?
                                      WHERE code = ?");
     } else {
         $sth = $dbh->prepare_cached("INSERT INTO borrower_attribute_types 
                                         (description, repeatable, unique_id, opac_display, password_allowed,
-                                         staff_searchable, authorised_value_category, display_checkout, code)
+                                         staff_searchable, authorised_value_category, display_checkout, category_code, class, code)
                                         VALUES (?, ?, ?, ?, ?,
-                                                ?, ?, ?, ?)");
+                                                ?, ?, ?, ?, ?, ?)");
     }
     $sth->bind_param(1, $self->{'description'});
     $sth->bind_param(2, $self->{'repeatable'});
@@ -202,7 +214,9 @@ sub store {
     $sth->bind_param(6, $self->{'staff_searchable'});
     $sth->bind_param(7, $self->{'authorised_value_category'});
     $sth->bind_param(8, $self->{'display_checkout'});
-    $sth->bind_param(9, $self->{'code'});
+    $sth->bind_param(9, $self->{'category_code'} || undef);
+    $sth->bind_param(10, $self->{'class'});
+    $sth->bind_param(11, $self->{'code'});
     $sth->execute;
 
 }
@@ -341,6 +355,61 @@ sub authorised_value_category {
     @_ ? $self->{'authorised_value_category'} = shift : $self->{'authorised_value_category'};
 }
 
+=head2 category_code
+
+=over 4
+
+my $category_code = $attr_type->category_code();
+$attr_type->category_code($category_code);
+
+=back
+
+Accessor.
+
+=cut
+
+sub category_code {
+    my $self = shift;
+    @_ ? $self->{'category_code'} = shift : $self->{'category_code'};
+}
+
+=head2 category_description
+
+=over 4
+
+my $category_description = $attr_type->category_description();
+$attr_type->category_description($category_description);
+
+=back
+
+Accessor.
+
+=cut
+
+sub category_description {
+    my $self = shift;
+    @_ ? $self->{'category_description'} = shift : $self->{'category_description'};
+}
+
+=head2 class
+
+=over 4
+
+my $class = $attr_type->class();
+$attr_type->class($class);
+
+=back
+
+Accessor.
+
+=cut
+
+sub class {
+    my $self = shift;
+    @_ ? $self->{'class'} = shift : $self->{'class'};
+}
+
+
 =head2 delete
 
   $attr_type->delete();
diff --git a/C4/Members/Attributes.pm b/C4/Members/Attributes.pm
index 4ae5600..137b11e 100644
--- a/C4/Members/Attributes.pm
+++ b/C4/Members/Attributes.pm
@@ -72,7 +72,7 @@ sub GetBorrowerAttributes {
     my $opac_only = @_ ? shift : 0;
 
     my $dbh = C4::Context->dbh();
-    my $query = "SELECT code, description, attribute, lib, password, display_checkout
+    my $query = "SELECT code, description, attribute, lib, password, display_checkout, category_type, class
                  FROM borrower_attributes
                  JOIN borrower_attribute_types USING (code)
                  LEFT JOIN authorised_values ON (category = authorised_value_category AND attribute = authorised_value)
@@ -90,6 +90,8 @@ sub GetBorrowerAttributes {
             value_description => $row->{'lib'},  
             password          => $row->{'password'},
             display_checkout  => $row->{'display_checkout'},
+            category_type     => $row->{'category_type'},
+            class             => $row->{'class'},
         }
     }
     return \@results;
diff --git a/admin/patron-attr-types.pl b/admin/patron-attr-types.pl
index 29a0d90..13b92ee 100755
--- a/admin/patron-attr-types.pl
+++ b/admin/patron-attr-types.pl
@@ -22,10 +22,13 @@
 use strict;
 use warnings;
 use CGI;
+use List::MoreUtils qw/uniq/;
+
 use C4::Auth;
 use C4::Context;
 use C4::Output;
 use C4::Koha;
+use C4::Members qw/GetBorrowercategoryList/;
 use C4::Members::AttributeTypes;
 
 my $script_name = "/cgi-bin/koha/admin/patron-attr-types.pl";
@@ -82,8 +85,10 @@ sub add_attribute_type_form {
     $template->param(
         attribute_type_form => 1,
         confirm_op => 'add_attribute_type_confirmed',
+        categories => GetBorrowercategoryList,
     );
     authorised_value_category_list($template);
+    pa_classes($template);
 }
 
 sub error_add_attribute_type_form {
@@ -110,6 +115,9 @@ sub error_add_attribute_type_form {
         $template->param(display_checkout_checked => 'checked="checked"');
     }
 
+    $template->param( category_code => $input->param('category_code') );
+    $template->param( class => $input->param('class') );
+
     $template->param(
         attribute_type_form => 1,
         confirm_op => 'add_attribute_type_confirmed',
@@ -152,6 +160,8 @@ sub add_update_attribute_type {
     $attr_type->password_allowed($password_allowed);
     my $display_checkout = $input->param('display_checkout');
     $attr_type->display_checkout($display_checkout);
+    $attr_type->category_code($input->param('category_code'));
+    $attr_type->class($input->param('class'));
 
     if ($op eq 'edit') {
         $template->param(edited_attribute_type => $attr_type->code());
@@ -209,6 +219,7 @@ sub edit_attribute_type_form {
 
     $template->param(code => $code);
     $template->param(description => $attr_type->description());
+    $template->param(class => $attr_type->class());
 
     if ($attr_type->repeatable()) {
         $template->param(repeatable_checked => 1);
@@ -231,20 +242,39 @@ sub edit_attribute_type_form {
         $template->param(display_checkout_checked => 'checked="checked"');
     }
     authorised_value_category_list($template, $attr_type->authorised_value_category());
+    pa_classes( $template, $attr_type->class );
+
+    $template->param ( category_code => $attr_type->category_code );
+    $template->param ( category_description => $attr_type->category_description );
 
     $template->param(
         attribute_type_form => 1,
         edit_attribute_type => 1,
         confirm_op => 'edit_attribute_type_confirmed',
+        categories => GetBorrowercategoryList,
     );
 
 }
 
 sub patron_attribute_type_list {
     my $template = shift;
-    
+
     my @attr_types = C4::Members::AttributeTypes::GetAttributeTypes();
-    $template->param(available_attribute_types => \@attr_types);
+    my @classes = uniq( map {$_->{class}} @attr_types );
+    @classes = sort @classes;
+
+    my @attributes_loop;
+    for my $class (@classes) {
+        my @items;
+        for my $attr (@attr_types) {
+            push @items, $attr if $attr->{class} eq $class
+        }
+        push @attributes_loop, {
+            class => $class,
+            items => \@items
+        };
+    }
+    $template->param(available_attribute_types => \@attributes_loop);
     $template->param(display_list => 1);
 }
 
@@ -261,3 +291,10 @@ sub authorised_value_category_list {
     }
     $template->param(authorised_value_categories => \@list);
 }
+
+sub pa_classes {
+    my $template = shift;
+    my $selected = @_ ? shift : '';
+
+    $template->param(classes_val_loop => GetAuthorisedValues( 'PA_CLASS', $selected ) );
+}
diff --git a/installer/data/mysql/kohastructure.sql b/installer/data/mysql/kohastructure.sql
index 37113c2..3ab9937 100644
--- a/installer/data/mysql/kohastructure.sql
+++ b/installer/data/mysql/kohastructure.sql
@@ -286,6 +286,8 @@ CREATE TABLE `borrower_attribute_types` ( -- definitions for custom patron field
   `staff_searchable` tinyint(1) NOT NULL default 0, -- defines if this field is searchable via the patron search in the staff client (1 for yes, 0 for no)
   `authorised_value_category` varchar(10) default NULL, -- foreign key from authorised_values that links this custom field to an authorized value category
   `display_checkout` tinyint(1) NOT NULL default 0,-- defines if this field displays in checkout screens
+  `category_type` VARCHAR(1) NOT NULL DEFAULT '',-- defines a category for an attribute_type
+  `class` VARCHAR(255) NOT NULL DEFAULT '',-- defines a class for an attribute_type
   PRIMARY KEY  (`code`),
   KEY `auth_val_cat_idx` (`authorised_value_category`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
diff --git a/installer/data/mysql/updatedatabase.pl b/installer/data/mysql/updatedatabase.pl
index 099dfb9..6d08cd9 100755
--- a/installer/data/mysql/updatedatabase.pl
+++ b/installer/data/mysql/updatedatabase.pl
@@ -4663,6 +4663,16 @@ ENDOFRENEWAL
     print "Upgrade to $DBversion done (Added a system preference to allow renewal of Patron account either from todays date or from existing expiry date in the patrons account.)\n";
     SetVersion($DBversion);
 }
+
+$DBversion = "3.07.00.XXX";
+if (C4::Context->preference("Version") < TransformToNum($DBversion)) {
+    $dbh->do("ALTER TABLE borrower_attribute_types ADD COLUMN category_code VARCHAR(10) NULL DEFAULT NULL AFTER `display_checkout`");
+    $dbh->do("ALTER TABLE borrower_attribute_types ADD COLUMN class VARCHAR(255)  NOT NULL DEFAULT '' AFTER `category_type`");
+    $dbh->do("ALTER TABLE borrower_attribute_types ADD CONSTRAINT category_code_fk FOREIGN KEY (category_code) REFERENCES categories(categorycode)");
+    print "Upgrade to $DBversion done (New fields category_type and class in borrower_attribute_types table)\n";
+    SetVersion($DBversion);
+}
+
 =head1 FUNCTIONS
 
 =head2 DropAllForeignKeys($table)
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 b8a8e3e..f6f76c4 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
@@ -186,6 +186,34 @@ 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="category">Category: </label>
+            <select name="category_code" id="category">
+                <option value=""></option>
+                [% FOREACH cat IN categories %]
+                    [% IF ( cat.categorycode == category_code ) %]<option value="[% cat.categorycode %]" selected="selected">[% cat.description %]</option>[% ELSE %]<option value="[% cat.categorycode %]">[% cat.description %]</option>[% END %]
+                [% END %]
+            </select>
+            <span>Please let blank if you want these attributs to be for all types of patron. Else, select one type.</span>
+        </li>
+        <li>
+            <label for="class">Class: </label>
+            <select name="class">
+                <option value="" />
+                [% FOREACH class IN classes_val_loop %]
+                    [% IF ( class.selected ) %]
+                        <option value="[% class.authorised_value %]" selected="selected">
+                            [% class.lib %]
+                        </option>
+                    [% ELSE %]
+                        <option value="[% class.authorised_value %]" >
+                            [% class.lib %]
+                        </option>
+                    [% END %]
+                [% END %]
+            </select>
+            <span>Group attributes types with a block title (based on Authorised values category 'PA_CLASS')</span>
+        </li>
     </ol>
   </fieldset>
   <fieldset class="action">
@@ -248,23 +276,36 @@ function CheckAttributeTypeForm(f) {
 <div class="dialog message">Could not delete patron attribute type &quot;[% ERROR_delete_not_found %]&quot; 
     &mdash; it was already absent from the database.</div>
 [% END %]
-[% IF ( available_attribute_types ) %]<table>
-  <tr>
-    <th>Code</th>
-    <th>Description</th>
-    <th>Actions</th>
-  </tr>
-  [% FOREACH available_attribute_type IN available_attribute_types %]
-  <tr>
-    <td>[% available_attribute_type.code |html %]</td>
-    <td>[% available_attribute_type.description %]</td>
-    <td>
-      <a href="[% available_attribute_type.script_name %]?op=edit_attribute_type&amp;code=[% available_attribute_type.code |html %]">Edit</a>
-      <a href="[% available_attribute_type.script_name %]?op=delete_attribute_type&amp;code=[% available_attribute_type.code |html %]">Delete</a>
-    </td>
-  </tr>
+[% IF ( available_attribute_types ) %]
+  [% FOREACH attribute IN available_attribute_types %]
+    [% IF attribute.class %]
+        <h4>[% attribute.class %]</h4>
+    [% END %]
+    <table class="patron_attributes_types">
+      <thead>
+        <tr>
+          <th>Code</th>
+          <th>Description</th>
+          <th>Actions</th>
+        </tr>
+      </thead>
+      <tbody>
+        [% FOREACH item IN attribute.items %]
+          <tr>
+            <td>[% item.code |html %]</td>
+            <td>[% item.description %]</td>
+            <td>
+              <a href="[% item.script_name %]?op=edit_attribute_type&amp;code=[% item.code |html %]">Edit</a>
+              <a href="[% item.script_name %]?op=delete_attribute_type&amp;code=[% item.code |html %]">Delete</a>
+            </td>
+          </tr>
+        [% END %]
+      </tbody>
+    </table>
   [% END %]
-</table>[% ELSE %]<p>There are no saved patron attribute types.</p>[% END %]
+[% ELSE %]
+  <p>There are no saved patron attribute types.</p>
+[% END %]
 
 <div class="pages">[% pagination_bar %]</div>
 
diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/members/memberentrygen.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/members/memberentrygen.tt
index 02d39f5..eda8ff3 100644
--- a/koha-tmpl/intranet-tmpl/prog/en/modules/members/memberentrygen.tt
+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/members/memberentrygen.tt
@@ -23,6 +23,16 @@
             document.form.state.value=RegExp.$3;
             document.form.country.value=RegExp.$4;
         });
+
+        [% IF categorycode %]
+            update_category_code( "[% categorycode %]" );
+        [% ELSE %]
+            if ( $("#categorycode").length > 0 ){
+                var category_code = $("#categorycode").find("option:selected").val();
+                update_category_code( category_code );
+            }
+        [% END %]
+
     });
 
     function clear_entry(node) {
@@ -51,6 +61,26 @@
         $("select#patron_attr_" + newId, clone).attr('value','');
         original.parentNode.insertBefore(clone, original.nextSibling);
     }
+
+    function update_category_code(category_code) {
+        if ( $(category_code).is("select") ) {
+            category_code = $("#categorycode").find("option:selected").val();
+        }
+        var mytables = $(".attributes_table>tbody");
+
+        mytables.find("tr").each(function(){
+            $(this).hide()
+        });
+
+        mytables.find("tr[data-category_code="+category_code+"]").each(function(){
+            $(this).show();
+        });
+        mytables.find("tr[data-category_code='']").each(function(){
+            $(this).show();
+        });
+
+    }
+
 		var MSG_SEPARATOR = _("Separator must be / in field ");
         var MSG_INCORRECT_DAY = _("Invalid day entered in field ");
         var MSG_INCORRECT_MONTH = _("Invalid month entered in field ");
@@ -984,25 +1014,25 @@
         [% END %]
     <li>
         <label for="categorycode">Category: </label>
-        <select id="categorycode" name="categorycode">
+        <select id="categorycode" name="categorycode" onchange="update_category_code(this);">
         [% FOREACH typeloo IN typeloop %]
-			[% FOREACH categoryloo IN typeloo.categoryloop %]
-				[% IF ( loop.first ) %]
-					[% IF ( categoryloo.typename_C ) %]<optgroup label="Child">[% END %]
-					[% IF ( categoryloo.typename_A ) %]<optgroup label="Adult">[% END %]
-					[% IF ( categoryloo.typename_S ) %]<optgroup label="Staff">[% END %]
-					[% IF ( categoryloo.typename_I ) %]<optgroup label="Organization">[% END %]
-					[% IF ( categoryloo.typename_P ) %]<optgroup label="Professional">[% END %]
-					[% IF ( categoryloo.typename_X ) %]<optgroup label="Statistical">[% END %]
-			    [% END %]
-				[% IF ( categoryloo.categorycodeselected ) %]
-               <option value="[% categoryloo.categorycode %]" selected="selected">[% categoryloo.categoryname %]</option>
-				[% ELSE %]
-<option value="[% categoryloo.categorycode %]">[% categoryloo.categoryname %]</option>
-				[% END %]
-				[% IF ( loop.last ) %]
-			        </optgroup>
-				[% END %]
+            [% FOREACH categoryloo IN typeloo.categoryloop %]
+                [% IF ( loop.first ) %]
+                    [% IF ( categoryloo.typename_C ) %]<optgroup label="Child"        value="C">[% END %]
+                    [% IF ( categoryloo.typename_A ) %]<optgroup label="Adult"        value="A">[% END %]
+                    [% IF ( categoryloo.typename_S ) %]<optgroup label="Staff"        value="S">[% END %]
+                    [% IF ( categoryloo.typename_I ) %]<optgroup label="Organization" value="I">[% END %]
+                    [% IF ( categoryloo.typename_P ) %]<optgroup label="Professional" value="P">[% END %]
+                    [% IF ( categoryloo.typename_X ) %]<optgroup label="Statistical"  value="X">[% END %]
+                [% END %]
+                [% IF ( categoryloo.categorycodeselected ) %]
+                    <option value="[% categoryloo.categorycode %]" selected="selected" data-typename="[% typeloo.typename %]">[% categoryloo.categoryname %]</option>
+                [% ELSE %]
+                    <option value="[% categoryloo.categorycode %]" data-typename="[% typeloo.typename %]">[% categoryloo.categoryname %]</option>
+                [% END %]
+                [% IF ( loop.last ) %]
+                    </optgroup>
+                [% END %]
             [% END %]
        [% END %]
        </select>
@@ -1281,7 +1311,7 @@
 			       [% IF ( opduplicate ) %] 
 			           <textarea id="debarredcomment" name="debarredcomment" cols="55" rows="3" onclick="this.value=''">[% debarredcomment %]</textarea>
 			       [% ELSE %]
-				   <textarea id="debarredcomment" name="debarredcomment" cols="55" rows="3" ">[% debarredcomment %]</textarea> 
+				   <textarea id="debarredcomment" name="debarredcomment" cols="55" rows="3" >[% debarredcomment %]</textarea>
 			       [% END %]
 	        </li>
 
@@ -1296,55 +1326,67 @@
   <fieldset class="rows" id="memberentry_patron_attributes">
     <input type="hidden" name="setting_extended_patron_attributes" value="1" />
     <legend>Additional attributes and identifiers</legend>
-    <table>
-        <tr>
-            <th>Type</th>
-            <th colspan="2">Value</th>
-        </tr>
-        [% FOREACH patron_attribute IN patron_attributes %]
-        <tr>
-            <td>[% patron_attribute.code %] ([% patron_attribute.description %])
-            </td>
-            <td>
-                <input type="hidden" id="[% patron_attribute.form_id %]_code" name="[% patron_attribute.form_id %]_code" value="[% patron_attribute.code |html %]" />
-                [% IF ( patron_attribute.use_dropdown ) %]
-                    <select id="[% patron_attribute.form_id %]" name="[% patron_attribute.form_id %]">
-                        <option value="" />
-                        [% FOREACH auth_val_loo IN patron_attribute.auth_val_loop %]
-                            [% IF ( auth_val_loo.selected ) %]
-                                <option value="[% auth_val_loo.authorised_value %]" selected="selected">
-                                    [% auth_val_loo.lib %]
-                                </option>
+    [% FOREACH pa_loo IN patron_attributes %]
+        [% IF pa_loo.class %]
+            <h4>[% pa_loo.class %]</h4>
+            <table id=aai_[% pa_loo.class %] class="attributes_table">
+        [% ELSE %]
+            <table id="aai" class="attributes_table">
+        [% END %]
+        <thead>
+            <tr>
+                <th>Type</th>
+                <th colspan="2">Value</th>
+            </tr>
+        </thead>
+        <tbody>
+            [% FOREACH patron_attribute IN pa_loo.items %]
+                <tr data-category_code="[% patron_attribute.category_code %]">
+                    <td>
+                        [% patron_attribute.code %] ([% patron_attribute.description %])
+                    </td>
+                    <td>
+                        <input type="hidden" id="[% patron_attribute.form_id %]_code" name="[% patron_attribute.form_id %]_code" value="[% patron_attribute.code |html %]" />
+                        [% IF ( patron_attribute.use_dropdown ) %]
+                            <select id="[% patron_attribute.form_id %]" name="[% patron_attribute.form_id %]">
+                                <option value="" />
+                                [% FOREACH auth_val_loo IN patron_attribute.auth_val_loop %]
+                                    [% IF ( auth_val_loo.selected ) %]
+                                        <option value="[% auth_val_loo.authorised_value %]" selected="selected">
+                                            [% auth_val_loo.lib %]
+                                        </option>
+                                    [% ELSE %]
+                                        <option value="[% auth_val_loo.authorised_value %]" >
+                                            [% auth_val_loo.lib %]
+                                        </option>
+                                    [% END %]
+                                [% END %]
+                            </select>
+                        [% ELSE %]
+                            [% IF ( opduplicate ) %]
+                            <input type="text" maxlength="64" value="[% patron_attribute.value %]"
+                                   id="[% patron_attribute.form_id %]" name="[% patron_attribute.form_id %]" onclick="this.value=''" />
                             [% ELSE %]
-                                <option value="[% auth_val_loo.authorised_value %]" >
-                                    [% auth_val_loo.lib %]
-                                </option>
+                            <input type="text" maxlength="64" value="[% patron_attribute.value %]"
+                                   id="[% patron_attribute.form_id %]" name="[% patron_attribute.form_id %]" />
                             [% END %]
                         [% END %]
-                    </select>
-                [% ELSE %]
-                    [% IF ( opduplicate ) %]
-                    <input type="text" maxlength="64" value="[% patron_attribute.value %]"
-                           id="[% patron_attribute.form_id %]" name="[% patron_attribute.form_id %]" onclick="this.value=''" />
-                    [% ELSE %]
-                    <input type="text" maxlength="64" value="[% patron_attribute.value %]"
-                           id="[% patron_attribute.form_id %]" name="[% patron_attribute.form_id %]" />
-                    [% END %]
-                [% END %]
-                [% IF ( patron_attribute.password_allowed ) %]
-                    (Password: <input type="password" maxlength="64" value="[% patron_attribute.password %]"
-                           id="[% patron_attribute.form_id %]_password" name="[% patron_attribute.form_id %]_password" />)
-                [% END %]
-            </td>
-            <td>
-                <a href="#" onclick="clear_entry(this); return false;">Clear</a>
-                [% IF ( patron_attribute.repeatable ) %]
-                <a href="#" onclick="clone_entry(this); return false;">New</a>
-                [% END %]
-            </td>
-        </tr>
-        [% END %]
-    </table>
+                        [% IF ( patron_attribute.password_allowed ) %]
+                            (Password: <input type="password" maxlength="64" value="[% patron_attribute.password %]"
+                                   id="[% patron_attribute.form_id %]_password" name="[% patron_attribute.form_id %]_password" />)
+                        [% END %]
+                    </td>
+                    <td>
+                        <a href="#" onclick="clear_entry(this); return false;">Clear</a>
+                        [% IF ( patron_attribute.repeatable ) %]
+                        <a href="#" onclick="clone_entry(this); return false;">New</a>
+                        [% END %]
+                    </td>
+                </tr>
+            [% END %]
+        </tbody>
+        </table>
+    [% END %]
   </fieldset>
 [% END %][% END %][% END %]
 
diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/members/moremember.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/members/moremember.tt
index c3d7063..3bd1203 100644
--- a/koha-tmpl/intranet-tmpl/prog/en/modules/members/moremember.tt
+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/members/moremember.tt
@@ -285,22 +285,35 @@ function validate1(date) {
 [% UNLESS ( no_patron_attribute_types ) %]
 <div id="patron-extended-attributes" style="padding-top: 1em;">
 <h3>Additional attributes and identifiers</h3>
-<table>
-    <tr>
-        <th>Type</th>
-        <th>Value</th>
-    </tr>
-    [% FOREACH extendedattribute IN extendedattributes %]
-    <tr>
-        <td>[% extendedattribute.code %] ([% extendedattribute.description %])</td>
-        <td>[% extendedattribute.value %]
-            [% IF ( extendedattribute.value_description ) %]
-                ([% extendedattribute.value_description %])
-            [% END %]
-        </td>
-    </tr>
+[% FOREACH attribute IN attributes_loop %]
+    [% IF attribute.class %]
+        <h4>[% attribute.class %]</h4>
+        <table id=aai_[% attribute.class %]>
+    [% ELSE %]
+        <table id="aai">
     [% END %]
-</table>
+        <thead>
+            <tr>
+                <th>Type</th>
+                <th>Description</th>
+                <th>Value</th>
+            </tr>
+        </thead>
+        <tbody>
+        [% FOREACH item IN attribute.items %]
+            <tr>
+                <td>[% item.code %]</td>
+                <td>[% item.description %]</td>
+                <td>[% item.value %]
+                    [% IF ( item.value_description ) %]
+                        ([% item.value_description %])
+                    [% END %]
+                </td>
+            </tr>
+        [% END %]
+        </tbody>
+    </table>
+[% END %]
 </div>
 <div class="action"><a href="memberentry.pl?op=modify&amp;borrowernumber=[% borrowernumber %]&amp;step=4">Edit</a></div>
 [% END %]
diff --git a/members/memberentry.pl b/members/memberentry.pl
index 6de07bf..4969f40 100755
--- a/members/memberentry.pl
+++ b/members/memberentry.pl
@@ -25,6 +25,7 @@ use warnings;
 # external modules
 use CGI;
 # use Digest::MD5 qw(md5_base64);
+use List::MoreUtils qw/uniq/;
 
 # internal modules
 use C4::Auth;
@@ -414,6 +415,9 @@ if ($op eq 'add'){
 if ($op eq "modify")  {
     $template->param( updtype => 'M',modify => 1 );
     $template->param( step_1=>1, step_2=>1, step_3=>1, step_4=>1, step_5 => 1, step_6 => 1) unless $step;
+    if ( $step == 4 ) {
+        $template->param( category_type => $borrower_data->{'categorycode'} );
+    }
 }
 if ( $op eq "duplicate" ) {
     $template->param( updtype => 'I' );
@@ -755,6 +759,8 @@ sub patron_attributes_form {
         return;
     }
     my $attributes = C4::Members::Attributes::GetBorrowerAttributes($borrowernumber);
+    my @classes = uniq( map {$_->{class}} @$attributes );
+    @classes = sort @classes;
 
     # map patron's attributes into a more convenient structure
     my %attr_hash = ();
@@ -764,14 +770,17 @@ sub patron_attributes_form {
 
     my @attribute_loop = ();
     my $i = 0;
+    my %items_by_class;
     foreach my $type_code (map { $_->{code} } @types) {
         my $attr_type = C4::Members::AttributeTypes->fetch($type_code);
         my $entry = {
+            class             => $attr_type->class(),
             code              => $attr_type->code(),
             description       => $attr_type->description(),
             repeatable        => $attr_type->repeatable(),
             password_allowed  => $attr_type->password_allowed(),
             category          => $attr_type->authorised_value_category(),
+            category_code     => $attr_type->category_code(),
             password          => '',
         };
         if (exists $attr_hash{$attr_type->code()}) {
@@ -786,8 +795,7 @@ sub patron_attributes_form {
                 }
                 $i++;
                 $newentry->{form_id} = "patron_attr_$i";
-                #use Data::Dumper; die Dumper($entry) if  $entry->{use_dropdown};
-                push @attribute_loop, $newentry;
+                push @{$items_by_class{$attr_type->class()}}, $newentry;
             }
         } else {
             $i++;
@@ -797,9 +805,16 @@ sub patron_attributes_form {
                 $newentry->{auth_val_loop} = GetAuthorisedValues($attr_type->authorised_value_category());
             }
             $newentry->{form_id} = "patron_attr_$i";
-            push @attribute_loop, $newentry;
+            push @{$items_by_class{$attr_type->class()}}, $newentry;
+        }
+    }
+    while ( my ($class, @items) = each %items_by_class ) {
+        push @attribute_loop, {
+            class => $class,
+            items => @items
         }
     }
+
     $template->param(patron_attributes => \@attribute_loop);
 
 }
diff --git a/members/moremember.pl b/members/moremember.pl
index c477100..e3f8e87 100755
--- a/members/moremember.pl
+++ b/members/moremember.pl
@@ -252,7 +252,6 @@ my $issuecount     = @{$issue};
 my $relissuecount  = @{$relissue};
 my $roaddetails = &GetRoadTypeDetails( $data->{'streettype'} );
 my $today       = POSIX::strftime("%Y-%m-%d", localtime);	# iso format
-my @issuedata;
 my @borrowers_with_issues;
 my $overdues_exist = 0;
 my $totalprice = 0;
@@ -432,11 +431,27 @@ my $branch=C4::Context->userenv->{'branch'};
 $template->param(%$data);
 
 if (C4::Context->preference('ExtendedPatronAttributes')) {
-    my $attributes = GetBorrowerAttributes($borrowernumber);
+    my $attributes = C4::Members::Attributes::GetBorrowerAttributes($borrowernumber);
+    my @classes = uniq( map {$_->{class}} @$attributes );
+    @classes = sort @classes;
+
+    my @attributes_loop;
+    for my $class (@classes) {
+        my @items;
+        for my $attr (@$attributes) {
+            push @items, $attr if $attr->{class} eq $class
+        }
+        push @attributes_loop, {
+            class => $class,
+            items => \@items
+        };
+    }
+
     $template->param(
         ExtendedPatronAttributes => 1,
-        extendedattributes => $attributes
+        attributes_loop => \@attributes_loop
     );
+
     my @types = C4::Members::AttributeTypes::GetAttributeTypes();
     if (scalar(@types) == 0) {
         $template->param(no_patron_attribute_types => 1);
-- 
1.7.7.3



More information about the Koha-patches mailing list