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

(-)a/Koha/Patrons.pm (-144 / +281 lines)
Lines 59-94 sub search_limited { Link Here
59
    my @restricted_branchcodes;
59
    my @restricted_branchcodes;
60
    if ( $userenv and $userenv->{number} ) {
60
    if ( $userenv and $userenv->{number} ) {
61
        my $logged_in_user = Koha::Patrons->find( $userenv->{number} );
61
        my $logged_in_user = Koha::Patrons->find( $userenv->{number} );
62
        @restricted_branchcodes = $logged_in_user->libraries_where_can_see_patrons;
62
        @restricted_branchcodes =
63
          $logged_in_user->libraries_where_can_see_patrons;
63
    }
64
    }
64
    $params->{'me.branchcode'} = { -in => \@restricted_branchcodes } if @restricted_branchcodes;
65
    $params->{'me.branchcode'} = { -in => \@restricted_branchcodes }
66
      if @restricted_branchcodes;
65
    return $self->search( $params, $attributes );
67
    return $self->search( $params, $attributes );
66
}
68
}
67
69
68
=head3 filter_by_is_guarantor
70
=head3 filter_by_is_guarantor
69
71
70
    Koha::Patrons->filter_by_is_guarantor(1);
72
    $guarantors = Koha::Patrons->filter_by_is_guarantor;
73
    $guarantors = Koha::Patrons->filter_by_is_guarantor($enabled);
71
74
72
Returns patrons filtered by whether they have a guarantor, are a guarantor or are not a guarantor.
75
Returns patrons that are guarantors.
73
76
74
=head4 options
77
=head4 options
75
78
76
=over 4
79
=over 4
77
80
78
=item undef - do not apply filter
81
=item 0 - boolean to disable the filter
79
82
 
80
=item 1 - boolean to limit to NOT guarantors
83
=item 1 - boolean to enable the filter (default)
81
84
 
82
=item 0 - boolean limit to ONLY guarantors
83
84
=back
85
=back
85
86
86
=cut
87
=cut
87
88
88
sub filter_by_is_guarantor {
89
sub filter_by_is_guarantor {
89
    my ( $self, $option ) = @_;
90
    my ( $self, $enabled ) = @_;
90
91
91
    return $self unless defined($option);
92
    # Noop if explicitly disabled by param
93
    return $self if ( defined($enabled) && !$enabled );
92
94
93
    my $guarantorList = Koha::Patron::Relationships->search(
95
    my $guarantorList = Koha::Patron::Relationships->search(
94
        {},
96
        {},
Lines 100-137 sub filter_by_is_guarantor { Link Here
100
102
101
    # Patrons who are guarantors
103
    # Patrons who are guarantors
102
    return $self->search(
104
    return $self->search(
103
        { 'me.borrowernumber' => { '-in' => $guarantorList } } )
105
        { 'me.borrowernumber' => { '-in' => $guarantorList } } );
104
      if $option;
105
106
106
    # Patrons who are not guarantors
107
    return $self->search(
108
        { 'me.borrowernumber' => { '-not_in' => $guarantorList } } );
109
}
107
}
110
108
111
=head3 filter_by_has_guarantor
109
=head3 filter_by_is_not_guarantor
112
110
113
    Koha::Patrons->filter_by_has_guarantor(1);
111
    $non_guarantors = Koha::Patrons->filter_by_is_not_guarantor;
112
    $non_guarantors = Koha::Patrons->filter_by_is_not_guarantor($enabled);
114
113
115
Returns patrons filtered by whether they have a guarantor, are a guarantor or are not a guarantor.
114
Returns patrons that are not guarantors.
116
115
117
=head4 options
116
=head4 options
118
117
119
=over 4
118
=over 4
120
119
121
=item undef - do not apply filter
120
=item 0 - boolean to disable the filter
121
 
122
=item 1 - boolean to enable the filter (default)
123
 
124
=back
125
126
=cut
127
128
sub filter_by_is_not_guarantor {
129
    my ( $self, $enabled ) = @_;
130
131
    # Noop if explicitly disabled by param
132
    return $self if ( defined($enabled) && !$enabled );
133
134
    my $guarantorList = Koha::Patron::Relationships->search(
135
        {},
136
        {
137
            columns  => ['guarantor_id'],
138
            distinct => 1
139
        }
140
    )->_resultset->as_query;
141
142
    # Patrons who are not guarantors
143
    return $self->search(
144
        { 'me.borrowernumber' => { '-not_in' => $guarantorList } } );
145
}
146
147
=head3 filter_by_is_guarantee
122
148
123
=item 1 - boolean to limit to users who have a guarantor
149
    $guarantees = Koha::Patrons->filter_by_is_guarantee;
150
    $guarantees = Koha::Patrons->filter_by_is_guarantee($enabled);
124
151
125
=item 0 - boolean to limit to users who do not have a guarantor
152
Returns patrons that are guaranteed, have a guarantor.
126
153
154
=head4 options
155
156
=over 4
157
158
=item 0 - boolean to disable the filter
159
 
160
=item 1 - boolean to enable the filter (default)
161
 
127
=back
162
=back
128
163
129
=cut
164
=cut
130
165
131
sub filter_by_has_guarantor {
166
sub filter_by_is_guarantee {
132
    my ( $self, $option ) = @_;
167
    my ( $self, $enabled ) = @_;
133
168
134
    return $self unless defined($option);
169
    # Noop if explicitly disabled by param
170
    return $self if ( defined($enabled) && !$enabled );
135
171
136
    my $guaranteeList = Koha::Patron::Relationships->search(
172
    my $guaranteeList = Koha::Patron::Relationships->search(
137
        {},
173
        {},
Lines 143-161 sub filter_by_has_guarantor { Link Here
143
179
144
    # Patrons who have guarantors
180
    # Patrons who have guarantors
145
    return $self->search(
181
    return $self->search(
146
        { 'me.borrowernumber' => { '-in' => $guaranteeList } } )
182
        { 'me.borrowernumber' => { '-in' => $guaranteeList } } );
147
      if $option;
183
}
184
185
=head3 filter_by_is_not_guarantee
186
187
    $non_guarantees = Koha::Patrons->filter_by_is_not_guarantee;
188
    $non_guarantees = Koha::Patrons->filter_by_is_not_guarantee($enabled);
189
190
Returns patrons that are not guaranteed, do not have a guarantor.
191
192
=head4 options
193
194
=over 4
195
196
=item 0 - boolean to disable the filter
197
 
198
=item 1 - boolean to enable the filter (default)
199
 
200
=back
201
202
=cut
203
204
sub filter_by_is_not_guarantee {
205
    my ( $self, $enabled ) = @_;
206
207
    # Noop if explicitly disabled by param
208
    return $self if ( defined($enabled) && !$enabled );
209
210
    my $guaranteeList = Koha::Patron::Relationships->search(
211
        {},
212
        {
213
            columns  => ['guarantee_id'],
214
            distinct => 1
215
        }
216
    )->_resultset->as_query;
148
217
149
    # Patrons who do not have guarantors
218
    # Patrons who do not have guarantors
150
    return $self->search(
219
    return $self->search(
151
        { 'me.borrowernumber' => { '-not_in' => $guaranteeList } } );
220
        { 'me.borrowernumber' => { '-not_in' => $guaranteeList } } );
152
}
221
}
153
222
154
=head3 filter_by_last_issued
223
=head3 filter_by_date_last_checkout
155
224
156
    Koha::Patrons->filter_by_last_issued( { after => DateTime, before => DateTime } );
225
    Koha::Patrons->filter_by_date_last_checkout( { after => DateTime, before => DateTime } );
157
226
158
Returns patrons filtered by whether their last issue falls betwen the passed limits.
227
Returns patrons filtered by when their last issue date falls.
159
228
160
=head4 arguments hashref
229
=head4 arguments hashref
161
230
Lines 169-175 Returns patrons filtered by whether their last issue falls betwen the passed lim Link Here
169
238
170
=cut
239
=cut
171
240
172
sub filter_by_last_issued {
241
sub filter_by_date_last_checkout {
173
    my ( $self, $options ) = @_;
242
    my ( $self, $options ) = @_;
174
243
175
    return $self
244
    return $self
Lines 177-183 sub filter_by_last_issued { Link Here
177
        && ( $options->{before} || $options->{after} ) );
246
        && ( $options->{before} || $options->{after} ) );
178
247
179
    my $where = {};
248
    my $where = {};
180
    my $group_by = [ map { 'me.' . $_ } $self->_resultset->result_source->columns ];
249
    my $group_by =
250
      [ map { 'me.' . $_ } $self->_resultset->result_source->columns ];
181
    my $attrs = {
251
    my $attrs = {
182
        join     => 'old_issues',
252
        join     => 'old_issues',
183
        group_by => $group_by,
253
        group_by => $group_by,
Lines 227-257 sub filter_by_last_issued { Link Here
227
#    return $self->search( $where, $attrs );
297
#    return $self->search( $where, $attrs );
228
#}
298
#}
229
299
230
=head3 filter_by_has_issues
300
=head3 filter_by_has_pending_checkouts
231
301
232
    Koha::Patrons->filter_by_has_issues(1);
302
    $patrons_with_checkouts = Koha::Patrons->filter_by_has_pending_checkout;
233
303
234
Returns patrons filtered by whether they have current issues or not.
304
Returns patrons filtered by whether they have one or more current checkouts.
235
305
236
=head4 options
306
=head4 options
237
307
238
=over 4
308
=over 4
239
309
240
=item undef - do not apply filter
310
=item 0 - boolean to disable the filter
311
 
312
=item 1 - boolean to enable the filter (default)
313
 
314
=back
315
316
=cut
317
318
sub filter_by_has_pending_checkouts {
319
    my ( $self, $enabled ) = @_;
320
321
    # Noop if explicitly disabled by param
322
    return $self if ( defined($enabled) && !$enabled );
323
324
    my $issueList = Koha::Checkouts->search(
325
        {},
326
        {
327
            columns  => ['borrowernumber'],
328
            distinct => 1
329
        }
330
    )->_resultset->as_query;
241
331
242
=item 0 - limit to patrons WITHOUT current issues
332
    # Patrons who have current issues
333
    return $self->search( { 'me.borrowernumber' => { '-in' => $issueList } } );
334
}
335
336
=head3 filter_by_has_no_pending_checkouts
337
338
    Koha::Patrons->filter_by_has_no_ending_checkout(1);
243
339
244
=item 1 - limit to patrons WITH current issues
340
Returns patrons filtered to those who do not have any current checkouts.
245
341
342
=head4 options
343
344
=over 4
345
346
=item 0 - boolean to disable the filter
347
 
348
=item 1 - boolean to enable the filter (default)
349
 
246
=back
350
=back
247
351
248
=cut
352
=cut
249
353
250
sub filter_by_has_issues {
354
sub filter_by_has_no_pending_checkouts {
251
    my ( $self, $option ) = @_;
355
    my ( $self, $enabled ) = @_;
252
356
253
    return $self
357
    # Noop if explicitly disabled by param
254
      unless defined($option);
358
    return $self if ( defined($enabled) && !$enabled );
255
359
256
    my $issueList = Koha::Checkouts->search(
360
    my $issueList = Koha::Checkouts->search(
257
        {},
361
        {},
Lines 261-270 sub filter_by_has_issues { Link Here
261
        }
365
        }
262
    )->_resultset->as_query;
366
    )->_resultset->as_query;
263
367
264
    # Patrons who have current issues
265
    return $self->search( { 'me.borrowernumber' => { '-in' => $issueList } } )
266
      if $option;
267
268
    # Patrons who do not have current issues
368
    # Patrons who do not have current issues
269
    return $self->search(
369
    return $self->search(
270
        { 'me.borrowernumber' => { '-not_in' => $issueList } } );
370
        { 'me.borrowernumber' => { '-not_in' => $issueList } } );
Lines 300-308 sub filter_by_has_issues { Link Here
300
#    return $self->search($where,$attrs);
400
#    return $self->search($where,$attrs);
301
#}
401
#}
302
402
303
=head3 filter_by_when_expired
403
=head3 filter_by_date_expired
304
404
305
    Koha::Patrons->filter_by_when_expired( { after => DateTime, before => DateTime );
405
    Koha::Patrons->filter_by_date_expired( { after => DateTime, before => DateTime );
306
406
307
Returns patrons filtered by whether their accounts expired between between the passed limits.
407
Returns patrons filtered by whether their accounts expired between between the passed limits.
308
408
Lines 318-324 Returns patrons filtered by whether their accounts expired between between the p Link Here
318
418
319
=cut
419
=cut
320
420
321
sub filter_by_when_expired {
421
sub filter_by_date_expired {
322
    my ( $self, $options ) = @_;
422
    my ( $self, $options ) = @_;
323
423
324
    return $self
424
    return $self
Lines 350-356 sub filter_by_when_expired { Link Here
350
    return $self->search( $where, $attrs );
450
    return $self->search( $where, $attrs );
351
}
451
}
352
452
353
354
=head3 filter_by_amount_owed
453
=head3 filter_by_amount_owed
355
454
356
    Koha::Patrons->filter_by_amount_owed( { less_than => '2.00', more_than => '0.50' } );
455
    Koha::Patrons->filter_by_amount_owed( { less_than => '2.00', more_than => '0.50' } );
Lines 418-424 sub filter_by_amount_owed { Link Here
418
        && ( $options->{less_than} || $options->{more_than} ) );
517
        && ( $options->{less_than} || $options->{more_than} ) );
419
518
420
    my $where = {};
519
    my $where = {};
421
    my $group_by = [ map { 'me.' . $_ } $self->_resultset->result_source->columns ];
520
    my $group_by =
521
      [ map { 'me.' . $_ } $self->_resultset->result_source->columns ];
522
422
    #push @{$group_by}, 'outstanding';
523
    #push @{$group_by}, 'outstanding';
423
    my $attrs = {
524
    my $attrs = {
424
        join     => 'accountlines',
525
        join     => 'accountlines',
Lines 514-524 Returns all Patrons which are Housebound choosers. Link Here
514
=cut
615
=cut
515
616
516
sub search_housebound_choosers {
617
sub search_housebound_choosers {
517
    my ( $self ) = @_;
618
    my ($self) = @_;
518
    my $cho = $self->_resultset
619
    my $cho = $self->_resultset->search_related(
519
        ->search_related('housebound_role', {
620
        'housebound_role',
621
        {
520
            housebound_chooser => 1,
622
            housebound_chooser => 1,
521
        })->search_related('borrowernumber');
623
        }
624
    )->search_related('borrowernumber');
522
    return Koha::Patrons->_new_from_dbic($cho);
625
    return Koha::Patrons->_new_from_dbic($cho);
523
}
626
}
524
627
Lines 529-539 Returns all Patrons which are Housebound deliverers. Link Here
529
=cut
632
=cut
530
633
531
sub search_housebound_deliverers {
634
sub search_housebound_deliverers {
532
    my ( $self ) = @_;
635
    my ($self) = @_;
533
    my $del = $self->_resultset
636
    my $del = $self->_resultset->search_related(
534
        ->search_related('housebound_role', {
637
        'housebound_role',
638
        {
535
            housebound_deliverer => 1,
639
            housebound_deliverer => 1,
536
        })->search_related('borrowernumber');
640
        }
641
    )->search_related('borrowernumber');
537
    return Koha::Patrons->_new_from_dbic($del);
642
    return Koha::Patrons->_new_from_dbic($del);
538
}
643
}
539
644
Lines 551-572 from 12 to 17 days. Link Here
551
sub search_upcoming_membership_expires {
656
sub search_upcoming_membership_expires {
552
    my ( $self, $params ) = @_;
657
    my ( $self, $params ) = @_;
553
    my $before = $params->{before} || 0;
658
    my $before = $params->{before} || 0;
554
    my $after  = $params->{after} || 0;
659
    my $after  = $params->{after}  || 0;
555
    delete $params->{before};
660
    delete $params->{before};
556
    delete $params->{after};
661
    delete $params->{after};
557
662
558
    my $days = C4::Context->preference("MembershipExpiryDaysNotice") || 0;
663
    my $days = C4::Context->preference("MembershipExpiryDaysNotice") || 0;
559
    my $date_before = dt_from_string->add( days => $days - $before );
664
    my $date_before = dt_from_string->add( days => $days - $before );
560
    my $date_after = dt_from_string->add( days => $days + $after );
665
    my $date_after  = dt_from_string->add( days => $days + $after );
561
    my $dtf = Koha::Database->new->schema->storage->datetime_parser;
666
    my $dtf         = Koha::Database->new->schema->storage->datetime_parser;
562
667
563
    $params->{dateexpiry} = {
668
    $params->{dateexpiry} = {
564
        ">=" => $dtf->format_date( $date_before ),
669
        ">=" => $dtf->format_date($date_before),
565
        "<=" => $dtf->format_date( $date_after ),
670
        "<=" => $dtf->format_date($date_after),
566
    };
671
    };
567
    return $self->SUPER::search(
672
    return $self->SUPER::search( $params,
568
        $params, { join => ['branchcode', 'categorycode'] }
673
        { join => [ 'branchcode', 'categorycode' ] } );
569
    );
570
}
674
}
571
675
572
=head3 search_patrons_to_anonymise
676
=head3 search_patrons_to_anonymise
Lines 581-602 sub search_patrons_to_anonymise { Link Here
581
    my ( $class, $params ) = @_;
685
    my ( $class, $params ) = @_;
582
    my $older_than_date = $params->{before};
686
    my $older_than_date = $params->{before};
583
    my $library         = $params->{library};
687
    my $library         = $params->{library};
584
    $older_than_date = $older_than_date ? dt_from_string($older_than_date) : dt_from_string;
688
    $older_than_date =
689
      $older_than_date ? dt_from_string($older_than_date) : dt_from_string;
585
    $library ||=
690
    $library ||=
586
      ( C4::Context->preference('IndependentBranches') && C4::Context->userenv && !C4::Context->IsSuperLibrarian() && C4::Context->userenv->{branch} )
691
      (      C4::Context->preference('IndependentBranches')
692
          && C4::Context->userenv
693
          && !C4::Context->IsSuperLibrarian()
694
          && C4::Context->userenv->{branch} )
587
      ? C4::Context->userenv->{branch}
695
      ? C4::Context->userenv->{branch}
588
      : undef;
696
      : undef;
589
    my $anonymous_patron = C4::Context->preference('AnonymousPatron') || undef;
697
    my $anonymous_patron = C4::Context->preference('AnonymousPatron') || undef;
590
698
591
    my $dtf = Koha::Database->new->schema->storage->datetime_parser;
699
    my $dtf = Koha::Database->new->schema->storage->datetime_parser;
592
    my $rs = $class->_resultset->search(
700
    my $rs  = $class->_resultset->search(
593
        {   returndate                  => { '<'   =>  $dtf->format_datetime($older_than_date), },
701
        {
702
            returndate => { '<' => $dtf->format_datetime($older_than_date), },
594
            'old_issues.borrowernumber' => { 'not' => undef },
703
            'old_issues.borrowernumber' => { 'not' => undef },
595
            privacy                     => { '<>'  => 0 },                  # Keep forever
704
            privacy                     => { '<>'  => 0 },       # Keep forever
596
            ( $library ? ( 'old_issues.branchcode' => $library ) : () ),
705
            ( $library ? ( 'old_issues.branchcode' => $library ) : () ),
597
            ( $anonymous_patron ? ( 'old_issues.borrowernumber' => { '!=' => $anonymous_patron } ) : () ),
706
            (
707
                $anonymous_patron
708
                ? ( 'old_issues.borrowernumber' =>
709
                      { '!=' => $anonymous_patron } )
710
                : ()
711
            ),
598
        },
712
        },
599
        {   join     => ["old_issues"],
713
        {
714
            join     => ["old_issues"],
600
            distinct => 1,
715
            distinct => 1,
601
        }
716
        }
602
    );
717
    );
Lines 620-643 sub anonymise_issue_history { Link Here
620
735
621
    $older_than_date = dt_from_string $older_than_date if $older_than_date;
736
    $older_than_date = dt_from_string $older_than_date if $older_than_date;
622
737
623
    # The default of 0 does not work due to foreign key constraints
738
# The default of 0 does not work due to foreign key constraints
624
    # The anonymisation should not fail quietly if AnonymousPatron is not a valid entry
739
# The anonymisation should not fail quietly if AnonymousPatron is not a valid entry
625
    # Set it to undef (NULL)
740
# Set it to undef (NULL)
626
    my $dtf = Koha::Database->new->schema->storage->datetime_parser;
741
    my $dtf     = Koha::Database->new->schema->storage->datetime_parser;
627
    my $nb_rows = 0;
742
    my $nb_rows = 0;
628
    while ( my $patron = $self->next ) {
743
    while ( my $patron = $self->next ) {
629
        my $old_issues_to_anonymise = $patron->old_checkouts->search(
744
        my $old_issues_to_anonymise = $patron->old_checkouts->search(
630
        {
745
            {
631
            (
746
                (
632
                $older_than_date
747
                    $older_than_date
633
                ? ( returndate =>
748
                    ? ( returndate =>
634
                      { '<' => $dtf->format_datetime($older_than_date) } )
749
                          { '<' => $dtf->format_datetime($older_than_date) } )
635
                : ()
750
                    : ()
636
            )
751
                )
637
        }
752
            }
638
        );
753
        );
639
        my $anonymous_patron = C4::Context->preference('AnonymousPatron') || undef;
754
        my $anonymous_patron =
640
        $nb_rows += $old_issues_to_anonymise->update( { 'old_issues.borrowernumber' => $anonymous_patron } );
755
          C4::Context->preference('AnonymousPatron') || undef;
756
        $nb_rows += $old_issues_to_anonymise->update(
757
            { 'old_issues.borrowernumber' => $anonymous_patron } );
641
    }
758
    }
642
    return $nb_rows;
759
    return $nb_rows;
643
}
760
}
Lines 659-677 sub anonymise_issue_history { Link Here
659
sub delete {
776
sub delete {
660
    my ( $self, $params ) = @_;
777
    my ( $self, $params ) = @_;
661
    my $patrons_deleted;
778
    my $patrons_deleted;
662
    $self->_resultset->result_source->schema->txn_do( sub {
779
    $self->_resultset->result_source->schema->txn_do(
663
        my ( $set, $params ) = @_;
780
        sub {
664
        my $count = $set->count;
781
            my ( $set, $params ) = @_;
665
        while ( my $patron = $set->next ) {
782
            my $count = $set->count;
783
            while ( my $patron = $set->next ) {
666
784
667
            next unless $patron->in_storage;
785
                next unless $patron->in_storage;
668
786
669
            $patron->move_to_deleted if $params->{move};
787
                $patron->move_to_deleted if $params->{move};
670
            $patron->delete;
788
                $patron->delete;
671
789
672
            $patrons_deleted++;
790
                $patrons_deleted++;
673
        }
791
            }
674
    }, $self, $params );
792
        },
793
        $self,
794
        $params
795
    );
675
    return $patrons_deleted;
796
    return $patrons_deleted;
676
}
797
}
677
798
Lines 686-707 sub delete { Link Here
686
=cut
807
=cut
687
808
688
sub search_unsubscribed {
809
sub search_unsubscribed {
689
    my ( $class ) = @_;
810
    my ($class) = @_;
690
811
691
    my $delay = C4::Context->preference('UnsubscribeReflectionDelay');
812
    my $delay = C4::Context->preference('UnsubscribeReflectionDelay');
692
    if( !defined($delay) || $delay eq q{} ) {
813
    if ( !defined($delay) || $delay eq q{} ) {
814
693
        # return empty set
815
        # return empty set
694
        return $class->search({ borrowernumber => undef });
816
        return $class->search( { borrowernumber => undef } );
695
    }
817
    }
696
    my $parser = Koha::Database->new->schema->storage->datetime_parser;
818
    my $parser = Koha::Database->new->schema->storage->datetime_parser;
697
    my $dt = dt_from_string()->subtract( days => $delay );
819
    my $dt     = dt_from_string()->subtract( days => $delay );
698
    my $str = $parser->format_datetime($dt);
820
    my $str    = $parser->format_datetime($dt);
699
    my $fails = C4::Context->preference('FailedLoginAttempts') || 0;
821
    my $fails  = C4::Context->preference('FailedLoginAttempts') || 0;
700
    my $cond = [ undef, 0, 1..$fails-1 ]; # NULL, 0, 1..fails-1 (if fails>0)
822
    my $cond = [ undef, 0, 1 .. $fails - 1 ]; # NULL, 0, 1..fails-1 (if fails>0)
701
    return $class->search(
823
    return $class->search(
702
        {
824
        {
703
            'patron_consents.refused_on' => { '<=' => $str },
825
            'patron_consents.refused_on' => { '<=' => $str },
704
            'login_attempts' => $cond,
826
            'login_attempts'             => $cond,
705
        },
827
        },
706
        { join => 'patron_consents' },
828
        { join => 'patron_consents' },
707
    );
829
    );
Lines 721-741 sub search_anonymize_candidates { Link Here
721
    my ( $class, $params ) = @_;
843
    my ( $class, $params ) = @_;
722
844
723
    my $delay = C4::Context->preference('PatronAnonymizeDelay');
845
    my $delay = C4::Context->preference('PatronAnonymizeDelay');
724
    if( !defined($delay) || $delay eq q{} ) {
846
    if ( !defined($delay) || $delay eq q{} ) {
847
725
        # return empty set
848
        # return empty set
726
        return $class->search({ borrowernumber => undef });
849
        return $class->search( { borrowernumber => undef } );
727
    }
850
    }
728
    my $cond = {};
851
    my $cond   = {};
729
    my $parser = Koha::Database->new->schema->storage->datetime_parser;
852
    my $parser = Koha::Database->new->schema->storage->datetime_parser;
730
    my $dt = dt_from_string()->subtract( days => $delay );
853
    my $dt     = dt_from_string()->subtract( days => $delay );
731
    my $str = $parser->format_datetime($dt);
854
    my $str    = $parser->format_datetime($dt);
732
    $cond->{dateexpiry} = { '<=' => $str };
855
    $cond->{dateexpiry} = { '<=' => $str };
733
    $cond->{anonymized} = 0; # not yet done
856
    $cond->{anonymized} = 0;    # not yet done
734
    if( $params->{locked} ) {
857
    if ( $params->{locked} ) {
735
        my $fails = C4::Context->preference('FailedLoginAttempts') || 0;
858
        my $fails = C4::Context->preference('FailedLoginAttempts') || 0;
736
        $cond->{login_attempts} = [ -and => { '!=' => undef }, { -not_in => [0, 1..$fails-1 ] } ]; # -not_in does not like undef
859
        $cond->{login_attempts} =
860
          [ -and => { '!=' => undef }, { -not_in => [ 0, 1 .. $fails - 1 ] } ]
861
          ;    # -not_in does not like undef
737
    }
862
    }
738
    return $class->search( $cond );
863
    return $class->search($cond);
739
}
864
}
740
865
741
=head3 search_anonymized
866
=head3 search_anonymized
Lines 749-768 sub search_anonymize_candidates { Link Here
749
=cut
874
=cut
750
875
751
sub search_anonymized {
876
sub search_anonymized {
752
    my ( $class ) = @_;
877
    my ($class) = @_;
753
878
754
    my $delay = C4::Context->preference('PatronRemovalDelay');
879
    my $delay = C4::Context->preference('PatronRemovalDelay');
755
    if( !defined($delay) || $delay eq q{} ) {
880
    if ( !defined($delay) || $delay eq q{} ) {
881
756
        # return empty set
882
        # return empty set
757
        return $class->search({ borrowernumber => undef });
883
        return $class->search( { borrowernumber => undef } );
758
    }
884
    }
759
    my $cond = {};
885
    my $cond   = {};
760
    my $parser = Koha::Database->new->schema->storage->datetime_parser;
886
    my $parser = Koha::Database->new->schema->storage->datetime_parser;
761
    my $dt = dt_from_string()->subtract( days => $delay );
887
    my $dt     = dt_from_string()->subtract( days => $delay );
762
    my $str = $parser->format_datetime($dt);
888
    my $str    = $parser->format_datetime($dt);
763
    $cond->{dateexpiry} = { '<=' => $str };
889
    $cond->{dateexpiry} = { '<=' => $str };
764
    $cond->{anonymized} = 1;
890
    $cond->{anonymized} = 1;
765
    return $class->search( $cond );
891
    return $class->search($cond);
766
}
892
}
767
893
768
=head3 lock
894
=head3 lock
Lines 777-783 sub search_anonymized { Link Here
777
sub lock {
903
sub lock {
778
    my ( $self, $params ) = @_;
904
    my ( $self, $params ) = @_;
779
    my $count = $self->count;
905
    my $count = $self->count;
780
    while( my $patron = $self->next ) {
906
    while ( my $patron = $self->next ) {
781
        $patron->lock($params);
907
        $patron->lock($params);
782
    }
908
    }
783
}
909
}
Lines 792-800 sub lock { Link Here
792
=cut
918
=cut
793
919
794
sub anonymize {
920
sub anonymize {
795
    my ( $self ) = @_;
921
    my ($self) = @_;
796
    my $count = $self->count;
922
    my $count = $self->count;
797
    while( my $patron = $self->next ) {
923
    while ( my $patron = $self->next ) {
798
        $patron->anonymize;
924
        $patron->anonymize;
799
    }
925
    }
800
}
926
}
Lines 824-850 sub search_patrons_to_update_category { Link Here
824
    my %query;
950
    my %query;
825
    my $search_params;
951
    my $search_params;
826
952
827
    my $cat_from = Koha::Patron::Categories->find($params->{from});
953
    my $cat_from = Koha::Patron::Categories->find( $params->{from} );
828
    $search_params->{categorycode}=$params->{from};
954
    $search_params->{categorycode} = $params->{from};
829
    if ($params->{too_young} || $params->{too_old}){
955
    if ( $params->{too_young} || $params->{too_old} ) {
830
        my $dtf = Koha::Database->new->schema->storage->datetime_parser;
956
        my $dtf = Koha::Database->new->schema->storage->datetime_parser;
831
        if( $cat_from->dateofbirthrequired && $params->{too_young} ) {
957
        if ( $cat_from->dateofbirthrequired && $params->{too_young} ) {
832
            my $date_after = dt_from_string()->subtract( years => $cat_from->dateofbirthrequired);
958
            my $date_after = dt_from_string()
833
            $search_params->{dateofbirth}{'>'} = $dtf->format_datetime( $date_after );
959
              ->subtract( years => $cat_from->dateofbirthrequired );
960
            $search_params->{dateofbirth}{'>'} =
961
              $dtf->format_datetime($date_after);
834
        }
962
        }
835
        if( $cat_from->upperagelimit && $params->{too_old} ) {
963
        if ( $cat_from->upperagelimit && $params->{too_old} ) {
836
            my $date_before = dt_from_string()->subtract( years => $cat_from->upperagelimit);
964
            my $date_before =
837
            $search_params->{dateofbirth}{'<'} = $dtf->format_datetime( $date_before );
965
              dt_from_string()->subtract( years => $cat_from->upperagelimit );
966
            $search_params->{dateofbirth}{'<'} =
967
              $dtf->format_datetime($date_before);
838
        }
968
        }
839
    }
969
    }
840
    if ($params->{fine_min} || $params->{fine_max}) {
970
    if ( $params->{fine_min} || $params->{fine_max} ) {
841
        $query{join} = ["accountlines"];
971
        $query{join}     = ["accountlines"];
842
        $query{columns} = ["borrowernumber"];
972
        $query{columns}  = ["borrowernumber"];
843
        $query{group_by} = ["borrowernumber"];
973
        $query{group_by} = ["borrowernumber"];
844
        $query{having} = \['COALESCE(sum(accountlines.amountoutstanding),0) <= ?',$params->{fine_max}] if defined $params->{fine_max};
974
        $query{having}   = \[
845
        $query{having} = \['COALESCE(sum(accountlines.amountoutstanding),0) >= ?',$params->{fine_min}] if defined $params->{fine_min};
975
            'COALESCE(sum(accountlines.amountoutstanding),0) <= ?',
976
            $params->{fine_max}
977
          ]
978
          if defined $params->{fine_max};
979
        $query{having} = \[
980
            'COALESCE(sum(accountlines.amountoutstanding),0) >= ?',
981
            $params->{fine_min}
982
          ]
983
          if defined $params->{fine_min};
846
    }
984
    }
847
    return $self->search($search_params,\%query);
985
    return $self->search( $search_params, \%query );
848
}
986
}
849
987
850
=head3 update_category_to
988
=head3 update_category_to
Lines 862-870 call search_patrons_to_update to filter the Koha::Patrons set Link Here
862
sub update_category_to {
1000
sub update_category_to {
863
    my ( $self, $params ) = @_;
1001
    my ( $self, $params ) = @_;
864
    my $counter = 0;
1002
    my $counter = 0;
865
    while( my $patron = $self->next ) {
1003
    while ( my $patron = $self->next ) {
866
        $counter++;
1004
        $counter++;
867
        $patron->categorycode($params->{category})->store();
1005
        $patron->categorycode( $params->{category} )->store();
868
    }
1006
    }
869
    return $counter;
1007
    return $counter;
870
}
1008
}
Lines 904-910 sub filter_by_attribute_value { Link Here
904
    return Koha::Patrons->_new_from_dbic($rs);
1042
    return Koha::Patrons->_new_from_dbic($rs);
905
}
1043
}
906
1044
907
908
=head3 _type
1045
=head3 _type
909
1046
910
=cut
1047
=cut
(-)a/t/db_dependent/Koha/Patrons.t (-43 / +117 lines)
Lines 1603-1609 subtest 'BorrowersLog tests' => sub { Link Here
1603
};
1603
};
1604
1604
1605
subtest 'complex filters' => sub {
1605
subtest 'complex filters' => sub {
1606
    plan tests => 7;
1606
    plan tests => 9;
1607
1607
1608
    my $now             = DateTime->now;
1608
    my $now             = DateTime->now;
1609
    my $new_patron_cf_1 = Koha::Patron->new(
1609
    my $new_patron_cf_1 = Koha::Patron->new(
Lines 1664-1671 subtest 'complex filters' => sub { Link Here
1664
        is( ref($filtered), 'Koha::Patrons',
1664
        is( ref($filtered), 'Koha::Patrons',
1665
'Koha::Patrons->filter_by_is_guarantor should return a Koha::Patrons result set in a scalar context'
1665
'Koha::Patrons->filter_by_is_guarantor should return a Koha::Patrons result set in a scalar context'
1666
        );
1666
        );
1667
        is( $filtered->count, 3,
1667
        is( $filtered->count, 1, 'filter_by_is_guarantor() found one patron' );
1668
            'filter_by_is_guarantor() found both patrons' );
1668
        is( $filtered->next->guarantee_relationships->count,
1669
            1, 'filter_by_is_guarantor() found the correct patron' );
1669
1670
1670
        $filtered = $results->filter_by_is_guarantor(1);
1671
        $filtered = $results->filter_by_is_guarantor(1);
1671
        is( $filtered->count, 1, 'filter_by_is_guarantor(1) found one patron' );
1672
        is( $filtered->count, 1, 'filter_by_is_guarantor(1) found one patron' );
Lines 1673-1706 subtest 'complex filters' => sub { Link Here
1673
            1, 'filter_by_is_guarantor(1) found the correct patron' );
1674
            1, 'filter_by_is_guarantor(1) found the correct patron' );
1674
1675
1675
        $filtered = $results->filter_by_is_guarantor(0);
1676
        $filtered = $results->filter_by_is_guarantor(0);
1677
        is( $filtered->count, 3,
1678
            'filter_by_is_guarantor(0) found all patrons - filter disabled' );
1679
    };
1680
1681
    subtest 'filter_by_is_not_guarantor' => sub {
1682
        plan tests => 6;
1683
1684
        my $filtered = $results->filter_by_is_not_guarantor();
1685
        is( ref($filtered), 'Koha::Patrons',
1686
'Koha::Patrons->filter_by_is_not_guarantor should return a Koha::Patrons result set in a scalar context'
1687
        );
1688
        is( $filtered->count, 2,
1689
            'filter_by_is_not_guarantor() found both patrons' );
1690
        is( $filtered->next->guarantee_relationships->count,
1691
            0, 'filter_by_is_not_guarantor() found the correct patrons' );
1692
1693
        $filtered = $results->filter_by_is_not_guarantor(1);
1676
        is( $filtered->count, 2,
1694
        is( $filtered->count, 2,
1677
            'filter_by_is_guarantor(0) found two patrons' );
1695
            'filter_by_is_not_guarantor(1) found two patrons' );
1678
        is( $filtered->next->guarantee_relationships->count,
1696
        is( $filtered->next->guarantee_relationships->count,
1679
            0, 'filter_by_is_guarantor(0) found the correct patrons' );
1697
            0, 'filter_by_is_not_guarantor(1) found the correct patrons' );
1698
        
1699
        $filtered = $results->filter_by_is_not_guarantor(0);
1700
        is( $filtered->count, 3,
1701
            'filter_by_is_not_guarantor(0) found all patrons - filter disabled' );
1680
    };
1702
    };
1681
1703
1682
    subtest 'filter_by_has_guarantor' => sub {
1704
    subtest 'filter_by_is_guarantee' => sub {
1683
        plan tests => 6;
1705
        plan tests => 6;
1684
1706
1685
        my $filtered = $results->filter_by_has_guarantor();
1707
        my $filtered = $results->filter_by_is_guarantee();
1686
        is( ref($filtered), 'Koha::Patrons',
1708
        is( ref($filtered), 'Koha::Patrons',
1687
'filter_by_has_guarantor() should return a Koha::Patrons result set in a scalar context'
1709
'filter_by_is_guarantee() should return a Koha::Patrons result set in a scalar context'
1710
        );
1711
        is( $filtered->count, 1,
1712
            'filter_by_is_guarantee() found one patron' );
1713
        is(
1714
            $filtered->next->borrowernumber,
1715
            $new_patron_cf_2->borrowernumber,
1716
            'filter_by_is_guarantee() found the correct patron'
1688
        );
1717
        );
1689
        is( $filtered->count, 3,
1690
            'filter_by_has_guarantor() found both patrons' );
1691
1718
1692
        $filtered = $results->filter_by_has_guarantor(1);
1719
        $filtered = $results->filter_by_is_guarantee(1);
1693
        is( $filtered->count, 1,
1720
        is( $filtered->count, 1,
1694
            'filter_by_has_guarantor(1) found one patron' );
1721
            'filter_by_is_guarantee(1) found one patron' );
1695
        is(
1722
        is(
1696
            $filtered->next->borrowernumber,
1723
            $filtered->next->borrowernumber,
1697
            $new_patron_cf_2->borrowernumber,
1724
            $new_patron_cf_2->borrowernumber,
1698
            'filter_by_has_guarantor(1) found the correct patron'
1725
            'filter_by_is_guarantee(1) found the correct patron'
1726
        );
1727
1728
        $filtered = $results->filter_by_is_guarantee(0);
1729
        is( $filtered->count, 3,
1730
            'filter_by_is_guarantee(0) found all patrons - filter disabled' );
1731
    };
1732
1733
    subtest 'filter_by_is_not_guarantee' => sub {
1734
        plan tests => 6;
1735
1736
        my $filtered = $results->filter_by_is_not_guarantee();
1737
        is( ref($filtered), 'Koha::Patrons',
1738
'filter_by_is_not_guarantee() should return a Koha::Patrons result set in a scalar context'
1739
        );
1740
        is( $filtered->count, 2,
1741
            'filter_by_is_not_guarantee() found two patrons' );
1742
        is_deeply(
1743
            [
1744
                sort( $filtered->next->borrowernumber,
1745
                    $filtered->next->borrowernumber )
1746
            ],
1747
            [
1748
                sort ( $new_patron_cf_1->borrowernumber,
1749
                    $new_patron_cf_3->borrowernumber )
1750
            ],
1751
            'filter_by_is_not_guarantee() found the correct patrons'
1699
        );
1752
        );
1700
1753
1701
        $filtered = $results->filter_by_has_guarantor(0);
1754
        $filtered = $results->filter_by_is_not_guarantee(1);
1702
        is( $filtered->count, 2,
1755
        is( $filtered->count, 2,
1703
            'filter_by_has_guarantor(0) found two patrons' );
1756
            'filter_by_is_not_guarantee(1) found two patrons' );
1704
        is_deeply(
1757
        is_deeply(
1705
            [
1758
            [
1706
                sort( $filtered->next->borrowernumber,
1759
                sort( $filtered->next->borrowernumber,
Lines 1710-1720 subtest 'complex filters' => sub { Link Here
1710
                sort ( $new_patron_cf_1->borrowernumber,
1763
                sort ( $new_patron_cf_1->borrowernumber,
1711
                    $new_patron_cf_3->borrowernumber )
1764
                    $new_patron_cf_3->borrowernumber )
1712
            ],
1765
            ],
1713
            'filter_by_has_guarantor(0) found the correct patrons'
1766
            'filter_by_is_not_guarantee(1) found the correct patrons'
1714
        );
1767
        );
1768
1769
        $filtered = $results->filter_by_is_not_guarantee(0);
1770
        is( $filtered->count, 3,
1771
            'filter_by_is_not_guarantee(0) found all patrons - filter disabled' );
1715
    };
1772
    };
1716
1773
1717
    subtest 'filter_by_last_issued' => sub {
1774
    subtest 'filter_by_date_last_checkout' => sub {
1718
        plan tests => 4;
1775
        plan tests => 4;
1719
1776
1720
        my $first = DateTime->now()->subtract( days => 5 );
1777
        my $first = DateTime->now()->subtract( days => 5 );
Lines 1747-1774 subtest 'complex filters' => sub { Link Here
1747
            }
1804
            }
1748
        );
1805
        );
1749
1806
1750
        my $filtered = $results->filter_by_last_issued();
1807
        my $filtered = $results->filter_by_date_last_checkout();
1751
        is( ref($filtered), 'Koha::Patrons',
1808
        is( ref($filtered), 'Koha::Patrons',
1752
'filter_by_last_issued() should return a Koha::Patrons result set in a scalar context'
1809
'filter_by_date_last_checkout() should return a Koha::Patrons result set in a scalar context'
1753
        );
1810
        );
1754
1811
1755
        $filtered = $results->filter_by_last_issued( { before => $last } );
1812
        $filtered = $results->filter_by_date_last_checkout( { before => $last } );
1756
        is( $filtered->_resultset->as_subselect_rs->count,
1813
        is( $filtered->_resultset->as_subselect_rs->count,
1757
            2, "filter_by_last_issued({ before => $last }) found two patrons" );
1814
            2, "filter_by_date_last_checkout({ before => $last }) found two patrons" );
1758
1815
1759
        $filtered = $results->filter_by_last_issued( { after => $first } );
1816
        $filtered = $results->filter_by_date_last_checkout( { after => $first } );
1760
        is( $filtered->_resultset->as_subselect_rs->count,
1817
        is( $filtered->_resultset->as_subselect_rs->count,
1761
            2, "filter_by_last_issued({ after => $first }) found two patrons" );
1818
            2, "filter_by_date_last_checkout({ after => $first }) found two patrons" );
1762
1819
1763
        $filtered = $results->filter_by_last_issued(
1820
        $filtered = $results->filter_by_date_last_checkout(
1764
            { after => $first, before => $last } );
1821
            { after => $first, before => $last } );
1765
        is( $filtered->_resultset->as_subselect_rs->count, 1,
1822
        is( $filtered->_resultset->as_subselect_rs->count, 1,
1766
"filter_by_last_issued({ after => $first, before => $last }) found two patrons"
1823
"filter_by_date_last_checkout({ after => $first, before => $last }) found two patrons"
1767
        );
1824
        );
1768
    };
1825
    };
1769
1826
1770
    subtest 'filter_by_has_issues' => sub {
1827
    subtest 'filter_by_has_pending_checkouts/filter_by_has_no_pending_checkouts' => sub {
1771
        plan tests => 3;
1828
        plan tests => 8;
1772
1829
1773
        my $issue_1 = $builder->build(
1830
        my $issue_1 = $builder->build(
1774
            {
1831
            {
Lines 1779-1823 subtest 'complex filters' => sub { Link Here
1779
            }
1836
            }
1780
        );
1837
        );
1781
1838
1782
        my $filtered = $results->filter_by_has_issues();
1839
        my $filtered = $results->filter_by_has_pending_checkouts();
1783
        is( ref($filtered), 'Koha::Patrons',
1840
        is( ref($filtered), 'Koha::Patrons',
1784
'filter_by_has_issues() should return a Koha::Patrons result set in a scalar context'
1841
'filter_by_has_pending_checkouts() should return a Koha::Patrons result set in a scalar context'
1785
        );
1842
        );
1843
        is( $filtered->_resultset->as_subselect_rs->count,
1844
            1, "filter_by_has_pending_checkouts() found one patron" );
1845
1846
1847
        $filtered = $results->filter_by_has_pending_checkouts(1);
1848
        is( $filtered->_resultset->as_subselect_rs->count,
1849
            1, "filter_by_has_pending_checkouts(1) found one patron" );
1850
1851
        $filtered = $results->filter_by_has_pending_checkouts(0);
1852
        is( $filtered->_resultset->as_subselect_rs->count,
1853
            3, "filter_by_has_pending_checkouts(0) found all patrons - filter disabled" );
1854
        
1855
        $filtered = $results->filter_by_has_no_pending_checkouts();
1856
        is( ref($filtered), 'Koha::Patrons',
1857
'filter_by_has_no_pending_checkouts() should return a Koha::Patrons result set in a scalar context'
1858
        );
1859
        is( $filtered->_resultset->as_subselect_rs->count,
1860
            2, "filter_by_has_no_pending_checkouts() found two patrons" );
1786
1861
1787
        $filtered = $results->filter_by_has_issues(1);
1862
        $filtered = $results->filter_by_has_no_pending_checkouts(1);
1788
        is( $filtered->_resultset->as_subselect_rs->count,
1863
        is( $filtered->_resultset->as_subselect_rs->count,
1789
            1, "filter_by_has_issues(1) found one patron" );
1864
            2, "filter_by_has_no_pending_checkouts(1) found two patrons" );
1790
1865
1791
        $filtered = $results->filter_by_has_issues(0);
1866
        $filtered = $results->filter_by_has_no_pending_checkouts(0);
1792
        is( $filtered->_resultset->as_subselect_rs->count,
1867
        is( $filtered->_resultset->as_subselect_rs->count,
1793
            2, "filter_by_has_issues(0) found two patrons" );
1868
            3, "filter_by_has_no_pending_checkouts(0) found all patrons - filter disabled" );
1794
    };
1869
    };
1795
1870
1796
    subtest 'filter_by_when_expired' => sub {
1871
    subtest 'filter_by_date_expired' => sub {
1797
        plan tests => 4;
1872
        plan tests => 4;
1798
1873
1799
        my $first  = $now->clone->subtract( days => 12 );
1874
        my $first  = $now->clone->subtract( days => 12 );
1800
        my $second = $now->clone->subtract( days => 4 );
1875
        my $second = $now->clone->subtract( days => 4 );
1801
1876
1802
        my $filtered = $results->filter_by_when_expired();
1877
        my $filtered = $results->filter_by_date_expired();
1803
        is( ref($filtered), 'Koha::Patrons',
1878
        is( ref($filtered), 'Koha::Patrons',
1804
'Koha::Patrons->filter_by_when_expired should return a Koha::Patrons result set in a scalar context'
1879
'Koha::Patrons->filter_by_date_expired should return a Koha::Patrons result set in a scalar context'
1805
        );
1880
        );
1806
1881
1807
        $filtered = $results->filter_by_when_expired( { before => $second } );
1882
        $filtered = $results->filter_by_date_expired( { before => $second } );
1808
        is( $filtered->_resultset->as_subselect_rs->count,
1883
        is( $filtered->_resultset->as_subselect_rs->count,
1809
            2,
1884
            2,
1810
            "filter_by_when_expired({ before => $second }) found two patrons" );
1885
            "filter_by_date_expired({ before => $second }) found two patrons" );
1811
1886
1812
        $filtered = $results->filter_by_when_expired( { after => $first } );
1887
        $filtered = $results->filter_by_date_expired( { after => $first } );
1813
        is( $filtered->_resultset->as_subselect_rs->count,
1888
        is( $filtered->_resultset->as_subselect_rs->count,
1814
            2,
1889
            2,
1815
            "filter_by_when_expired({ after => $first }) found two patrons" );
1890
            "filter_by_date_expired({ after => $first }) found two patrons" );
1816
1891
1817
        $filtered = $results->filter_by_when_expired(
1892
        $filtered = $results->filter_by_date_expired(
1818
            { after => $first, before => $second } );
1893
            { after => $first, before => $second } );
1819
        is( $filtered->_resultset->as_subselect_rs->count, 1,
1894
        is( $filtered->_resultset->as_subselect_rs->count, 1,
1820
"filter_by_when_expired({ after => $first, before => $second }) found one patrons"
1895
"filter_by_date_expired({ after => $first, before => $second }) found one patrons"
1821
        );
1896
        );
1822
    };
1897
    };
1823
1898
1824
- 

Return to bug 11983