View | Details | Raw Unified | Return to bug 5742
Collapse All | Expand All

(-)a/C4/Members.pm (-71 / +88 lines)
Lines 42-127 use Koha::DateUtils; Link Here
42
our ($VERSION,@ISA,@EXPORT,@EXPORT_OK,$debug);
42
our ($VERSION,@ISA,@EXPORT,@EXPORT_OK,$debug);
43
43
44
BEGIN {
44
BEGIN {
45
	$VERSION = 3.02;
45
    $VERSION = 3.02;
46
	$debug = $ENV{DEBUG} || 0;
46
    $debug = $ENV{DEBUG} || 0;
47
	require Exporter;
47
    require Exporter;
48
	@ISA = qw(Exporter);
48
    @ISA = qw(Exporter);
49
	#Get data
49
    #Get data
50
	push @EXPORT, qw(
50
    push @EXPORT, qw(
51
		&Search
51
        &Search
52
		&GetMemberDetails
52
        &GetMemberDetails
53
        &GetMemberRelatives
53
        &GetMemberRelatives
54
		&GetMember
54
        &GetMember
55
55
56
		&GetGuarantees 
56
        &GetGuarantees
57
57
58
		&GetMemberIssuesAndFines
58
        &GetMemberIssuesAndFines
59
		&GetPendingIssues
59
        &GetPendingIssues
60
		&GetAllIssues
60
        &GetAllIssues
61
61
62
		&get_institutions 
62
        &get_institutions
63
		&getzipnamecity 
63
        &getzipnamecity
64
		&getidcity
64
        &getidcity
65
65
66
                &GetFirstValidEmailAddress
66
        &GetFirstValidEmailAddress
67
67
68
		&GetAge 
68
        &GetAge
69
		&GetCities 
69
        &GetCities
70
		&GetRoadTypes 
70
        &GetRoadTypes
71
		&GetRoadTypeDetails 
71
        &GetRoadTypeDetails
72
		&GetSortDetails
72
        &GetSortDetails
73
		&GetTitles
73
        &GetTitles
74
74
75
    &GetPatronImage
75
        &GetPatronImage
76
    &PutPatronImage
76
        &PutPatronImage
77
    &RmPatronImage
77
        &RmPatronImage
78
78
79
                &GetHideLostItemsPreference
79
        &GetHideLostItemsPreference
80
80
81
		&IsMemberBlocked
81
        &IsMemberBlocked
82
		&GetMemberAccountRecords
82
        &GetMemberAccountRecords
83
		&GetBorNotifyAcctRecord
83
        &GetBorNotifyAcctRecord
84
84
85
		&GetborCatFromCatType 
85
        &GetborCatFromCatType
86
		&GetBorrowercategory
86
        &GetBorrowercategory
87
    &GetBorrowercategoryList
87
        GetBorrowerCategorycode
88
        &GetBorrowercategoryList
88
89
89
		&GetBorrowersWhoHaveNotBorrowedSince
90
        &GetBorrowersWhoHaveNotBorrowedSince
90
		&GetBorrowersWhoHaveNeverBorrowed
91
        &GetBorrowersWhoHaveNeverBorrowed
91
		&GetBorrowersWithIssuesHistoryOlderThan
92
        &GetBorrowersWithIssuesHistoryOlderThan
92
93
93
		&GetExpiryDate
94
        &GetExpiryDate
94
95
95
		&AddMessage
96
        &AddMessage
96
		&DeleteMessage
97
        &DeleteMessage
97
		&GetMessages
98
        &GetMessages
98
		&GetMessagesCount
99
        &GetMessagesCount
99
100
100
        &IssueSlip
101
        &IssueSlip
101
		GetBorrowersWithEmail
102
        GetBorrowersWithEmail
102
	);
103
    );
103
104
104
	#Modify data
105
    #Modify data
105
	push @EXPORT, qw(
106
    push @EXPORT, qw(
106
		&ModMember
107
        &ModMember
107
		&changepassword
108
        &changepassword
108
         &ModPrivacy
109
         &ModPrivacy
109
	);
110
    );
110
111
111
	#Delete data
112
    #Delete data
112
	push @EXPORT, qw(
113
    push @EXPORT, qw(
113
		&DelMember
114
        &DelMember
114
	);
115
    );
115
116
116
	#Insert data
117
    #Insert data
117
	push @EXPORT, qw(
118
    push @EXPORT, qw(
118
		&AddMember
119
        &AddMember
119
		&add_member_orgs
120
        &add_member_orgs
120
		&MoveMemberToDeleted
121
        &MoveMemberToDeleted
121
		&ExtendMemberSubscriptionTo
122
        &ExtendMemberSubscriptionTo
122
	);
123
    );
123
124
124
	#Check data
125
    #Check data
125
    push @EXPORT, qw(
126
    push @EXPORT, qw(
126
        &checkuniquemember
127
        &checkuniquemember
127
        &checkuserpassword
128
        &checkuserpassword
Lines 329-335 sub GetMemberDetails { Link Here
329
        $sth->execute($cardnumber);
330
        $sth->execute($cardnumber);
330
    }
331
    }
331
    else {
332
    else {
332
        return undef;
333
        return;
333
    }
334
    }
334
    my $borrower = $sth->fetchrow_hashref;
335
    my $borrower = $sth->fetchrow_hashref;
335
    my ($amount) = GetMemberAccountRecords( $borrowernumber);
336
    my ($amount) = GetMemberAccountRecords( $borrowernumber);
Lines 581-587 sub GetMemberRelatives { Link Here
581
    $sth->execute($borrowernumber);
582
    $sth->execute($borrowernumber);
582
    my $data = $sth->fetchrow_arrayref();
583
    my $data = $sth->fetchrow_arrayref();
583
    push @glist, $data->[0] if $data->[0];
584
    push @glist, $data->[0] if $data->[0];
584
    my $guarantor = $data->[0] if $data->[0];
585
    my $guarantor = $data->[0] ? $data->[0] : undef;
585
586
586
    # Getting guarantees
587
    # Getting guarantees
587
    $query = "SELECT borrowernumber FROM borrowers WHERE guarantorid=?";
588
    $query = "SELECT borrowernumber FROM borrowers WHERE guarantorid=?";
Lines 692-698 sub GetMemberIssuesAndFines { Link Here
692
    return ($overdue_count, $issue_count, $total_fines);
693
    return ($overdue_count, $issue_count, $total_fines);
693
}
694
}
694
695
695
sub columns(;$) {
696
sub columns {
696
    return @{C4::Context->dbh->selectcol_arrayref("SHOW columns from borrowers")};
697
    return @{C4::Context->dbh->selectcol_arrayref("SHOW columns from borrowers")};
697
}
698
}
698
699
Lines 846-852 mode, to avoid database corruption. Link Here
846
use vars qw( @weightings );
847
use vars qw( @weightings );
847
my @weightings = ( 8, 4, 6, 3, 5, 2, 1 );
848
my @weightings = ( 8, 4, 6, 3, 5, 2, 1 );
848
849
849
sub fixup_cardnumber ($) {
850
sub fixup_cardnumber {
850
    my ($cardnumber) = @_;
851
    my ($cardnumber) = @_;
851
    my $autonumber_members = C4::Context->boolean_preference('autoMemberNum') || 0;
852
    my $autonumber_members = C4::Context->boolean_preference('autoMemberNum') || 0;
852
853
Lines 1409-1418 sub GetborCatFromCatType { Link Here
1409
Given the borrower's category code, the function returns the corresponding
1410
Given the borrower's category code, the function returns the corresponding
1410
data hashref for a comprehensive information display.
1411
data hashref for a comprehensive information display.
1411
1412
1412
  $arrayref_hashref = &GetBorrowercategory;
1413
1414
If no category code provided, the function returns all the categories.
1415
1416
=cut
1413
=cut
1417
1414
1418
sub GetBorrowercategory {
1415
sub GetBorrowercategory {
Lines 1433-1438 sub GetBorrowercategory { Link Here
1433
    return;  
1430
    return;  
1434
}    # sub getborrowercategory
1431
}    # sub getborrowercategory
1435
1432
1433
1434
=head2 GetBorrowerCategorycode
1435
1436
    $categorycode = &GetBorrowerCategoryCode( $borrowernumber );
1437
1438
Given the borrowernumber, the function returns the corresponding categorycode
1439
=cut
1440
1441
sub GetBorrowerCategorycode {
1442
    my ( $borrowernumber ) = @_;
1443
    my $dbh = C4::Context->dbh;
1444
    my $sth = $dbh->prepare( qq{
1445
        SELECT categorycode
1446
        FROM borrowers
1447
        WHERE borrowernumber = ?
1448
    } );
1449
    $sth->execute( $borrowernumber );
1450
    return $sth->fetchrow;
1451
}
1452
1436
=head2 GetBorrowercategoryList
1453
=head2 GetBorrowercategoryList
1437
1454
1438
  $arrayref_hashref = &GetBorrowercategoryList;
1455
  $arrayref_hashref = &GetBorrowercategoryList;
(-)a/C4/Members/AttributeTypes.pm (-1 / +1 lines)
Lines 151-157 sub fetch { Link Here
151
    $sth->execute($code);
151
    $sth->execute($code);
152
    my $row = $sth->fetchrow_hashref;
152
    my $row = $sth->fetchrow_hashref;
153
    $sth->finish();
153
    $sth->finish();
154
    return undef unless defined $row;
154
    return unless defined $row;
155
155
156
    $self->{'code'}                      = $row->{'code'};
156
    $self->{'code'}                      = $row->{'code'};
157
    $self->{'description'}               = $row->{'description'};
157
    $self->{'description'}               = $row->{'description'};
(-)a/C4/Members/Attributes.pm (-5 / +51 lines)
Lines 32-39 BEGIN { Link Here
32
    $VERSION = 3.01;
32
    $VERSION = 3.01;
33
    @ISA = qw(Exporter);
33
    @ISA = qw(Exporter);
34
    @EXPORT_OK = qw(GetBorrowerAttributes GetBorrowerAttributeValue CheckUniqueness SetBorrowerAttributes
34
    @EXPORT_OK = qw(GetBorrowerAttributes GetBorrowerAttributeValue CheckUniqueness SetBorrowerAttributes
35
                    DeleteBorrowerAttribute UpdateBorrowerAttribute
35
                    extended_attributes_code_value_arrayref extended_attributes_merge
36
                    extended_attributes_code_value_arrayref extended_attributes_merge
36
					SearchIdMatchingAttribute);
37
                    SearchIdMatchingAttribute);
37
    %EXPORT_TAGS = ( all => \@EXPORT_OK );
38
    %EXPORT_TAGS = ( all => \@EXPORT_OK );
38
}
39
}
39
40
Lines 76-93 sub GetBorrowerAttributes { Link Here
76
                 FROM borrower_attributes
77
                 FROM borrower_attributes
77
                 JOIN borrower_attribute_types USING (code)
78
                 JOIN borrower_attribute_types USING (code)
78
                 LEFT JOIN authorised_values ON (category = authorised_value_category AND attribute = authorised_value)
79
                 LEFT JOIN authorised_values ON (category = authorised_value_category AND attribute = authorised_value)
79
                 WHERE borrowernumber = ?";
80
                 WHERE 1";
81
    $query .= "\nAND borrowernumber = ?" if $borrowernumber;
80
    $query .= "\nAND opac_display = 1" if $opac_only;
82
    $query .= "\nAND opac_display = 1" if $opac_only;
81
    $query .= "\nORDER BY code, attribute";
83
    $query .= "\nORDER BY code, attribute";
82
    my $sth = $dbh->prepare_cached($query);
84
    my $sth = $dbh->prepare_cached($query);
83
    $sth->execute($borrowernumber);
85
    $sth->execute($borrowernumber ? $borrowernumber : ());
84
    my @results = ();
86
    my @results = ();
85
    while (my $row = $sth->fetchrow_hashref()) {
87
    while (my $row = $sth->fetchrow_hashref()) {
86
        push @results, {
88
        push @results, {
87
            code              => $row->{'code'},
89
            code              => $row->{'code'},
88
            description       => $row->{'description'},
90
            description       => $row->{'description'},
89
            value             => $row->{'attribute'},  
91
            value             => $row->{'attribute'},
90
            value_description => $row->{'lib'},  
92
            value_description => $row->{'lib'},
91
            password          => $row->{'password'},
93
            password          => $row->{'password'},
92
            display_checkout  => $row->{'display_checkout'},
94
            display_checkout  => $row->{'display_checkout'},
93
            category_code     => $row->{'category_code'},
95
            category_code     => $row->{'category_code'},
Lines 233-238 sub SetBorrowerAttributes { Link Here
233
    return 1; # borower attributes successfully set
235
    return 1; # borower attributes successfully set
234
}
236
}
235
237
238
=head2 DeleteBorrowerAttribute
239
240
  DeleteBorrowerAttribute($borrowernumber, $attribute);
241
242
Delete a borrower attribute for the patron identified by C<$borrowernumber> and the attribute code of C<$attribute>
243
244
=cut
245
sub DeleteBorrowerAttribute {
246
    my ( $borrowernumber, $attribute ) = @_;
247
248
    my $dbh = C4::Context->dbh;
249
    my $sth = $dbh->prepare(qq{
250
        DELETE FROM borrower_attributes
251
            WHERE borrowernumber = ?
252
            AND code = ?
253
    } );
254
    $sth->execute( $borrowernumber, $attribute->{code} );
255
}
256
257
=head2 UpdateBorrowerAttribute
258
259
  UpdateBorrowerAttribute($borrowernumber, $attribute );
260
261
Update a borrower attribute C<$attribute> for the patron identified by C<$borrowernumber>,
262
263
=cut
264
sub UpdateBorrowerAttribute {
265
    my ( $borrowernumber, $attribute ) = @_;
266
267
    DeleteBorrowerAttribute $borrowernumber, $attribute;
268
269
    my $dbh = C4::Context->dbh;
270
    my $query = "INSERT INTO borrower_attributes SET attribute = ?, code = ?, borrowernumber = ?";
271
    my @params = ( $attribute->{attribute}, $attribute->{code}, $borrowernumber );
272
    if ( defined $attribute->{password} ) {
273
        $query .= ", password = ?";
274
        push @params, $attribute->{password};
275
    }
276
    my $sth = $dbh->prepare( $query );
277
278
    $sth->execute( @params );
279
}
280
281
236
=head2 extended_attributes_code_value_arrayref 
282
=head2 extended_attributes_code_value_arrayref 
237
283
238
   my $patron_attributes = "homeroom:1150605,grade:01,extradata:foobar";
284
   my $patron_attributes = "homeroom:1150605,grade:01,extradata:foobar";
(-)a/Koha/Template/Plugin/KohaDates.pm (+1 lines)
Lines 29-34 use C4::Dates; Link Here
29
29
30
sub filter {
30
sub filter {
31
    my ($self,$text) = @_;
31
    my ($self,$text) = @_;
32
    return "" if not $text;
32
    my $date = C4::Dates->new( $text, 'iso' );
33
    my $date = C4::Dates->new( $text, 'iso' );
33
    return $date->output("syspref");
34
    return $date->output("syspref");
34
}
35
}
(-)a/installer/data/mysql/de-DE/mandatory/userpermissions.sql (+1 lines)
Lines 28-33 INSERT INTO permissions (module_bit, code, description) VALUES Link Here
28
   (13, 'manage_staged_marc', 'MARC-Importe verwalten, auch Übernahme in Katalog und Import rückgängig machen'),
28
   (13, 'manage_staged_marc', 'MARC-Importe verwalten, auch Übernahme in Katalog und Import rückgängig machen'),
29
   (13, 'export_catalog', 'Titel- und Exemplardaten exportieren'),
29
   (13, 'export_catalog', 'Titel- und Exemplardaten exportieren'),
30
   (13, 'import_patrons', 'Benutzerdaten importieren'),
30
   (13, 'import_patrons', 'Benutzerdaten importieren'),
31
   (13, 'edit_patrons', 'Perform batch modification of patrons'),
31
   (13, 'delete_anonymize_patrons', 'Inaktive Benutzer löschen und Ausleihhistorie anonymisieren (Benutzerausleihhistorie löschen)'),
32
   (13, 'delete_anonymize_patrons', 'Inaktive Benutzer löschen und Ausleihhistorie anonymisieren (Benutzerausleihhistorie löschen)'),
32
   (13, 'batch_upload_patron_images', 'Benutzerfotos einzeln oder im Stapel hochladen'),
33
   (13, 'batch_upload_patron_images', 'Benutzerfotos einzeln oder im Stapel hochladen'),
33
   (13, 'schedule_tasks', 'Aufgabenplaner verwenden'),
34
   (13, 'schedule_tasks', 'Aufgabenplaner verwenden'),
(-)a/installer/data/mysql/en/mandatory/userpermissions.sql (+1 lines)
Lines 28-33 INSERT INTO permissions (module_bit, code, description) VALUES Link Here
28
   (13, 'manage_staged_marc', 'Managed staged MARC records, including completing and reversing imports'),
28
   (13, 'manage_staged_marc', 'Managed staged MARC records, including completing and reversing imports'),
29
   (13, 'export_catalog', 'Export bibliographic and holdings data'),
29
   (13, 'export_catalog', 'Export bibliographic and holdings data'),
30
   (13, 'import_patrons', 'Import patron data'),
30
   (13, 'import_patrons', 'Import patron data'),
31
   (13, 'edit_patrons', 'Perform batch modification of patrons'),
31
   (13, 'delete_anonymize_patrons', 'Delete old borrowers and anonymize circulation history (deletes borrower reading history)'),
32
   (13, 'delete_anonymize_patrons', 'Delete old borrowers and anonymize circulation history (deletes borrower reading history)'),
32
   (13, 'batch_upload_patron_images', 'Upload patron images in batch or one at a time'),
33
   (13, 'batch_upload_patron_images', 'Upload patron images in batch or one at a time'),
33
   (13, 'schedule_tasks', 'Schedule tasks to run'),
34
   (13, 'schedule_tasks', 'Schedule tasks to run'),
(-)a/installer/data/mysql/es-ES/mandatory/userpermissions.sql (+1 lines)
Lines 28-33 INSERT INTO permissions (module_bit, code, description) VALUES Link Here
28
   (13, 'manage_staged_marc', 'Managed staged MARC records, including completing and reversing imports'),
28
   (13, 'manage_staged_marc', 'Managed staged MARC records, including completing and reversing imports'),
29
   (13, 'export_catalog', 'Export bibliographic and holdings data'),
29
   (13, 'export_catalog', 'Export bibliographic and holdings data'),
30
   (13, 'import_patrons', 'Import patron data'),
30
   (13, 'import_patrons', 'Import patron data'),
31
   (13, 'edit_patrons', 'Perform batch modification of patrons'),
31
   (13, 'delete_anonymize_patrons', 'Delete old borrowers and anonymize circulation history (deletes borrower reading history)'),
32
   (13, 'delete_anonymize_patrons', 'Delete old borrowers and anonymize circulation history (deletes borrower reading history)'),
32
   (13, 'batch_upload_patron_images', 'Upload patron images in batch or one at a time'),
33
   (13, 'batch_upload_patron_images', 'Upload patron images in batch or one at a time'),
33
   (13, 'schedule_tasks', 'Schedule tasks to run'),
34
   (13, 'schedule_tasks', 'Schedule tasks to run'),
(-)a/installer/data/mysql/fr-FR/1-Obligatoire/userpermissions.sql (+1 lines)
Lines 18-23 INSERT INTO permissions (module_bit, code, description) VALUES Link Here
18
   (13, 'manage_staged_marc', 'Gérer les notices du réservoir, les charger ou annuler leur chargement'),
18
   (13, 'manage_staged_marc', 'Gérer les notices du réservoir, les charger ou annuler leur chargement'),
19
   (13, 'export_catalog', 'Exporter des notices bibliographiques et leurs exemplaires'),
19
   (13, 'export_catalog', 'Exporter des notices bibliographiques et leurs exemplaires'),
20
   (13, 'import_patrons', 'Importer des données d''adhérents'),
20
   (13, 'import_patrons', 'Importer des données d''adhérents'),
21
   (13, 'edit_patrons', 'Modification par lot des lecteurs'),
21
   (13, 'delete_anonymize_patrons', 'Supprimer les anciens adhérents et anonymiser l''historique des prêts (supprime l''historique des prêts des lecteurs'),
22
   (13, 'delete_anonymize_patrons', 'Supprimer les anciens adhérents et anonymiser l''historique des prêts (supprime l''historique des prêts des lecteurs'),
22
   (13, 'batch_upload_patron_images', 'Charger sur le serveur les images des adhérents par lot ou un par un'),
23
   (13, 'batch_upload_patron_images', 'Charger sur le serveur les images des adhérents par lot ou un par un'),
23
   (13, 'schedule_tasks', 'Planifier les tâches à exécuter'),
24
   (13, 'schedule_tasks', 'Planifier les tâches à exécuter'),
(-)a/installer/data/mysql/it-IT/necessari/userpermissions.sql (+1 lines)
Lines 30-35 INSERT INTO permissions (module_bit, code, description) VALUES Link Here
30
   (13, 'manage_staged_marc', 'Gestisci i record MARC in lavorazione, inclusi il completare e il cancellare gli import'),
30
   (13, 'manage_staged_marc', 'Gestisci i record MARC in lavorazione, inclusi il completare e il cancellare gli import'),
31
   (13, 'export_catalog', 'Esporta i dati bibliografici e di copia'),
31
   (13, 'export_catalog', 'Esporta i dati bibliografici e di copia'),
32
   (13, 'import_patrons', 'Importa i dati utente'),
32
   (13, 'import_patrons', 'Importa i dati utente'),
33
   (13, 'edit_patrons', 'Perform batch modification of patrons'),
33
   (13, 'delete_anonymize_patrons', 'Cancella i vecchi prestiti e rendi anonimo lo storico della circolazione (canella in lettura lo storico utenti prestito)'),
34
   (13, 'delete_anonymize_patrons', 'Cancella i vecchi prestiti e rendi anonimo lo storico della circolazione (canella in lettura lo storico utenti prestito)'),
34
   (13, 'batch_upload_patron_images', 'Aggiorna le foto utente in modalità batch o al momento'),
35
   (13, 'batch_upload_patron_images', 'Aggiorna le foto utente in modalità batch o al momento'),
35
   (13, 'schedule_tasks', 'Schedula i task da far andare'),
36
   (13, 'schedule_tasks', 'Schedula i task da far andare'),
(-)a/installer/data/mysql/nb-NO/1-Obligatorisk/userpermissions.sql (+1 lines)
Lines 49-54 INSERT INTO permissions (module_bit, code, description) VALUES Link Here
49
   (13, 'manage_staged_marc', 'Behandle lagrede MARC-poster, inkludert ferdigstilling og reversering av importer'),
49
   (13, 'manage_staged_marc', 'Behandle lagrede MARC-poster, inkludert ferdigstilling og reversering av importer'),
50
   (13, 'export_catalog', 'Eksportere bibliografiske data og beholdningsdata'),
50
   (13, 'export_catalog', 'Eksportere bibliografiske data og beholdningsdata'),
51
   (13, 'import_patrons', 'Importere låneropplysninger'),
51
   (13, 'import_patrons', 'Importere låneropplysninger'),
52
   (13, 'edit_patrons', 'Perform batch modification of patrons'),
52
   (13, 'delete_anonymize_patrons', 'Slette utgåtte lånere og anonymisere lånehistorikk'),
53
   (13, 'delete_anonymize_patrons', 'Slette utgåtte lånere og anonymisere lånehistorikk'),
53
   (13, 'batch_upload_patron_images', 'Laste opp bilder av lånere enkeltvis eller en masse'),
54
   (13, 'batch_upload_patron_images', 'Laste opp bilder av lånere enkeltvis eller en masse'),
54
   (13, 'schedule_tasks', 'Planlegge oppgaver som skal kjøres'),
55
   (13, 'schedule_tasks', 'Planlegge oppgaver som skal kjøres'),
(-)a/installer/data/mysql/pl-PL/mandatory/userpermissions.sql (+1 lines)
Lines 28-33 INSERT INTO permissions (module_bit, code, description) VALUES Link Here
28
   (13, 'manage_staged_marc', 'Managed staged MARC records, including completing and reversing imports'),
28
   (13, 'manage_staged_marc', 'Managed staged MARC records, including completing and reversing imports'),
29
   (13, 'export_catalog', 'Export bibliographic and holdings data'),
29
   (13, 'export_catalog', 'Export bibliographic and holdings data'),
30
   (13, 'import_patrons', 'Import patron data'),
30
   (13, 'import_patrons', 'Import patron data'),
31
   (13, 'edit_patrons', 'Perform batch modification of patrons'),
31
   (13, 'delete_anonymize_patrons', 'Delete old borrowers and anonymize circulation history (deletes borrower reading history)'),
32
   (13, 'delete_anonymize_patrons', 'Delete old borrowers and anonymize circulation history (deletes borrower reading history)'),
32
   (13, 'batch_upload_patron_images', 'Upload patron images in batch or one at a time'),
33
   (13, 'batch_upload_patron_images', 'Upload patron images in batch or one at a time'),
33
   (13, 'schedule_tasks', 'Schedule tasks to run'),
34
   (13, 'schedule_tasks', 'Schedule tasks to run'),
(-)a/installer/data/mysql/updatedatabase.pl (+11 lines)
Lines 5146-5151 if ( C4::Context->preference("Version") < TransformToNum($DBversion) ) { Link Here
5146
    SetVersion($DBversion);
5146
    SetVersion($DBversion);
5147
}
5147
}
5148
5148
5149
5150
5151
5152
5153
$DBversion = "3.07.00.XXX";
5154
if ( C4::Context->preference("Version") < TransformToNum($DBversion) ) {
5155
    $dbh->do("INSERT IGNORE INTO permissions (module_bit, code, description) VALUES('13', 'edit_patrons', 'Perform batch modifivation of patrons')");
5156
    print "Upgrade to $DBversion done (Adds permissions flag for access to the patron modifications tool)\n";
5157
    SetVersion($DBversion);
5158
}
5159
5149
=head1 FUNCTIONS
5160
=head1 FUNCTIONS
5150
5161
5151
=head2 DropAllForeignKeys($table)
5162
=head2 DropAllForeignKeys($table)
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/modborrowers.tt (+316 lines)
Line 0 Link Here
1
[% USE KohaDates %]
2
[% INCLUDE 'doc-head-open.inc'%]
3
<title>Koha &rsaquo; Tools &rsaquo; [% IF ( del ) %]Batch item deletion[% ELSE %]Batch item modification[% END %] </title>
4
[% INCLUDE 'doc-head-close.inc' %]
5
[% INCLUDE 'calendar.inc' %]
6
<script type="text/javascript" src="[% themelang %]/lib/jquery/plugins/jquery.tablesorter.min.js"></script>
7
<script type="text/JavaScript" language="JavaScript">
8
//<![CDATA[
9
        var patron_attributes_lib = new Array();
10
        var patron_attributes_values = new Array();
11
        $(document).ready(function() {
12
            $("#borrowerst").tablesorter();
13
14
            $("#selectallbutton").click(function() {
15
                $("#borrowerst").find("input:checkbox").each(function() {
16
                    $(this).attr("checked", true);
17
                });
18
                return false;
19
            });
20
            $("#clearallbutton").click(function() {
21
                $("#borrowerst").find("input:checkbox").each(function() {
22
                    $(this).attr("checked", false);
23
                });
24
                return false;
25
            });
26
27
            var values = new Array();
28
            var lib = new Array();
29
            [% FOREACH pav IN patron_attributes_values %]
30
                values = new Array();
31
                lib = new Array();
32
                [% FOREACH option IN pav.options %]
33
                    values.push("[% option.lib %]");
34
                    lib.push("[% option.authorised_value %]");
35
                [% END %]
36
                patron_attributes_lib["[% pav.attribute_code %]"] = values;
37
                patron_attributes_values["[% pav.attribute_code %]"] = lib;
38
            [% END %]
39
40
            $('select[name="patron_attributes"]').change(function() {
41
                updateAttrValues(this);
42
            } );
43
44
            $('select[name="patron_attributes"]').change();
45
46
        } );
47
48
        function updateAttrValues (select_attr) {
49
            var attr_code = $(select_attr).val();
50
            var type = $(select_attr).find("option:selected").attr('data-type');
51
            var category = $(select_attr).find("option:selected").attr('data-category');
52
            var span = $(select_attr).parent().parent().find('span.patron_attributes_value');
53
            var information_category_node = $(select_attr).parent().parent().find('span.information_category');
54
            information_category_node.html("");
55
            if ( category.length > 0 ) {
56
                information_category_node.html('This attribute will be only applied to the borrower\'s category "' + category + '"');
57
            }
58
            if ( type == 'select' ) {
59
                var options = '<option value = ""></option>';
60
                for ( var i = 0 ; i < patron_attributes_values[attr_code].length ; i++ ) {
61
                    options += '<option value="'+patron_attributes_values[attr_code][i]+'">'+patron_attributes_lib[attr_code][i]+'</option>';
62
                }
63
                span.html('<select name="patron_attributes_value">' + options + '</select>');
64
            } else {
65
                span.html('<input type="text" name="patron_attributes_value"/>')
66
            }
67
        }
68
69
        function add_attributes() {
70
            var li_node = $("li.attributes:last");
71
            var li_clone = $(li_node).clone();
72
            if ( $(li_clone).find("a.delete").length == 0 ) {
73
                $(li_clone).append('[<a href="#" title="Delete" class="delete" onclick="del_attributes(this);return false;">X</a>]');
74
            }
75
            $(li_clone).find('select[name="patron_attributes"]').change(function() {
76
                updateAttrValues(this);
77
            } );
78
79
            $(li_clone).find('select[name="patron_attributes"]').change();
80
81
            $("#fields_list>ol").append(li_clone);
82
            update_attr_values();
83
        }
84
85
        function del_attributes(a_node) {
86
            $(a_node).parent('li').remove();
87
            update_attr_values();
88
        }
89
90
        function update_attr_values() {
91
            $("li.attributes").each(function(i) {
92
                $(this).find("input:checkbox").val("attr"+i+"_value");
93
            });
94
        }
95
        function clearDate(nodeid) {
96
            $("#"+nodeid).val("");
97
        }
98
99
//]]>
100
</script>
101
</head>
102
<body>
103
[% INCLUDE 'header.inc' %]
104
[% INCLUDE 'cat-search.inc' %]
105
106
<div id="breadcrumbs">
107
    <a href="/cgi-bin/koha/mainpage.pl">Home</a> &rsaquo;
108
    <a href="/cgi-bin/koha/tools/tools-home.pl">Tools</a> &rsaquo;
109
    <a href="/cgi-bin/koha/tools/modborrowers.pl">Patrons modification</a>
110
</div>
111
112
<div id="doc3" class="yui-t2">
113
    <div id="bd">
114
        <div id="yui-main">
115
            <div class="yui-b">
116
                [% IF ( op == 'show_form' ) %]
117
                <h1>Batch patrons modification</h1>
118
                <form method="post" enctype="multipart/form-data" action="/cgi-bin/koha/tools/modborrowers.pl">
119
                    <fieldset class="rows">
120
                    <legend>Use a file</legend>
121
                    <label for="uploadfile">File: </label> <input type="file" id="uploadfile" name="uploadfile" />
122
                    </fieldset>
123
                    <fieldset class="rows">
124
                        <legend>Or list cardnumbers one by one</legend>
125
                        <ol>
126
                            <li>
127
                              <label for="cardnumberlist">Carnumber list (one cardnumber per line): </label>
128
                              <textarea rows="10" cols="30" id="cardnumberlist" name="cardnumberlist">[% cardnumberlist %]</textarea>
129
                            </li>
130
                        </ol>
131
                    </fieldset>
132
                    <input type="hidden" name="op" value="show" />
133
                    <fieldset class="action">
134
                        <input type="submit" value="Continue" class="button" />
135
                        <a class="cancel" href="/cgi-bin/koha/tools/tools-home.pl">Cancel</a>
136
                    </fieldset>
137
                </form>
138
                [% END %]
139
140
                [% IF ( op == 'show' or op == 'show_results' ) %]
141
                    [% IF ( op == 'show' ) %]
142
                        <h1>Batch patrons modification</h1>
143
                    [% ELSE %]
144
                        <h1>Batch patrons results</h1>
145
                    [% END %]
146
                    [% IF ( notfoundcardnumbers ) %]
147
                        <div class="dialog alert"><p>Warning, the following cardnumbers were not found:</p></div>
148
                        <table style="margin:auto;">
149
                            <thead>
150
                                <tr><th>Cardnumbers not found</th></tr>
151
                            </thead>
152
                            <tbody>
153
                                [% FOREACH notfoundcardnumber IN notfoundcardnumbers %]
154
                                    <tr><td>[% notfoundcardnumber.cardnumber %]</td></tr>
155
                                [% END %]
156
                            </tbody>
157
                        </table>
158
                    [% END %]
159
160
                    [% IF ( op == 'show_results' ) %]
161
                        [% IF ( errors ) %]
162
                            Errors occured :
163
                            <ul class="warnings">
164
                            [% FOREACH error IN errors %]
165
                                [% IF ( error.error == 'can_not_update' ) %]
166
                                    <li>Can not update borrower with borrowernumber [% error.borrowernumber %]</li>
167
                                [% ELSE %]
168
                                    <li>[% error.error %]</li>
169
                                [% END %]
170
                            [% END %]
171
                            </ul>
172
                        [% END %]
173
                        <br/>
174
                    [% END %]
175
176
                    [% IF ( op == 'show' ) %]
177
                    <form name="f" action="modborrowers.pl" method="post">
178
                        <input type="hidden" name="op" value="do" />
179
                        [% IF ( borrowers ) %]
180
                            <div id="toolbar"><a id="selectallbutton" href="#">Select All</a> | <a id="clearallbutton" href="#">Clear All</a></div>
181
                        [% END %]
182
                    [% END %]
183
                            <div id="cataloguing_additem_itemlist">
184
                                <div style="overflow:auto">
185
                                    <table id="borrowerst">
186
                                        <thead>
187
                                            <tr>
188
                                                [% IF ( op == 'show' ) %]
189
                                                    <th>&nbsp;</th>
190
                                                [% END %]
191
                                                <th>Surname</th>
192
                                                <th>Firstname</th>
193
                                                <th>Branchname</th>
194
                                                <th>Categorycode</th>
195
                                                <th>Cardnumber</th>
196
                                                <th>dateenrolled</th>
197
                                                <th>dateexpiry</th>
198
                                                <th>debarred</th>
199
                                                [% FOREACH attrh IN attributes_header %]
200
                                                    <th>[% attrh.attribute %]</th>
201
                                                [% END %]
202
                                            </tr>
203
                                        </thead>
204
                                        <tbody>
205
                                            [% FOREACH borrower IN borrowers %]
206
                                                <tr>
207
                                                    [% IF ( op == 'show' ) %]
208
                                                        <td><input type="checkbox" name="borrowernumber" value="[% borrower.borrowernumber %]" checked="checked" /></td>
209
                                                    [% END %]
210
                                                    <td>[% borrower.surname %]</td>
211
                                                    <td>[% borrower.firstname %]</td>
212
                                                    <td>[% borrower.branchname %]</td>
213
                                                    <td>[% borrower.categorycode %]</td>
214
                                                    <td>[% borrower.cardnumber %]</td>
215
                                                    <td>[% borrower.dateenrolled | $KohaDates %]</td>
216
                                                    <td>[% borrower.dateexpiry | $KohaDates %]</td>
217
                                                    <td>[% borrower.debarred | $KohaDates %]</td>
218
                                                    [% FOREACH pa IN borrower.patron_attributes %]
219
                                                        [% IF ( pa.code ) %]
220
                                                            <td>[% pa.code %]=[% pa.value %]</td>
221
                                                        [% ELSE %]
222
                                                            <td></td>
223
                                                        [% END %]
224
                                                    [% END %]
225
                                                </tr>
226
                                            [% END %]
227
                                        </tbody>
228
                                    </table>
229
                                </div>
230
                            </div>
231
232
                            [% IF ( op == 'show' ) %]
233
                            <div id="cataloguing_additem_newitem">
234
                                <h2>Edit Patrons</h2>
235
                                <div class="hint">Checking the box right next the label will disable the entry and delete the values of that field on all selected patrons</div>
236
                                <fieldset class="rows" id="fields_list">
237
                                    <ol>
238
                                        [% FOREACH field IN fields %]
239
                                        <li>
240
                                            <label style="width:20em;">[% field.lib %]</label>
241
                                            [% IF field.mandatory %]
242
                                                <input type="checkbox" title="This field is mandatory" name="disable_input" value="[% field.name %]" readonly="readonly" onclick="return false;" />
243
                                            [% ELSE %]
244
                                                <input type="checkbox" title="Check to delete this field" name="disable_input" value="[% field.name %]" />
245
                                            [% END %]
246
                                            [% IF ( field.type == 'text' ) %]
247
                                                <input type="text" name="[% field.name %]" value="" />
248
                                            [% END %]
249
                                            [% IF ( field.type == 'select' ) %]
250
                                                [% IF field.option.size %]
251
                                                    <select name="[% field.name %]" >
252
                                                        [% FOREACH opt IN field.option %]
253
                                                            <option value="[% opt.value %]">[% opt.lib %]</option>
254
                                                        [% END %]
255
                                                    </select>
256
                                                [% ELSE %]
257
                                                    There is no value defined for [% field.name %]
258
                                                [% END %]
259
                                            [% END %]
260
                                            [% IF ( field.type == 'date' ) %]
261
                                                <img src="[% themelang %]/lib/calendar/cal.gif" style="cursor: pointer;" alt="Show Calendar" title="Show Calendar" id="[% field.name %]button"/>
262
                                                <input type="text" name="[% field.name %]" id="[% field.name %]" value="" size="10" maxlength="10" readonly />
263
                                                <a href="#" onclick="clearDate('[% field.name %]');return false;">X</a>
264
                                                <script type="text/javascript">
265
                                                 //<![CDATA[ 
266
                                                Calendar.setup({
267
                                                    inputField      : "[% field.name %]", 
268
                                                    button          : "[% field.name %]button",
269
                                                    ifFormat        : "[% DHTMLcalendar_dateformat %]",
270
                                                    onClose: function() { $("#[% field.name %]").change(); this.hide();}
271
                                                });
272
                                                //]]>
273
                                                </script>
274
                                            [% END %]
275
                                        </li>
276
                                        [% END %]
277
                                        [% IF ( patron_attributes_codes ) %]
278
                                            <li class="attributes">
279
                                                <label style="width:20em;">Attribute
280
                                                    <select name="patron_attributes">
281
                                                        [% FOREACH pac IN patron_attributes_codes %]
282
                                                            <option value="[% pac.attribute_code %]" data-type="[% pac.type %]" data-category="[% pac.category_lib %]">[% pac.attribute_lib %]</option>
283
                                                        [% END %]
284
                                                    </select>
285
                                                </label>
286
                                                <input type="checkbox" title="check to delete this field" name="disable_input" value="attr0_value" />
287
                                                <span class="patron_attributes_value"></span>
288
                                                <a href="#" title="Add an attribute" onclick="add_attributes(); return false;">+</a>
289
                                                <span class="information_category"></span>
290
                                            </li>
291
                                        [% END %]
292
                                    </ol>
293
                                </fieldset>
294
                                <fieldset class="action">
295
                                    <input type="submit" name="mainformsubmit" value="Save" />
296
                                    <a href="/cgi-bin/koha/tools/modborrowers.pl" class="cancel">Cancel</a>
297
                                </fieldset>
298
                            </div>
299
                        </form>
300
                        [% END %]
301
                [% END %]
302
                [% IF ( op == 'show_results' ) %]
303
                    <br/>
304
                    <a href="/cgi-bin/koha/tools/modborrowers.pl" title="new Batch patrons modification">new Batch patrons modification</a>
305
                [% END %]
306
            </div>
307
            </div>
308
            <div class="yui-b">
309
                [% INCLUDE 'tools-menu.inc' %]
310
            </div>
311
        </div>
312
    </div>
313
</div>
314
</body>
315
</html>
316
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/tools-home.tt (+5 lines)
Lines 45-50 Link Here
45
    <dd>Delete old borrowers and anonymize circulation history (deletes borrower reading history)</dd>
45
    <dd>Delete old borrowers and anonymize circulation history (deletes borrower reading history)</dd>
46
    [% END %]
46
    [% END %]
47
47
48
    [% IF ( CAN_user_tools_edit_patrons ) %]
49
    <dt><a href="/cgi-bin/koha/tools/modborrowers.pl">Patrons (Modification)</a></dt>
50
    <dd>Modify patrons</dd>
51
    [% END %]
52
48
    [% IF ( CAN_user_tools_moderate_tags ) %]
53
    [% IF ( CAN_user_tools_moderate_tags ) %]
49
    <dt><a href="/cgi-bin/koha/tags/review.pl">Tags</a> [% IF ( pendingtags ) %]<span class="holdcount"><a href="/cgi-bin/koha/tags/review.pl">[% pendingtags %]</a></span>[% END %]</dt>
54
    <dt><a href="/cgi-bin/koha/tags/review.pl">Tags</a> [% IF ( pendingtags ) %]<span class="holdcount"><a href="/cgi-bin/koha/tags/review.pl">[% pendingtags %]</a></span>[% END %]</dt>
50
	<dd>Moderate patron tags</dd>
55
	<dd>Moderate patron tags</dd>
(-)a/tools/modborrowers.pl (-1 / +356 lines)
Line 0 Link Here
0
- 
1
#!/usr/bin/perl
2
3
# Copyright 2012 BibLibre
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it under the
8
# terms of the GNU General Public License as published by the Free Software
9
# Foundation; either version 2 of the License, or (at your option) any later
10
# version.
11
#
12
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
13
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
14
# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License along
17
# with Koha; if not, write to the Free Software Foundation, Inc.,
18
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
20
# modborrowers.pl
21
#
22
# Batch Edit Patrons
23
# Modification for patron's fields:
24
# surname firstname branchcode categorycode sort1 sort2 dateenrolled dateexpiry debarred debarredcomment borrowernotes
25
# And for patron attributes.
26
27
use Modern::Perl;
28
use CGI;
29
use C4::Auth;
30
use C4::Branch;
31
use C4::Koha;
32
use C4::Members;
33
use C4::Members::Attributes;
34
use C4::Members::AttributeTypes qw/GetAttributeTypes_hashref/;
35
use C4::Output;
36
use List::MoreUtils qw /any uniq/;
37
38
my $input = new CGI;
39
my $op = $input->param('op') || 'show_form';
40
my ( $template, $loggedinuser, $cookie ) = get_template_and_user(
41
    {   template_name   => "tools/modborrowers.tmpl",
42
        query           => $input,
43
        type            => "intranet",
44
        authnotrequired => 0,
45
        flagsrequired   => { tools => "edit_patrons" },
46
    }
47
);
48
49
my %cookies   = parse CGI::Cookie($cookie);
50
my $sessionID = $cookies{'CGISESSID'}->value;
51
my $dbh       = C4::Context->dbh;
52
53
54
55
# Show borrower informations
56
if ( $op eq 'show' ) {
57
    my $filefh      = $input->upload('uploadfile');
58
    my $filecontent = $input->param('filecontent');
59
    my @borrowers;
60
    my @cardnumbers;
61
    my @notfoundcardnumbers;
62
63
    # Get cardnumbers from a file or the input area
64
    my @contentlist;
65
    if ($filefh) {
66
        while ( my $content = <$filefh> ) {
67
            $content =~ s/[\r\n]*$//g;
68
            push @cardnumbers, $content if $content;
69
        }
70
    } else {
71
        if ( my $list = $input->param('cardnumberlist') ) {
72
            push @cardnumbers, split( /\s\n/, $list );
73
        }
74
    }
75
76
    my $max_nb_attr = 0;
77
    for my $cardnumber ( @cardnumbers ) {
78
        my $borrower = GetBorrowerInfos( cardnumber => $cardnumber );
79
        if ( $borrower ) {
80
            $max_nb_attr = scalar( @{ $borrower->{patron_attributes} } )
81
                if scalar( @{ $borrower->{patron_attributes} } ) > $max_nb_attr;
82
            push @borrowers, $borrower;
83
        } else {
84
            push @notfoundcardnumbers, $cardnumber;
85
        }
86
    }
87
88
    # Just for a correct display
89
    for my $borrower ( @borrowers ) {
90
        my $length = scalar( @{ $borrower->{patron_attributes} } );
91
        push @{ $borrower->{patron_attributes} }, {} for ( $length .. $max_nb_attr - 1);
92
    }
93
94
    # Construct the patron attributes list
95
    my @patron_attributes_values;
96
    my @patron_attributes_codes;
97
    my $patron_attribute_types = C4::Members::AttributeTypes::GetAttributeTypes_hashref('all');
98
    my $patron_categories = C4::Members::GetBorrowercategoryList;
99
    for ( values %$patron_attribute_types ) {
100
        my $attr_type = C4::Members::AttributeTypes->fetch( $_->{code} );
101
        my $options = $attr_type->authorised_value_category
102
            ? GetAuthorisedValues( $attr_type->authorised_value_category )
103
            : undef;
104
        push @patron_attributes_values,
105
            {
106
                attribute_code => $_->{code},
107
                options        => $options,
108
            };
109
110
        my $category_code = $_->{category_code};
111
        my ( $category_lib ) = map {
112
            ( defined $category_code and $_->{categorycode} eq $category_code ) ? $_->{description} : ()
113
        } @$patron_categories;
114
        push @patron_attributes_codes,
115
            {
116
                attribute_code => $_->{code},
117
                attribute_lib  => $_->{description},
118
                category_lib   => $category_lib,
119
                type           => $attr_type->authorised_value_category ? 'select' : 'text',
120
            };
121
    }
122
123
    my @attributes_header = ();
124
    for ( 1 .. scalar( $max_nb_attr ) ) {
125
        push @attributes_header, { attribute => "Attributes $_" };
126
    }
127
    $template->param( borrowers => \@borrowers );
128
    $template->param( attributes_header => \@attributes_header );
129
    @notfoundcardnumbers = map { { cardnumber => $_ } } @notfoundcardnumbers;
130
    $template->param( notfoundcardnumbers => \@notfoundcardnumbers )
131
        if @notfoundcardnumbers;
132
133
    # Construct drop-down list values
134
    my $branches = GetBranchesLoop;
135
    my @branches_option;
136
    push @branches_option, { value => $_->{value}, lib => $_->{branchname} } for @$branches;
137
    unshift @branches_option, { value => "", lib => "" };
138
    my $categories = GetBorrowercategoryList;
139
    my @categories_option;
140
    push @categories_option, { value => $_->{categorycode}, lib => $_->{description} } for @$categories;
141
    unshift @categories_option, { value => "", lib => "" };
142
    my $bsort1 = GetAuthorisedValues("Bsort1");
143
    my @sort1_option;
144
    push @sort1_option, { value => $_->{authorised_value}, lib => $_->{lib} } for @$bsort1;
145
    unshift @sort1_option, { value => "", lib => "" }
146
        if @sort1_option;
147
    my $bsort2 = GetAuthorisedValues("Bsort2");
148
    my @sort2_option;
149
    push @sort2_option, { value => $_->{authorised_value}, lib => $_->{lib} } for @$bsort2;
150
    unshift @sort2_option, { value => "", lib => "" }
151
        if @sort2_option;
152
153
    my @mandatoryFields = split( /\|/, C4::Context->preference("BorrowerMandatoryField") );
154
155
    my @fields = (
156
        {
157
            name => "surname",
158
            lib  => "Surname",
159
            type => "text",
160
            mandatory => ( grep /surname/, @mandatoryFields ) ? 1 : 0
161
        }
162
        ,
163
        {
164
            name => "firstname",
165
            lib  => "Firstname",
166
            type => "text",
167
            mandatory => ( grep /surname/, @mandatoryFields ) ? 1 : 0,
168
        }
169
        ,
170
        {
171
            name => "branchcode",
172
            lib  => "Branchname",
173
            type => "select",
174
            option => \@branches_option,
175
            mandatory => ( grep /branchcode/, @mandatoryFields ) ? 1 : 0,
176
        }
177
        ,
178
        {
179
            name => "categorycode",
180
            lib  => "Category",
181
            type => "select",
182
            option => \@categories_option,
183
            mandatory => ( grep /categorycode/, @mandatoryFields ) ? 1 : 0,
184
        }
185
        ,
186
        {
187
            name => "sort1",
188
            lib  => "Sort 1",
189
            type => "select",
190
            option => \@sort1_option,
191
            mandatory => ( grep /sort1/, @mandatoryFields ) ? 1 : 0,
192
        }
193
        ,
194
        {
195
            name => "sort2",
196
            lib  => "Sort 2",
197
            type => "select",
198
            option => \@sort2_option,
199
            mandatory => ( grep /sort2/, @mandatoryFields ) ? 1 : 0,
200
        }
201
        ,
202
        {
203
            name => "dateenrolled",
204
            lib  => "Date enrolled",
205
            type => "date",
206
            mandatory => ( grep /dateenrolled/, @mandatoryFields ) ? 1 : 0,
207
        }
208
        ,
209
        {
210
            name => "dateexpiry",
211
            lib  => "Date expiry",
212
            type => "date",
213
            mandatory => ( grep /dateexpiry/, @mandatoryFields ) ? 1 : 0,
214
        }
215
        ,
216
        {
217
            name => "debarred",
218
            lib  => "Debarred",
219
            type => "date",
220
            mandatory => ( grep /debarred/, @mandatoryFields ) ? 1 : 0,
221
        }
222
        ,
223
        {
224
            name => "debarredcomment",
225
            lib  => "Debarred comment",
226
            type => "text",
227
            mandatory => ( grep /debarredcomment/, @mandatoryFields ) ? 1 : 0,
228
        }
229
        ,
230
        {
231
            name => "borrowernotes",
232
            lib  => "Borrower Notes",
233
            type => "text",
234
            mandatory => ( grep /borrowernotes/, @mandatoryFields ) ? 1 : 0,
235
        }
236
    );
237
238
    $template->param('patron_attributes_codes', \@patron_attributes_codes);
239
    $template->param('patron_attributes_values', \@patron_attributes_values);
240
241
    $template->param( fields => \@fields );
242
    $template->param( DHTMLcalendar_dateformat => C4::Dates->DHTMLcalendar() );
243
}
244
245
# Process modifications
246
if ( $op eq 'do' ) {
247
248
    my @disabled = $input->param('disable_input');
249
    my $infos;
250
    for my $field ( qw/surname firstname branchcode categorycode sort1 sort2 dateenrolled dateexpiry debarred debarredcomment borrowernotes/ ) {
251
        my $value = $input->param($field);
252
        $infos->{$field} = $value if $value;
253
        $infos->{$field} = "" if grep { /^$field$/ } @disabled;
254
    }
255
256
    my @attributes = $input->param('patron_attributes');
257
    my @attr_values = $input->param('patron_attributes_value');
258
259
    my @errors;
260
    my @borrowernumbers = $input->param('borrowernumber');
261
    # For each borrower selected
262
    for my $borrowernumber ( @borrowernumbers ) {
263
        # If at least one field are filled, we want to modify the borrower
264
        if ( defined $infos ) {
265
            $infos->{borrowernumber} = $borrowernumber;
266
            my $success = ModMember(%$infos);
267
            push @errors, { error => "can_not_update", borrowernumber => $infos->{borrowernumber} } if not $success;
268
        }
269
270
        #
271
        my $borrower_categorycode = GetBorrowerCategorycode $borrowernumber;
272
        my $i=0;
273
        for ( @attributes ) {
274
            my $attribute;
275
            $attribute->{code} = $_;
276
            $attribute->{attribute} = $attr_values[$i];
277
            my $attr_type = C4::Members::AttributeTypes->fetch( $_ );
278
            # If this borrower is not in the category of this attribute, we don't want to modify this attribute
279
            ++$i and next if $attr_type->{category_code} and $attr_type->{category_code} ne $borrower_categorycode;
280
            my $valuename = "attr" . $i . "_value";
281
            if ( grep { /^$valuename$/ } @disabled ) {
282
                # The attribute is disabled, we remove it for this borrower !
283
                eval {
284
                    C4::Members::Attributes::DeleteBorrowerAttribute( $borrowernumber, $attribute );
285
                };
286
                push @errors, { error => $@ } if $@;
287
            } else {
288
                # Attribute's value is empty, we don't want to modify it
289
                ++$i and next if not $attribute->{attribute};
290
291
                eval {
292
                    C4::Members::Attributes::UpdateBorrowerAttribute( $borrowernumber, $attribute );
293
                };
294
                push @errors, { error => $@ } if $@;
295
            }
296
            $i++;
297
        }
298
    }
299
    $op = "show_results"; # We have process modifications, the user want to view its
300
301
    # Construct the results list
302
    my @borrowers;
303
    my $max_nb_attr = 0;
304
    for my $borrowernumber ( @borrowernumbers ) {
305
        my $borrower = GetBorrowerInfos( borrowernumber => $borrowernumber );
306
        if ( $borrower ) {
307
            $max_nb_attr = scalar( @{ $borrower->{patron_attributes} } )
308
                if scalar( @{ $borrower->{patron_attributes} } ) > $max_nb_attr;
309
            push @borrowers, $borrower;
310
        }
311
    }
312
    my @patron_attributes_option;
313
    for my $borrower ( @borrowers ) {
314
        push @patron_attributes_option, { value => "$_->{code}", lib => $_->{code} } for @{ $borrower->{patron_attributes} };
315
        my $length = scalar( @{ $borrower->{patron_attributes} } );
316
        push @{ $borrower->{patron_attributes} }, {} for ( $length .. $max_nb_attr - 1);
317
    }
318
319
    my @attributes_header = ();
320
    for ( 1 .. scalar( $max_nb_attr ) ) {
321
        push @attributes_header, { attribute => "Attributes $_" };
322
    }
323
324
    $template->param( borrowers => \@borrowers );
325
    $template->param( attributes_header => \@attributes_header );
326
327
    $template->param( borrowers => \@borrowers );
328
    $template->param( errors => \@errors );
329
}
330
331
$template->param(
332
    op => $op,
333
);
334
output_html_with_http_headers $input, $cookie, $template->output;
335
exit;
336
337
sub GetBorrowerInfos {
338
    my ( %info ) = @_;
339
    my $borrower = GetMember( %info );
340
    if ( $borrower ) {
341
        $borrower->{branchname} = GetBranchName( $borrower->{branchcode} );
342
        for ( qw(dateenrolled dateexpiry debarred) ) {
343
            my $userdate = $borrower->{$_};
344
            unless ($userdate && $userdate ne "0000-00-00" and $userdate ne "9999-12-31") {
345
                $borrower->{$_} = '';
346
                next;
347
            }
348
            $borrower->{$_} = $userdate || '';
349
        }
350
        $borrower->{category_description} = GetBorrowercategory( $borrower->{categorycode} )->{description};
351
        my $attr_loop = C4::Members::Attributes::GetBorrowerAttributes( $borrower->{borrowernumber} );
352
        $borrower->{patron_attributes} = $attr_loop;
353
    }
354
    return $borrower;
355
}
356

Return to bug 5742