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

(-)a/C4/Circulation.pm (-3 / +3 lines)
Lines 3057-3063 sub CanBookBeRenewed { Link Here
3057
        my $overduesblockrenewing = C4::Context->preference('OverduesBlockRenewing');
3057
        my $overduesblockrenewing = C4::Context->preference('OverduesBlockRenewing');
3058
        my $restrictionblockrenewing = C4::Context->preference('RestrictionBlockRenewing');
3058
        my $restrictionblockrenewing = C4::Context->preference('RestrictionBlockRenewing');
3059
        my $restricted  = $patron->is_debarred;
3059
        my $restricted  = $patron->is_debarred;
3060
        my $hasoverdues = $patron->has_overdues;
3060
        my $hasoverdues = $patron->has_overdues({ cache => 1 });
3061
3061
3062
        if ( $restricted and $restrictionblockrenewing ) {
3062
        if ( $restricted and $restrictionblockrenewing ) {
3063
            return ( 0, 'restriction');
3063
            return ( 0, 'restriction');
Lines 3370-3376 sub AddRenewal { Link Here
3370
        my $overdue_restrictions = $patron->restrictions->search({ type => 'OVERDUES' });
3370
        my $overdue_restrictions = $patron->restrictions->search({ type => 'OVERDUES' });
3371
        if ( $patron
3371
        if ( $patron
3372
          && $patron->is_debarred
3372
          && $patron->is_debarred
3373
          && ! $patron->has_overdues
3373
          && !$patron->has_overdues
3374
          && $overdue_restrictions->count
3374
          && $overdue_restrictions->count
3375
        ) {
3375
        ) {
3376
            DelUniqueDebarment({ borrowernumber => $borrowernumber, type => 'OVERDUES' });
3376
            DelUniqueDebarment({ borrowernumber => $borrowernumber, type => 'OVERDUES' });
Lines 4625-4631 sub _CanBookBeAutoRenewed { Link Here
4625
        }
4625
        }
4626
    );
4626
    );
4627
4627
4628
    if ( $patron->is_expired && $patron->category->effective_BlockExpiredPatronOpacActions_contains('renew') ) {
4628
    if ( $patron->is_expired( { cache => 1 } ) && $patron->category->effective_BlockExpiredPatronOpacActions_contains('renew') ) {
4629
        return 'auto_account_expired';
4629
        return 'auto_account_expired';
4630
    }
4630
    }
4631
4631
(-)a/Koha/Object.pm (+87 lines)
Lines 90-95 sub new { Link Here
90
90
91
}
91
}
92
92
93
=head3 Koha::Object->_instance_cache_key();
94
95
my $instance_cache_key = Koha::Object->_instance_cache_key($key);
96
97
=cut
98
99
sub _instance_cache_key {
100
    my ($self, $key) = @_;
101
    warn "_instance_cache_key must not be called on object that has not been stored" unless $self->id;
102
    return $self->_type . ':' . $self->id  . ':' . $key;
103
}
104
105
=head3 Koha::Object->_instance_cache_get();
106
107
my $value = Koha::Object->_instance_cache_get($cache_key);
108
109
=cut
110
111
sub _instance_cache_get {
112
    my ($self, $key) = @_;
113
    return unless $self->id;
114
    return Koha::Cache::Memory::Lite->get_instance->get_from_cache(
115
        $self->_instance_cache_key($key)
116
    );
117
}
118
119
=head3 Koha::Object->_instance_cache_set();
120
121
Koha::Object->_instance_cache_set($cache_key, $value);
122
123
=cut
124
125
sub _instance_cache_set {
126
    my ($self, $key, $value) = @_;
127
    return unless $self->id;
128
    $self->{_cache}->{$key} = $value;
129
    return Koha::Cache::Memory::Lite->get_instance->set_in_cache(
130
        $self->_instance_cache_key($key),
131
        $value
132
    );
133
}
134
135
=head3 Koha::Object->_instance_cache_clear($cache_key);
136
137
Koha::Object->_instance_cache_clear($cache_key);
138
Koha::Object->_instance_cache_clear();
139
140
=cut
141
142
sub _instance_cache_clear {
143
    my ($self, $key) = @_;
144
    return unless $self->id;
145
    Koha::Cache::Memory::Lite->get_instance->clear_from_cache(
146
        $self->_instance_cache_key($key)
147
    )
148
}
149
150
=head3 Koha::Object->_accessor_cache($method_name);
151
152
my $value = Koha::Object->_accessor_cache($method_name);
153
154
=cut
155
156
sub _accessor_cache {
157
    my ($self, $method_name) = @_;
158
159
    my $value = $self->_instance_cache_get($method_name);
160
161
    return $value if defined $value;
162
163
    $value = $self->$method_name();
164
    $self->_instance_cache_set($method_name, $value);
165
166
    return $value;
167
}
168
169
=head3 Koha::Object->accessor_cache_clear($method_name);
170
171
Koha::Object->accessor_cache_clear($method_name);
172
173
=cut
174
175
sub accessor_cache_clear {
176
    my ($self, $method_name) = @_;
177
    $self->_instance_cache_clear($method_name);
178
}
179
93
=head3 Koha::Object->_new_from_dbic();
180
=head3 Koha::Object->_new_from_dbic();
94
181
95
my $object = Koha::Object->_new_from_dbic($dbic_row);
182
my $object = Koha::Object->_new_from_dbic($dbic_row);
(-)a/Koha/Patron.pm (-6 / +45 lines)
Lines 884-903 sub is_debarred { Link Here
884
    return;
884
    return;
885
}
885
}
886
886
887
=head3 dateexpiry
888
889
Override Patron::dateexpiry to invalidate Patron::is_expired cache.
890
891
=cut
892
893
sub dateexpiry {
894
    my $self = shift @_;
895
    if (@_) {
896
        $self->_instance_cache_clear('is_expired');
897
    }
898
    return $self->SUPER::dateexpiry(@_);
899
}
900
901
=head3 set
902
903
Override Patron::set to invalidate Patron::is_expired cache if dateexpiry is set.
904
905
=cut
906
907
sub set {
908
    my $self = shift @_;
909
    my ($properties) = @_;
910
    if (exists $properties->{dateexpiry}) {
911
        $self->_instance_cache_clear('is_expired');
912
    }
913
    return $self->SUPER::set(@_);
914
}
915
887
=head3 is_expired
916
=head3 is_expired
888
917
889
my $is_expired = $patron->is_expired;
918
my $is_expired = $patron->is_expired;
919
my $is_expired = $patron->is_expired({ cache => 1});
890
920
891
Returns 1 if the patron is expired or 0;
921
Returns 1 if the patron is expired or 0;
892
922
893
=cut
923
=cut
894
924
895
sub is_expired {
925
sub is_expired {
896
    my ($self) = @_;
926
    my ($self, $params) = @_;
897
    return 0 unless $self->dateexpiry;
927
    $params //= {};
898
    return 0 if $self->dateexpiry =~ '^9999';
928
    return $self->_accessor_cache('is_expired') if $params->{cache};
899
    return 1 if dt_from_string( $self->dateexpiry ) < dt_from_string->truncate( to => 'day' );
929
900
    return 0;
930
    $self->_instance_cache_clear('is_expired');
931
    return $self->dateexpiry &&
932
        $self->dateexpiry !~ '^9999' &&
933
        dt_from_string( $self->dateexpiry ) < dt_from_string->truncate( to => 'day' ) ? 1 : 0;
901
}
934
}
902
935
903
=head3 is_active
936
=head3 is_active
Lines 1142-1154 sub renew_account { Link Here
1142
=head3 has_overdues
1175
=head3 has_overdues
1143
1176
1144
my $has_overdues = $patron->has_overdues;
1177
my $has_overdues = $patron->has_overdues;
1178
my $has_overdues = $patron->has_overdues({ cache => 1 });
1145
1179
1146
Returns the number of patron's overdues
1180
Returns the number of patron's overdues
1147
1181
1148
=cut
1182
=cut
1149
1183
1150
sub has_overdues {
1184
sub has_overdues {
1151
    my ($self) = @_;
1185
    my ($self, $params) = @_;
1186
    $params //= {};
1187
1188
    return $self->_accessor_cache('has_overdues') if $params->{cache};
1189
1190
    $self->_instance_cache_clear('has_overdues');
1152
    my $date = dt_from_string();
1191
    my $date = dt_from_string();
1153
    my $dtf = Koha::Database->new->schema->storage->datetime_parser;
1192
    my $dtf = Koha::Database->new->schema->storage->datetime_parser;
1154
    return $self->_result->issues->search({ date_due => { '<' => $dtf->format_datetime($date) } })->count;
1193
    return $self->_result->issues->search({ date_due => { '<' => $dtf->format_datetime($date) } })->count;
(-)a/t/db_dependent/Koha/Patrons.t (-7 / +55 lines)
Lines 264-270 subtest 'siblings' => sub { Link Here
264
};
264
};
265
265
266
subtest 'has_overdues' => sub {
266
subtest 'has_overdues' => sub {
267
    plan tests => 3;
267
    plan tests => 12;
268
268
269
    my $item_1 = $builder->build_sample_item;
269
    my $item_1 = $builder->build_sample_item;
270
    my $retrieved_patron = Koha::Patrons->find( $new_patron_1->borrowernumber );
270
    my $retrieved_patron = Koha::Patrons->find( $new_patron_1->borrowernumber );
Lines 273-298 subtest 'has_overdues' => sub { Link Here
273
    my $tomorrow = DateTime->today( time_zone => C4::Context->tz() )->add( days => 1 );
273
    my $tomorrow = DateTime->today( time_zone => C4::Context->tz() )->add( days => 1 );
274
    my $issue = Koha::Checkout->new({ borrowernumber => $new_patron_1->id, itemnumber => $item_1->itemnumber, date_due => $tomorrow, branchcode => $library->{branchcode} })->store();
274
    my $issue = Koha::Checkout->new({ borrowernumber => $new_patron_1->id, itemnumber => $item_1->itemnumber, date_due => $tomorrow, branchcode => $library->{branchcode} })->store();
275
    is( $retrieved_patron->has_overdues, 0, );
275
    is( $retrieved_patron->has_overdues, 0, );
276
277
    # Cache is set
278
    is( $retrieved_patron->has_overdues({ cache => 1}), 0, );
279
    is( $retrieved_patron->_instance_cache_get('has_overdues'), 0, 'has_overdues cache has been set');
280
    # Cache is used
281
    is( $retrieved_patron->has_overdues({ cache => 1}), 0, 'has_overdues cache is used');
282
276
    $issue->delete();
283
    $issue->delete();
277
    my $yesterday = DateTime->today(time_zone => C4::Context->tz())->add( days => -1 );
284
    my $yesterday = DateTime->today(time_zone => C4::Context->tz())->add( days => -1 );
278
    $issue = Koha::Checkout->new({ borrowernumber => $new_patron_1->id, itemnumber => $item_1->itemnumber, date_due => $yesterday, branchcode => $library->{branchcode} })->store();
285
    $issue = Koha::Checkout->new({ borrowernumber => $new_patron_1->id, itemnumber => $item_1->itemnumber, date_due => $yesterday, branchcode => $library->{branchcode} })->store();
279
    $retrieved_patron = Koha::Patrons->find( $new_patron_1->borrowernumber );
286
    $retrieved_patron = Koha::Patrons->find( $new_patron_1->borrowernumber );
280
    is( $retrieved_patron->has_overdues, 1, );
287
    is( $retrieved_patron->has_overdues, 1, );
288
    is( $retrieved_patron->_instance_cache_get('has_overdues'), undef, 'has_overdues cache has been invalidated' );
289
    # Cache is set
290
    is( $retrieved_patron->has_overdues({ cache => 1}), 1, );
291
    is ( $retrieved_patron->_instance_cache_get('has_overdues'), 1, 'has_overdues cache has been set' );
292
    # Cache is used
293
    is( $retrieved_patron->has_overdues({ cache => 1}), 1, 'has_overdues cache is used');
294
281
    $issue->delete();
295
    $issue->delete();
296
297
    # Cache is used (with stale entry, flushing cache must be handled manually as automatic invalidation is
298
    # complex and probably not worth the effort)
299
    is( $retrieved_patron->has_overdues({ cache => 1}), 1, );
300
301
    # Cache has been invalidated
302
    is( $retrieved_patron->has_overdues, 0, );
282
};
303
};
283
304
284
subtest 'is_expired' => sub {
305
subtest 'is_expired' => sub {
285
    plan tests => 4;
306
    plan tests => 15;
286
    my $patron = $builder->build({ source => 'Borrower' });
307
    my $patron = $builder->build({ source => 'Borrower' });
287
    $patron = Koha::Patrons->find( $patron->{borrowernumber} );
308
    $patron = Koha::Patrons->find( $patron->{borrowernumber} );
288
    $patron->dateexpiry( undef )->store->discard_changes;
309
    $patron->dateexpiry( undef )->store->discard_changes;
289
    is( $patron->is_expired, 0, 'Patron should not be considered expired if dateexpiry is not set');
310
    is( $patron->is_expired, 0, 'Patron should not be considered expired if dateexpiry is not set' );
290
    $patron->dateexpiry( dt_from_string )->store->discard_changes;
311
    $patron->dateexpiry( dt_from_string )->store->discard_changes;
291
    is( $patron->is_expired, 0, 'Patron should not be considered expired if dateexpiry is today');
312
    is( $patron->is_expired, 0, 'Patron should not be considered expired if dateexpiry is today' );
292
    $patron->dateexpiry( dt_from_string->add( days => 1 ) )->store->discard_changes;
313
    $patron->dateexpiry( dt_from_string->add( days => 1 ) )->store->discard_changes;
293
    is( $patron->is_expired, 0, 'Patron should not be considered expired if dateexpiry is tomorrow');
314
    is( $patron->is_expired, 0, 'Patron should not be considered expired if dateexpiry is tomorrow' );
315
    $patron->dateexpiry( dt_from_string->add( days => -1 ) )->store->discard_changes;
316
    is( $patron->is_expired, 1, 'Patron should be considered expired if dateexpiry is yesterday' );
317
318
    # Test is_expired cache
319
    $patron->dateexpiry( undef )->store->discard_changes;
320
    # Set cache
321
    is( $patron->is_expired({ cache => 1 }), 0, 'Patron should not be considered expired if dateexpiry is not set, with caching enabled' );
322
    is( $patron->_instance_cache_get('is_expired'), 0, 'is_expired cache has been set');
323
    is( $patron->is_expired({ cache => 1 }), 0, 'Patron should not be considered expired if dateexpiry is not set, with caching enabled and cache hit' );
294
    $patron->dateexpiry( dt_from_string->add( days => -1 ) )->store->discard_changes;
324
    $patron->dateexpiry( dt_from_string->add( days => -1 ) )->store->discard_changes;
295
    is( $patron->is_expired, 1, 'Patron should be considered expired if dateexpiry is yesterday');
325
    is( $patron->is_expired({ cache => 1 }), 1, 'Patron should be considered expired if dateexpiry is yesterday, cache has been invalidated' );
326
    is( $patron->_instance_cache_get('is_expired'), 1, 'is_expired cache has been set');
327
    is( $patron->is_expired({ cache => 1 }), 1, 'Patron should be considered expired if dateexpiry is yesterday, on cache hit' );
328
329
    $patron->{dateexpiry} = undef;
330
    # Checking cache is really utilized by setting dateexpiry property without using accessor method
331
    is( $patron->is_expired({ cache => 1 }), 1, 'Cache is used with stale value' );
332
333
    $patron->set({ dateexpiry => undef })->store->discard_changes;
334
    is( $patron->is_expired({ cache => 1 }), 0, 'Patron should not be considered expired if dateexpiry is not set, cache has been invalidated' );
335
    is( $patron->is_expired({ cache => 1 }), 0, 'Patron should not be considered expired if dateexpiry is not set, on cache hit' );
336
337
    $patron->is_expired;
338
    is( $patron->_instance_cache_get('is_expired'), undef , 'Cache has been invalidated after calling is_expired without caching enabled' );
339
340
    # Set cache
341
    $patron->is_expired({ cache => 1 });
342
    # Clear cache using public method accessor_cache_clear
343
    $patron->accessor_cache_clear('is_expired');
344
    is( $patron->_instance_cache_get('is_expired'), undef , 'Cache has been invalidated after calling accessor_cache_clear' );
296
345
297
    $patron->delete;
346
    $patron->delete;
298
};
347
};
299
- 

Return to bug 32476