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

(-)a/C4/Circulation.pm (-67 / +77 lines)
Lines 2233-2246 Internal function, called only by AddReturn that calculates and updates Link Here
2233
2233
2234
Should only be called for overdue returns
2234
Should only be called for overdue returns
2235
2235
2236
Calculation of the debarment date has been moved to a separate subroutine _calculate_new_debar_dt
2237
to ease testing.
2238
2236
=cut
2239
=cut
2237
2240
2238
sub _debar_user_on_return {
2241
sub _calculate_new_debar_dt {
2239
    my ( $borrower, $item, $dt_due, $return_date ) = @_;
2242
    my ( $borrower, $item, $dt_due, $return_date ) = @_;
2240
2243
2241
    my $branchcode = _GetCircControlBranch( $item, $borrower );
2244
    my $branchcode = _GetCircControlBranch( $item, $borrower );
2242
    $return_date //= dt_from_string();
2243
2244
    my $circcontrol = C4::Context->preference('CircControl');
2245
    my $circcontrol = C4::Context->preference('CircControl');
2245
    my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule(
2246
    my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule(
2246
        {   categorycode => $borrower->{categorycode},
2247
        {   categorycode => $borrower->{categorycode},
Lines 2252-2332 sub _debar_user_on_return { Link Here
2252
    my $unit     = $issuing_rule ? $issuing_rule->lengthunit : undef;
2253
    my $unit     = $issuing_rule ? $issuing_rule->lengthunit : undef;
2253
    my $chargeable_units = C4::Overdues::get_chargeable_units($unit, $dt_due, $return_date, $branchcode);
2254
    my $chargeable_units = C4::Overdues::get_chargeable_units($unit, $dt_due, $return_date, $branchcode);
2254
2255
2255
    if ($finedays) {
2256
    return unless $finedays;
2256
2257
        # finedays is in days, so hourly loans must multiply by 24
2258
        # thus 1 hour late equals 1 day suspension * finedays rate
2259
        $finedays = $finedays * 24 if ( $unit eq 'hours' );
2260
2257
2261
        # grace period is measured in the same units as the loan
2258
    # finedays is in days, so hourly loans must multiply by 24
2262
        my $grace =
2259
    # thus 1 hour late equals 1 day suspension * finedays rate
2263
          DateTime::Duration->new( $unit => $issuing_rule->firstremind );
2260
    $finedays = $finedays * 24 if ( $unit eq 'hours' );
2264
2261
2265
        my $deltadays = DateTime::Duration->new(
2262
    # grace period is measured in the same units as the loan
2266
            days => $chargeable_units
2263
    my $grace =
2267
        );
2264
      DateTime::Duration->new( $unit => $issuing_rule->firstremind );
2268
        if ( $deltadays->subtract($grace)->is_positive() ) {
2269
            my $suspension_days = $deltadays * $finedays;
2270
2271
            # If the max suspension days is < than the suspension days
2272
            # the suspension days is limited to this maximum period.
2273
            my $max_sd = $issuing_rule->maxsuspensiondays;
2274
            if ( defined $max_sd ) {
2275
                $max_sd = DateTime::Duration->new( days => $max_sd );
2276
                $suspension_days = $max_sd
2277
                  if DateTime::Duration->compare( $max_sd, $suspension_days ) < 0;
2278
            }
2279
2265
2280
            my ( $has_been_extended, $is_a_reminder );
2266
    my $deltadays = DateTime::Duration->new(
2281
            if ( C4::Context->preference('CumulativeRestrictionPeriods') and $borrower->{debarred} ) {
2267
        days => $chargeable_units
2282
                my $debarment = @{ GetDebarments( { borrowernumber => $borrower->{borrowernumber}, type => 'SUSPENSION' } ) }[0];
2268
    );
2283
                if ( $debarment ) {
2269
    if ( $deltadays->subtract($grace)->is_positive() ) {
2284
                    $return_date = dt_from_string( $debarment->{expiration}, 'sql' );
2270
        my $suspension_days = $deltadays * $finedays;
2285
                    $has_been_extended = 1;
2271
2286
                }
2272
        # If the max suspension days is < than the suspension days
2287
            }
2273
        # the suspension days is limited to this maximum period.
2274
        my $max_sd = $issuing_rule->maxsuspensiondays;
2275
        if ( defined $max_sd ) {
2276
            $max_sd = DateTime::Duration->new( days => $max_sd );
2277
            $suspension_days = $max_sd
2278
              if DateTime::Duration->compare( $max_sd, $suspension_days ) < 0;
2279
        }
2288
2280
2289
            if ( $issuing_rule->suspension_chargeperiod > 1 ) {
2281
        my ( $has_been_extended );
2290
                # No need to / 1 and do not consider / 0
2282
        if ( C4::Context->preference('CumulativeRestrictionPeriods') and $borrower->{debarred} ) {
2291
                $suspension_days = DateTime::Duration->new(
2283
            my $debarment = @{ GetDebarments( { borrowernumber => $borrower->{borrowernumber}, type => 'SUSPENSION' } ) }[0];
2292
                    days => floor( $suspension_days->in_units('days') / $issuing_rule->suspension_chargeperiod )
2284
            if ( $debarment ) {
2293
                );
2285
                $return_date = dt_from_string( $debarment->{expiration}, 'sql' );
2286
                $has_been_extended = 1;
2294
            }
2287
            }
2288
        }
2295
2289
2296
            my $new_debar_dt;
2290
        if ( $issuing_rule->suspension_chargeperiod > 1 ) {
2297
            # Use the calendar or not to calculate the debarment date
2291
            # No need to / 1 and do not consider / 0
2298
            if ( C4::Context->preference('SuspensionsCalendar') eq 'noSuspensionsWhenClosed' ) {
2292
            $suspension_days = DateTime::Duration->new(
2299
                my $calendar = Koha::Calendar->new(
2293
                days => floor( $suspension_days->in_units('days') / $issuing_rule->suspension_chargeperiod )
2300
                    branchcode => $branchcode,
2294
            );
2301
                    days_mode  => 'Calendar'
2295
        }
2302
                );
2303
                $new_debar_dt = $calendar->addDate( $return_date, $suspension_days );
2304
            }
2305
            else {
2306
                $new_debar_dt = $return_date->clone()->add_duration($suspension_days);
2307
            }
2308
2296
2309
            Koha::Patron::Debarments::AddUniqueDebarment({
2297
        my $new_debar_dt;
2310
                borrowernumber => $borrower->{borrowernumber},
2298
        # Use the calendar or not to calculate the debarment date
2311
                expiration     => $new_debar_dt->ymd(),
2299
        if ( C4::Context->preference('SuspensionsCalendar') eq 'noSuspensionsWhenClosed' ) {
2312
                type           => 'SUSPENSION',
2300
            my $calendar = Koha::Calendar->new(
2313
            });
2301
                branchcode => $branchcode,
2314
            # if borrower was already debarred but does not get an extra debarment
2302
                days_mode  => 'Calendar'
2315
            my $patron = Koha::Patrons->find( $borrower->{borrowernumber} );
2303
            );
2316
            my $new_debarment_str;
2304
            $new_debar_dt = $calendar->addDate( $return_date, $suspension_days );
2317
            if ( $borrower->{debarred} eq $patron->is_debarred ) {
2305
        }
2318
                $is_a_reminder = 1;
2306
        else {
2319
                $new_debarment_str = $borrower->{debarred};
2307
            $new_debar_dt = $return_date->clone()->add_duration($suspension_days);
2320
            } else {
2321
                $new_debarment_str = $new_debar_dt->ymd();
2322
            }
2323
            # FIXME Should return a DateTime object
2324
            return $new_debarment_str, $is_a_reminder;
2325
        }
2308
        }
2309
        return $new_debar_dt;
2326
    }
2310
    }
2327
    return;
2311
    return;
2328
}
2312
}
2329
2313
2314
sub _debar_user_on_return {
2315
    my ( $borrower, $item, $dt_due, $return_date ) = @_;
2316
2317
    $return_date //= dt_from_string();
2318
2319
    my $new_debar_dt = _calculate_new_debar_dt ($borrower, $item, $dt_due, $return_date);
2320
2321
    return unless $new_debar_dt;
2322
2323
    Koha::Patron::Debarments::AddUniqueDebarment({
2324
        borrowernumber => $borrower->{borrowernumber},
2325
        expiration     => $new_debar_dt->ymd(),
2326
        type           => 'SUSPENSION',
2327
    });
2328
    # if borrower was already debarred but does not get an extra debarment
2329
    my $patron = Koha::Patrons->find( $borrower->{borrowernumber} );
2330
    my ($new_debarment_str, $is_a_reminder);
2331
    if ( $borrower->{debarred} eq $patron->is_debarred ) {
2332
        $is_a_reminder = 1;
2333
        $new_debarment_str = $borrower->{debarred};
2334
    } else {
2335
        $new_debarment_str = $new_debar_dt->ymd();
2336
    }
2337
    # FIXME Should return a DateTime object
2338
    return $new_debarment_str, $is_a_reminder;
2339
}
2340
2330
=head2 _FixOverduesOnReturn
2341
=head2 _FixOverduesOnReturn
2331
2342
2332
   &_FixOverduesOnReturn($borrowernumber, $itemnumber, $exemptfine, $status);
2343
   &_FixOverduesOnReturn($borrowernumber, $itemnumber, $exemptfine, $status);
2333
- 

Return to bug 24138