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

(-)a/C4/Members.pm (-141 / +24 lines)
Lines 32-38 use C4::Reserves; Link Here
32
use C4::Accounts;
32
use C4::Accounts;
33
use C4::Biblio;
33
use C4::Biblio;
34
use C4::Letters;
34
use C4::Letters;
35
use C4::SQLHelper qw(InsertInTable UpdateInTable SearchInTable);
36
use C4::Members::Attributes qw(SearchIdMatchingAttribute UpdateBorrowerAttribute);
35
use C4::Members::Attributes qw(SearchIdMatchingAttribute UpdateBorrowerAttribute);
37
use C4::NewsChannels; #get slip news
36
use C4::NewsChannels; #get slip news
38
use DateTime;
37
use DateTime;
Lines 157-295 This module contains routines for adding, modifying and deleting members/patrons Link Here
157
156
158
=head1 FUNCTIONS
157
=head1 FUNCTIONS
159
158
160
=head2 Search
161
162
  $borrowers_result_array_ref = &Search($filter,$orderby, $limit, 
163
                       $columns_out, $search_on_fields,$searchtype);
164
165
Looks up patrons (borrowers) on filter. A wrapper for SearchInTable('borrowers').
166
167
For C<$filter>, C<$orderby>, C<$limit>, C<&columns_out>, C<&search_on_fields> and C<&searchtype>
168
refer to C4::SQLHelper:SearchInTable().
169
170
Special C<$filter> key '' is effectively expanded to search on surname firstname othernamescw
171
and cardnumber unless C<&search_on_fields> is defined
172
173
Examples:
174
175
  $borrowers = Search('abcd', 'cardnumber');
176
177
  $borrowers = Search({''=>'abcd', category_type=>'I'}, 'surname');
178
179
=cut
180
181
sub _express_member_find {
182
    my ($filter) = @_;
183
184
    # this is used by circulation everytime a new borrowers cardnumber is scanned
185
    # so we can check an exact match first, if that works return, otherwise do the rest
186
    my $dbh   = C4::Context->dbh;
187
    my $query = "SELECT borrowernumber FROM borrowers WHERE cardnumber = ?";
188
    if ( my $borrowernumber = $dbh->selectrow_array($query, undef, $filter) ) {
189
        return( {"borrowernumber"=>$borrowernumber} );
190
    }
191
192
    my ($search_on_fields, $searchtype);
193
    if ( length($filter) == 1 ) {
194
        $search_on_fields = [ qw(surname) ];
195
        $searchtype = 'start_with';
196
    } else {
197
        $search_on_fields = [ qw(surname firstname othernames cardnumber) ];
198
        $searchtype = 'contain';
199
    }
200
201
    return (undef, $search_on_fields, $searchtype);
202
}
203
204
sub Search {
205
    my ( $filter, $orderby, $limit, $columns_out, $search_on_fields, $searchtype, $not_attributes ) = @_;
206
207
    my $search_string;
208
    my $found_borrower;
209
210
    if ( my $fr = ref $filter ) {
211
        if ( $fr eq "HASH" ) {
212
            if ( my $search_string = $filter->{''} ) {
213
                my ($member_filter, $member_search_on_fields, $member_searchtype) = _express_member_find($search_string);
214
                if ($member_filter) {
215
                    $filter = $member_filter;
216
                    $found_borrower = 1;
217
                } else {
218
                    $search_on_fields ||= $member_search_on_fields;
219
                    $searchtype ||= $member_searchtype;
220
                }
221
            }
222
        }
223
        else {
224
            $search_string = $filter;
225
        }
226
    }
227
    else {
228
        $search_string = $filter;
229
        my ($member_filter, $member_search_on_fields, $member_searchtype) = _express_member_find($search_string);
230
        if ($member_filter) {
231
            $filter = $member_filter;
232
            $found_borrower = 1;
233
        } else {
234
            $search_on_fields ||= $member_search_on_fields;
235
            $searchtype ||= $member_searchtype;
236
        }
237
    }
238
239
    if ( !$found_borrower && C4::Context->preference('ExtendedPatronAttributes') && $search_string && !$not_attributes ) {
240
        my $matching_records = C4::Members::Attributes::SearchIdMatchingAttribute($search_string);
241
        if(scalar(@$matching_records)>0) {
242
            if ( my $fr = ref $filter ) {
243
                if ( $fr eq "HASH" ) {
244
                    my %f = %$filter;
245
                    $filter = [ $filter ];
246
                    delete $f{''};
247
                    push @$filter, { %f, "borrowernumber"=>$$matching_records };
248
                }
249
                else {
250
                    push @$filter, {"borrowernumber"=>$matching_records};
251
                }
252
            }
253
            else {
254
                $filter = [ $filter ];
255
                push @$filter, {"borrowernumber"=>$matching_records};
256
            }
257
        }
258
    }
259
260
    # $showallbranches was not used at the time SearchMember() was mainstreamed into Search().
261
    # Mentioning for the reference
262
263
    if ( C4::Context->preference("IndependentBranches") ) { # && !$showallbranches){
264
        if ( my $userenv = C4::Context->userenv ) {
265
            my $branch =  $userenv->{'branch'};
266
            if ( !C4::Context->IsSuperLibrarian() && $branch ){
267
                if (my $fr = ref $filter) {
268
                    if ( $fr eq "HASH" ) {
269
                        $filter->{branchcode} = $branch;
270
                    }
271
                    else {
272
                        foreach (@$filter) {
273
                            $_ = { '' => $_ } unless ref $_;
274
                            $_->{branchcode} = $branch;
275
                        }
276
                    }
277
                }
278
                else {
279
                    $filter = { '' => $filter, branchcode => $branch };
280
                }
281
            }
282
        }
283
    }
284
285
    if ($found_borrower) {
286
        $searchtype = "exact";
287
    }
288
    $searchtype ||= "start_with";
289
290
    return SearchInTable( "borrowers", $filter, $orderby, $limit, $columns_out, $search_on_fields, $searchtype );
291
}
292
293
=head2 GetMemberDetails
159
=head2 GetMemberDetails
294
160
295
($borrower) = &GetMemberDetails($borrowernumber, $cardnumber);
161
($borrower) = &GetMemberDetails($borrowernumber, $cardnumber);
Lines 797-804 sub ModMember { Link Here
797
        }
663
        }
798
    }
664
    }
799
    my $old_categorycode = GetBorrowerCategorycode( $data{borrowernumber} );
665
    my $old_categorycode = GetBorrowerCategorycode( $data{borrowernumber} );
800
    my $execute_success=UpdateInTable("borrowers",\%data);
666
801
    if ($execute_success) { # only proceed if the update was a success
667
    # get only the columns of a borrower
668
    my $schema = Koha::Database->new()->schema;
669
    my @columns = $schema->source('Borrower')->columns;
670
    my $new_borrower = { map { join(' ', @columns) =~ /$_/ ? ( $_ => $data{$_} ) : () } keys(%data) };
671
    delete $new_borrower->{flags};
672
673
    my $rs = $schema->resultset('Borrower')->search({
674
        borrowernumber => $new_borrower->{borrowernumber},
675
     });
676
    my $execute_success = $rs->update($new_borrower);
677
    if ($execute_success ne '0E0') { # only proceed if the update was a success
802
        # ok if its an adult (type) it may have borrowers that depend on it as a guarantor
678
        # ok if its an adult (type) it may have borrowers that depend on it as a guarantor
803
        # so when we update information for an adult we should check for guarantees and update the relevant part
679
        # so when we update information for an adult we should check for guarantees and update the relevant part
804
        # of their records, ie addresses and phone numbers
680
        # of their records, ie addresses and phone numbers
Lines 857-862 Returns as undef upon any db error without further processing Link Here
857
sub AddMember {
733
sub AddMember {
858
    my (%data) = @_;
734
    my (%data) = @_;
859
    my $dbh = C4::Context->dbh;
735
    my $dbh = C4::Context->dbh;
736
    my $schema = Koha::Database->new()->schema;
860
737
861
    # generate a proper login if none provided
738
    # generate a proper login if none provided
862
    $data{'userid'} = Generate_Userid( $data{'borrowernumber'}, $data{'firstname'}, $data{'surname'} )
739
    $data{'userid'} = Generate_Userid( $data{'borrowernumber'}, $data{'firstname'}, $data{'surname'} )
Lines 872-880 sub AddMember { Link Here
872
        $data{'dateenrolled'} = C4::Dates->new()->output("iso");
749
        $data{'dateenrolled'} = C4::Dates->new()->output("iso");
873
    }
750
    }
874
751
875
    my $patron_category =
752
    my $patron_category = $schema->resultset('Category')->find( $data{'categorycode'} );
876
      Koha::Database->new()->schema()->resultset('Category')
877
      ->find( $data{'categorycode'} );
878
    $data{'privacy'} =
753
    $data{'privacy'} =
879
        $patron_category->default_privacy() eq 'default' ? 1
754
        $patron_category->default_privacy() eq 'default' ? 1
880
      : $patron_category->default_privacy() eq 'never'   ? 2
755
      : $patron_category->default_privacy() eq 'never'   ? 2
Lines 885-891 sub AddMember { Link Here
885
760
886
    # create a disabled account if no password provided
761
    # create a disabled account if no password provided
887
    $data{'password'} = ($data{'password'})? hash_password($data{'password'}) : '!';
762
    $data{'password'} = ($data{'password'})? hash_password($data{'password'}) : '!';
888
    $data{'borrowernumber'}=InsertInTable("borrowers",\%data);
763
    $data{'dateofbirth'} = undef if( not $data{'dateofbirth'} );
764
765
    # get only the columns of Borrower
766
    my @columns = $schema->source('Borrower')->columns;
767
    my $new_member = { map { join(' ',@columns) =~ /$_/ ? ( $_ => $data{$_} )  : () } keys(%data) } ;
768
    delete $new_member->{borrowernumber};
769
770
    my $rs = $schema->resultset('Borrower');
771
    $data{borrowernumber} = $rs->create($new_member)->id;
889
772
890
    # If NorwegianPatronDBEnable is enabled, we set syncstatus to something that a
773
    # If NorwegianPatronDBEnable is enabled, we set syncstatus to something that a
891
    # cronjob will use for syncing with NL
774
    # cronjob will use for syncing with NL
Lines 904-910 sub AddMember { Link Here
904
787
905
    AddEnrolmentFeeIfNeeded( $data{categorycode}, $data{borrowernumber} );
788
    AddEnrolmentFeeIfNeeded( $data{categorycode}, $data{borrowernumber} );
906
789
907
    return $data{'borrowernumber'};
790
    return $data{borrowernumber};
908
}
791
}
909
792
910
=head2 Check_Userid
793
=head2 Check_Userid
(-)a/t/db_dependent/Members.t (-63 / +4 lines)
Lines 17-23 Link Here
17
17
18
use Modern::Perl;
18
use Modern::Perl;
19
19
20
use Test::More tests => 72;
20
use Test::More tests => 61;
21
use Test::MockModule;
21
use Test::MockModule;
22
use Data::Dumper;
22
use Data::Dumper;
23
use C4::Context;
23
use C4::Context;
Lines 47-54 my $PHONE = "555-12123"; Link Here
47
# XXX should be randomised and checked against the database
47
# XXX should be randomised and checked against the database
48
my $IMPOSSIBLE_CARDNUMBER = "XYZZZ999";
48
my $IMPOSSIBLE_CARDNUMBER = "XYZZZ999";
49
49
50
my $INDEPENDENT_BRANCHES_PREF = 'IndependentBranches';
51
52
# XXX make a non-commit transaction and rollback rather than insert/delete
50
# XXX make a non-commit transaction and rollback rather than insert/delete
53
51
54
#my ($usernum, $userid, $usercnum, $userfirstname, $usersurname, $userbranch, $branchname, $userflags, $emailaddress, $branchprinter)= @_;
52
#my ($usernum, $userid, $usercnum, $userfirstname, $usersurname, $userbranch, $branchname, $userflags, $emailaddress, $branchprinter)= @_;
Lines 128-188 ok ( $changedmember->{firstname} eq $CHANGED_FIRSTNAME && Link Here
128
     , "Member Changed")
126
     , "Member Changed")
129
  or diag("Mismatching member details: ".Dumper($member, $changedmember));
127
  or diag("Mismatching member details: ".Dumper($member, $changedmember));
130
128
131
C4::Context->set_preference( $INDEPENDENT_BRANCHES_PREF, '0' );
132
C4::Context->clear_syspref_cache();
133
134
my $results = Search($CARDNUMBER);
135
ok (@$results == 1, "Search cardnumber returned only one result")
136
  or diag("Multiple members with Card $CARDNUMBER: ".Dumper($results));
137
ok (_find_member($results), "Search cardnumber")
138
  or diag("Card $CARDNUMBER not found in the resultset: ".Dumper($results));
139
140
my @searchstring=($SURNAME);
141
$results = Search(\@searchstring);
142
ok (_find_member($results), "Search (arrayref)")
143
  or diag("Card $CARDNUMBER not found in the resultset: ".Dumper($results));
144
145
$results = Search(\@searchstring,undef,undef,undef,["surname"]);
146
ok (_find_member($results), "Surname Search (arrayref)")
147
  or diag("Card $CARDNUMBER not found in the resultset: ".Dumper($results));
148
149
$results = Search("$CHANGED_FIRSTNAME $SURNAME", "surname");
150
ok (_find_member($results), "Full name  Search (string)")
151
  or diag("Card $CARDNUMBER not found in the resultset: ".Dumper($results));
152
153
@searchstring=($PHONE);
154
$results = Search(\@searchstring,undef,undef,undef,["phone"]);
155
ok (_find_member($results), "Phone Search (arrayref)")
156
  or diag("Card $CARDNUMBER not found in the resultset: ".Dumper($results));
157
158
$results = Search($PHONE,undef,undef,undef,["phone"]);
159
ok (_find_member($results), "Phone Search (string)")
160
  or diag("Card $CARDNUMBER not found in the resultset: ".Dumper($results));
161
162
C4::Context->set_preference( $INDEPENDENT_BRANCHES_PREF, '1' );
163
C4::Context->clear_syspref_cache();
164
165
$results = Search("$CHANGED_FIRSTNAME $SURNAME", "surname");
166
ok (!_find_member($results), "Full name  Search (string) for independent branches, different branch")
167
  or diag("Card $CARDNUMBER found in the resultset for independent branches: ".Dumper(C4::Context->preference($INDEPENDENT_BRANCHES_PREF), $results));
168
169
@searchstring=($SURNAME);
170
$results = Search(\@searchstring);
171
ok (!_find_member($results), "Search (arrayref) for independent branches, different branch")
172
  or diag("Card $CARDNUMBER found in the resultset for independent branches: ".Dumper(C4::Context->preference($INDEPENDENT_BRANCHES_PREF), $results));
173
174
$USERENV[$BRANCH_IDX] = $BRANCHCODE;
175
C4::Context->set_userenv ( @USERENV );
176
177
$results = Search("$CHANGED_FIRSTNAME $SURNAME", "surname");
178
ok (_find_member($results), "Full name  Search (string) for independent branches, same branch")
179
  or diag("Card $CARDNUMBER not found in the resultset for independent branches: ".Dumper(C4::Context->preference($INDEPENDENT_BRANCHES_PREF), $results));
180
181
@searchstring=($SURNAME);
182
$results = Search(\@searchstring);
183
ok (_find_member($results), "Search (arrayref) for independent branches, same branch")
184
  or diag("Card $CARDNUMBER not found in the resultset for independent branches: ".Dumper(C4::Context->preference($INDEPENDENT_BRANCHES_PREF), $results));
185
186
C4::Context->set_preference( 'CardnumberLength', '' );
129
C4::Context->set_preference( 'CardnumberLength', '' );
187
C4::Context->clear_syspref_cache();
130
C4::Context->clear_syspref_cache();
188
131
Lines 263-271 is( @$messages, 0, 'DeleteMessage deletes a message correctly' ); Link Here
263
206
264
# clean up 
207
# clean up 
265
DelMember($member->{borrowernumber});
208
DelMember($member->{borrowernumber});
266
$results = Search($CARDNUMBER,undef,undef,undef,["cardnumber"]);
209
my $borrower = GetMember( cardnumber => $CARDNUMBER );
267
ok (!_find_member($results), "Delete member")
210
is( $borrower, undef, 'DelMember should remove the patron' );
268
  or diag("Card $CARDNUMBER found for the deleted member in the resultset: ".Dumper($results));
269
211
270
# Check_Userid tests
212
# Check_Userid tests
271
%data = (
213
%data = (
Lines 295-301 is( Check_Userid( 'tomasito.none', '' ), 0, Link Here
295
    'userid not unique (blank borrowernumber)' );
237
    'userid not unique (blank borrowernumber)' );
296
is( Check_Userid( 'tomasito.none', $new_borrowernumber ), 0,
238
is( Check_Userid( 'tomasito.none', $new_borrowernumber ), 0,
297
    'userid not unique (second borrowernumber passed)' );
239
    'userid not unique (second borrowernumber passed)' );
298
my $borrower = GetMember( borrowernumber => $new_borrowernumber );
240
$borrower = GetMember( borrowernumber => $new_borrowernumber );
299
ok( $borrower->{userid} ne 'tomasito', "Borrower with duplicate userid has new userid generated" );
241
ok( $borrower->{userid} ne 'tomasito', "Borrower with duplicate userid has new userid generated" );
300
242
301
$data{ cardnumber } = "234567890";
243
$data{ cardnumber } = "234567890";
302
- 

Return to bug 12633