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

(-)a/C4/Circulation.pm (-50 / +65 lines)
Lines 71-77 use Koha::Patron::Quota; Link Here
71
use Koha::Patron::Quota::Usage;
71
use Koha::Patron::Quota::Usage;
72
use Koha::Patron::Quota::Usages;
72
use Koha::Patron::Quota::Usages;
73
73
74
use Carp qw( carp );
74
use Carp            qw( carp );
75
use List::MoreUtils qw( any );
75
use List::MoreUtils qw( any );
76
use Scalar::Util    qw( looks_like_number blessed );
76
use Scalar::Util    qw( looks_like_number blessed );
77
use Date::Calc      qw( Date_to_Days );
77
use Date::Calc      qw( Date_to_Days );
Lines 1377-1402 sub CanBookBeIssued { Link Here
1377
    }
1377
    }
1378
1378
1379
    # CHECK FOR QUOTAS
1379
    # CHECK FOR QUOTAS
1380
    if ( my $quotas = $patron->all_quotas->filter_by_active ) {
1380
    if ( C4::Context->preference('EnableCirculationQuotas') ) {
1381
        if ( $quotas->count > 1 ) {
1381
        if ( my $quotas = $patron->all_quotas->filter_by_active ) {
1382
1382
            if ( $quotas->count > 1 ) {
1383
            # Multiple available quotas found - need confirmation from user
1383
1384
            $needsconfirmation{QUOTA_SELECT} = $quotas;
1384
                # Multiple available quotas found - need confirmation from user
1385
        } elsif ( $quotas->count == 1 ) {
1385
                $needsconfirmation{QUOTA_SELECT} = $quotas;
1386
            my $quota = $quotas->next;
1386
            } elsif ( $quotas->count == 1 ) {
1387
            if ( !$quota->has_available_quota ) {
1387
                my $quota = $quotas->next;
1388
                if ( C4::Context->preference("AllowQuotaOverride") ) {
1388
                if ( !$quota->has_available_quota ) {
1389
                    $needsconfirmation{QUOTA_EXCEEDED} = {
1389
                    if ( C4::Context->preference("AllowQuotaOverride") ) {
1390
                        available => $quota->available_quota,
1390
                        $needsconfirmation{QUOTA_EXCEEDED} = {
1391
                        total     => $quota->allocation,
1391
                            available => $quota->available_quota,
1392
                        used      => $quota->used,
1392
                            total     => $quota->allocation,
1393
                    };
1393
                            used      => $quota->used,
1394
                } else {
1394
                        };
1395
                    $issuingimpossible{QUOTA_EXCEEDED} = {
1395
                    } else {
1396
                        available => $quota->available_quota,
1396
                        $issuingimpossible{QUOTA_EXCEEDED} = {
1397
                        total     => $quota->allocation,
1397
                            available => $quota->available_quota,
1398
                        used      => $quota->used,
1398
                            total     => $quota->allocation,
1399
                    };
1399
                            used      => $quota->used,
1400
                        };
1401
                    }
1400
                }
1402
                }
1401
            }
1403
            }
1402
        }
1404
        }
Lines 2021-2039 sub AddIssue { Link Here
2021
                if C4::Context->preference('RealTimeHoldsQueue');
2023
                if C4::Context->preference('RealTimeHoldsQueue');
2022
2024
2023
            # Check quotas and record usage if needed
2025
            # Check quotas and record usage if needed
2024
            my $quota;
2026
            if ( C4::Context->preference('EnableCirculationQuotas') ) {
2025
            if ($selected_quota_id) {
2027
                my $quota;
2026
                $quota = Koha::Patron::Quotas->find($selected_quota_id);
2028
                if ($selected_quota_id) {
2027
            } else {
2029
                    $quota = Koha::Patron::Quotas->find($selected_quota_id);
2028
                $quota = $patron->all_quotas->filter_by_active->single;
2030
                } else {
2029
            }
2031
                    $quota = $patron->all_quotas->filter_by_active->single;
2032
                }
2033
2034
                if ($quota) {
2030
2035
2031
            if ($quota) {
2036
                    # Update patron's used quota value
2032
              # Update patron's used quota value
2037
                    $quota->add_usage(
2033
              $quota->add_usage({
2038
                        {
2034
                    patron_id => $patron->patron_id, 
2039
                            patron_id => $patron->borrowernumber,
2035
                    issue_id => $issue->issue_id,
2040
                            issue_id  => $issue->issue_id,
2036
                });
2041
                        }
2042
                    );
2043
                }
2037
            }
2044
            }
2038
        }
2045
        }
2039
    }
2046
    }
Lines 3389-3406 sub CanBookBeRenewed { Link Here
3389
        }
3396
        }
3390
    }
3397
    }
3391
3398
3392
    # # CHECK FOR QUOTAS  
3399
    # # CHECK FOR QUOTAS
3393
    if ( my $quota_usage = Koha::Patron::Quota::Usages->find( { issue_id => $issue->issue_id } ) ) {
3400
    if ( C4::Context->preference('EnableCirculationQuotas') ) {
3401
        if ( my $quota_usage = Koha::Patron::Quota::Usages->find( { issue_id => $issue->issue_id } ) ) {
3394
3402
3395
        # Get current actives quota for the patron
3403
            # Get current actives quota for the patron
3396
        if ( my $active_quotas = $patron->all_quotas->filter_by_active ) {
3404
            if ( my $active_quotas = $patron->all_quotas->filter_by_active ) {
3397
            my $all_exceeded = 1;
3405
                my $all_exceeded = 1;
3398
            while ( my $active_quota = $active_quotas->next ) {
3406
                while ( my $active_quota = $active_quotas->next ) {
3399
                if ( $active_quota->has_available_quota ) {
3407
                    if ( $active_quota->has_available_quota ) {
3400
                    $all_exceeded = 0;
3408
                        $all_exceeded = 0;
3409
                    }
3401
                }
3410
                }
3411
                return ( 0, "QUOTA_EXCEEDED" ) if $all_exceeded;
3402
            }
3412
            }
3403
            return ( 0, "QUOTA_EXCEEDED" ) if $all_exceeded;
3404
        }
3413
        }
3405
    }
3414
    }
3406
3415
Lines 3519-3532 sub AddRenewal { Link Here
3519
    my $circ_library = Koha::Libraries->find( _GetCircControlBranch( $item_object, $patron ) );
3528
    my $circ_library = Koha::Libraries->find( _GetCircControlBranch( $item_object, $patron ) );
3520
3529
3521
    # Check quotas and record usage if needed
3530
    # Check quotas and record usage if needed
3522
    if (my $quota_usage = Koha::Patron::Quota::Usages->find({ issue_id => $issue->issue_id })) {
3531
    if ( C4::Context->preference('EnableCirculationQuotas') ) {
3523
        # Get current active quota for the patron
3532
        if ( my $quota_usage = Koha::Patron::Quota::Usages->find( { issue_id => $issue->issue_id } ) ) {
3524
        if (my $active_quota = Koha::Patron::Quotas->find($quota_usage->patron_quota_id)) {
3533
3525
            # Update patron's used quota value
3534
            # Get current active quota for the patron
3526
                $active_quota->add_usage({
3535
            if ( my $active_quota = Koha::Patron::Quotas->find( $quota_usage->patron_quota_id ) ) {
3527
                    patron_id => $patron->borrowernumber,
3536
3528
                    issue_id  => $issue->issue_id,
3537
                # Update patron's used quota value
3529
                });
3538
                $active_quota->add_usage(
3539
                    {
3540
                        patron_id => $patron->borrowernumber,
3541
                        issue_id  => $issue->issue_id,
3542
                    }
3543
                );
3544
            }
3530
        }
3545
        }
3531
    }
3546
    }
3532
3547
(-)a/installer/data/mysql/atomicupdate/bug_38924-patron_quotas.pl (-11 / +17 lines)
Lines 25-45 return { Link Here
25
                ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
25
                ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
26
                }
26
                }
27
            );
27
            );
28
            
28
29
            $dbh->do(q{
29
            $dbh->do(
30
                q{
30
                INSERT IGNORE INTO permissions (module_bit, code, description) VALUES
31
                INSERT IGNORE INTO permissions (module_bit, code, description) VALUES
31
                (4, 'manage_borrower_quotas', 'Manage patron quotas'),
32
                (4, 'manage_borrower_quotas', 'Manage patron quotas'),
32
                (4, 'view_borrower_quotas', 'View patron quotas')
33
                (4, 'view_borrower_quotas', 'View patron quotas')
33
            });
34
            }
34
            
35
            );
36
35
            say_success( $out, "Patron quota table and permissions created successfully" );
37
            say_success( $out, "Patron quota table and permissions created successfully" );
36
        } else {
38
        } else {
37
            say_info( $out, "Patron quota table already exists" );
39
            say_info( $out, "Patron quota table already exists" );
38
        }
40
        }
39
41
40
        unless ( TableExists('patron_quota_usage') )
42
        unless ( TableExists('patron_quota_usage') ) {
41
        {
43
            $dbh->do(
42
            $dbh->do(q{
44
                q{
43
                CREATE TABLE `patron_quota_usage` (
45
                CREATE TABLE `patron_quota_usage` (
44
                  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'unique identifier for quota usage record',
46
                  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'unique identifier for quota usage record',
45
                  `patron_quota_id` int(11) NOT NULL COMMENT 'foreign key linking to patron_quota.id',
47
                  `patron_quota_id` int(11) NOT NULL COMMENT 'foreign key linking to patron_quota.id',
Lines 54-72 return { Link Here
54
                  CONSTRAINT `patron_quota_usage_ibfk_1` FOREIGN KEY (`patron_quota_id`) REFERENCES `patron_quota` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
56
                  CONSTRAINT `patron_quota_usage_ibfk_1` FOREIGN KEY (`patron_quota_id`) REFERENCES `patron_quota` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
55
                  CONSTRAINT `patron_quota_usage_ibfk_2` FOREIGN KEY (`patron_id`) REFERENCES `borrowers` (`borrowernumber`) ON DELETE CASCADE ON UPDATE CASCADE
57
                  CONSTRAINT `patron_quota_usage_ibfk_2` FOREIGN KEY (`patron_id`) REFERENCES `borrowers` (`borrowernumber`) ON DELETE CASCADE ON UPDATE CASCADE
56
                ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
58
                ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
57
            });
59
            }
60
            );
58
61
59
            say_success( $out, "Patron quota usage table created successfully" );
62
            say_success( $out, "Patron quota usage table created successfully" );
60
        } else {
63
        } else {
61
            say_info( $out, "Patron quota usage table already exists" );
64
            say_info( $out, "Patron quota usage table already exists" );
62
        }
65
        }
63
66
64
        $dbh->do(q{
67
        $dbh->do(
68
            q{
65
            INSERT IGNORE INTO systempreferences (variable, value, options, explanation, type)
69
            INSERT IGNORE INTO systempreferences (variable, value, options, explanation, type)
66
            VALUES
70
            VALUES
67
            ('AllowQuotaOverride', '0', NULL, 'Allow staff to override and check out items to patrons who have exceeded their quota limit', 'YesNo'),
71
            ('AllowQuotaOverride', '0', NULL, 'Allow staff to override and check out items to patrons who have exceeded their quota limit', 'YesNo'),
68
            ('UseGuarantorQuota', '0', NULL, 'Use guarantor quota instead of guarantee quota when checking out items', 'YesNo')
72
            ('UseGuarantorQuota', '0', NULL, 'Use guarantor quota instead of guarantee quota when checking out items', 'YesNo'),
69
        });
73
            ('EnableCirculationQuotas','0','','Enable or disable the circulation quotas feature','YesNo')
74
        }
75
        );
70
76
71
        say_success( $out, "Patron quota preferences added successfully" );
77
        say_success( $out, "Patron quota preferences added successfully" );
72
    },
78
    },
(-)a/installer/data/mysql/mandatory/sysprefs.sql (+1 lines)
Lines 258-263 INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, ` Link Here
258
('EnableAdvancedCatalogingEditor','0','','Enable the Rancor advanced cataloging editor','YesNo'),
258
('EnableAdvancedCatalogingEditor','0','','Enable the Rancor advanced cataloging editor','YesNo'),
259
('EnableBooking','1',NULL,'If enabled, activate every functionnalities related with Bookings module','YesNo'),
259
('EnableBooking','1',NULL,'If enabled, activate every functionnalities related with Bookings module','YesNo'),
260
('EnableBorrowerFiles','0',NULL,'If enabled, allows librarians to upload and attach arbitrary files to a borrower record.','YesNo'),
260
('EnableBorrowerFiles','0',NULL,'If enabled, allows librarians to upload and attach arbitrary files to a borrower record.','YesNo'),
261
('EnableCirculationQuotas','0','','Enable or disable the circulation quotas feature','YesNo'),
261
('EnableExpiredPasswordReset', '0', NULL, 'Enable ability for patrons with expired password to reset their password directly', 'YesNo'),
262
('EnableExpiredPasswordReset', '0', NULL, 'Enable ability for patrons with expired password to reset their password directly', 'YesNo'),
262
('EnableItemGroupHolds','0','','Enable item groups holds feature','YesNo'),
263
('EnableItemGroupHolds','0','','Enable item groups holds feature','YesNo'),
263
('EnableItemGroups','0','','Enable the item groups feature','YesNo'),
264
('EnableItemGroups','0','','Enable the item groups feature','YesNo'),
(-)a/koha-tmpl/intranet-tmpl/prog/en/includes/circ-menu.inc (+2 lines)
Lines 203-213 Link Here
203
                    </li>
203
                    </li>
204
                [% END %]
204
                [% END %]
205
            [% END %]
205
            [% END %]
206
            [% IF Koha.Preference('EnableCirculationQuotas') %]
206
                [% IF patron.category.category_type == 'I' %]
207
                [% IF patron.category.category_type == 'I' %]
207
                    <li [% IF ( quotaview ) %]class="active">[% END %]>
208
                    <li [% IF ( quotaview ) %]class="active">[% END %]>
208
                        <a href="/cgi-bin/koha/members/circulation_quota.pl?borrowernumber=[% patron.borrowernumber | uri %]">Circulation quota</a>
209
                        <a href="/cgi-bin/koha/members/circulation_quota.pl?borrowernumber=[% patron.borrowernumber | uri %]">Circulation quota</a>
209
                    </li>
210
                    </li>
210
                [% END %]
211
                [% END %]
212
            [% END %]
211
            [% IF CAN_user_borrowers_edit_borrowers %]
213
            [% IF CAN_user_borrowers_edit_borrowers %]
212
                [% IF ( IntranetReadingHistoryHolds ) %]
214
                [% IF ( IntranetReadingHistoryHolds ) %]
213
                    <li [% IF holdshistoryview %]class="active"[% END %]>
215
                    <li [% IF holdshistoryview %]class="active"[% END %]>
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref (-13 / +19 lines)
Lines 389-406 Circulation: Link Here
389
                  1: Allow
389
                  1: Allow
390
                  0: "Don't allow"
390
                  0: "Don't allow"
391
            - staff to check out an item with age restriction.
391
            - staff to check out an item with age restriction.
392
        -
393
            - pref: AllowQuotaOverride
394
              choices:
395
                  1: "Allow"
396
                  0: "Don't allow" 
397
            - staff to check out items to patrons who have exceeded their quota limit.
398
        -
399
            - pref: UseGuarantorQuota
400
              choices:
401
                  1: "Use"
402
                  0: "Don't use"
403
            - guarantor's quota instead of guarantee's quota when checking out items if guarantor has an active quota and quota has enough availability.
404
        -
392
        -
405
            - Prevent patrons from checking out items if they have more than
393
            - Prevent patrons from checking out items if they have more than
406
            - pref: noissuescharge
394
            - pref: noissuescharge
Lines 1347-1352 Circulation: Link Here
1347
            - pref: SCOBatchCheckoutsValidCategories
1335
            - pref: SCOBatchCheckoutsValidCategories
1348
              choices: patron-categories
1336
              choices: patron-categories
1349
              class: multiple
1337
              class: multiple
1338
    Quotas:
1339
        -
1340
            - pref: EnableCirculationQuotas
1341
              choices:
1342
                  1: "Enable"
1343
                  0: "Disable"
1344
            - circulation quotas for patrons.
1345
        -
1346
            - pref: AllowQuotaOverride
1347
              choices:
1348
                  1: "Allow"
1349
                  0: "Don't allow" 
1350
            - staff to check out items to patrons who have exceeded their quota limit.
1351
        -
1352
            - pref: UseGuarantorQuota
1353
              choices:
1354
                  1: "Use"
1355
                  0: "Don't use"
1356
            - guarantor's quota instead of guarantee's quota when checking out items if guarantor has an active quota and quota has enough availability.
1350
    Course reserves:
1357
    Course reserves:
1351
        -
1358
        -
1352
            - pref: UseCourseReserves
1359
            - pref: UseCourseReserves
1353
- 

Return to bug 38924