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

(-)a/C4/Circulation.pm (-49 / +64 lines)
Lines 1376-1401 sub CanBookBeIssued { Link Here
1376
    }
1376
    }
1377
1377
1378
    # CHECK FOR QUOTAS
1378
    # CHECK FOR QUOTAS
1379
    if ( my $quotas = $patron->all_quotas->filter_by_active ) {
1379
    if ( C4::Context->preference('EnableCirculationQuotas') ) {
1380
        if ( $quotas->count > 1 ) {
1380
        if ( my $quotas = $patron->all_quotas->filter_by_active ) {
1381
1381
            if ( $quotas->count > 1 ) {
1382
            # Multiple available quotas found - need confirmation from user
1382
1383
            $needsconfirmation{QUOTA_SELECT} = $quotas;
1383
                # Multiple available quotas found - need confirmation from user
1384
        } elsif ( $quotas->count == 1 ) {
1384
                $needsconfirmation{QUOTA_SELECT} = $quotas;
1385
            my $quota = $quotas->next;
1385
            } elsif ( $quotas->count == 1 ) {
1386
            if ( !$quota->has_available_quota ) {
1386
                my $quota = $quotas->next;
1387
                if ( C4::Context->preference("AllowQuotaOverride") ) {
1387
                if ( !$quota->has_available_quota ) {
1388
                    $needsconfirmation{QUOTA_EXCEEDED} = {
1388
                    if ( C4::Context->preference("AllowQuotaOverride") ) {
1389
                        available => $quota->available_quota,
1389
                        $needsconfirmation{QUOTA_EXCEEDED} = {
1390
                        total     => $quota->allocation,
1390
                            available => $quota->available_quota,
1391
                        used      => $quota->used,
1391
                            total     => $quota->allocation,
1392
                    };
1392
                            used      => $quota->used,
1393
                } else {
1393
                        };
1394
                    $issuingimpossible{QUOTA_EXCEEDED} = {
1394
                    } else {
1395
                        available => $quota->available_quota,
1395
                        $issuingimpossible{QUOTA_EXCEEDED} = {
1396
                        total     => $quota->allocation,
1396
                            available => $quota->available_quota,
1397
                        used      => $quota->used,
1397
                            total     => $quota->allocation,
1398
                    };
1398
                            used      => $quota->used,
1399
                        };
1400
                    }
1399
                }
1401
                }
1400
            }
1402
            }
1401
        }
1403
        }
Lines 2031-2049 sub AddIssue { Link Here
2031
                if C4::Context->preference('RealTimeHoldsQueue');
2033
                if C4::Context->preference('RealTimeHoldsQueue');
2032
2034
2033
            # Check quotas and record usage if needed
2035
            # Check quotas and record usage if needed
2034
            my $quota;
2036
            if ( C4::Context->preference('EnableCirculationQuotas') ) {
2035
            if ($selected_quota_id) {
2037
                my $quota;
2036
                $quota = Koha::Patron::Quotas->find($selected_quota_id);
2038
                if ($selected_quota_id) {
2037
            } else {
2039
                    $quota = Koha::Patron::Quotas->find($selected_quota_id);
2038
                $quota = $patron->all_quotas->filter_by_active->single;
2040
                } else {
2039
            }
2041
                    $quota = $patron->all_quotas->filter_by_active->single;
2042
                }
2043
2044
                if ($quota) {
2040
2045
2041
            if ($quota) {
2046
                    # Update patron's used quota value
2042
              # Update patron's used quota value
2047
                    $quota->add_usage(
2043
              $quota->add_usage({
2048
                        {
2044
                    patron_id => $patron->patron_id, 
2049
                            patron_id => $patron->borrowernumber,
2045
                    issue_id => $issue->issue_id,
2050
                            issue_id  => $issue->issue_id,
2046
                });
2051
                        }
2052
                    );
2053
                }
2047
            }
2054
            }
2048
        }
2055
        }
2049
    }
2056
    }
Lines 3418-3435 sub CanBookBeRenewed { Link Here
3418
        }
3425
        }
3419
    }
3426
    }
3420
3427
3421
    # # CHECK FOR QUOTAS  
3428
    # # CHECK FOR QUOTAS
3422
    if ( my $quota_usage = Koha::Patron::Quota::Usages->find( { issue_id => $issue->issue_id } ) ) {
3429
    if ( C4::Context->preference('EnableCirculationQuotas') ) {
3430
        if ( my $quota_usage = Koha::Patron::Quota::Usages->find( { issue_id => $issue->issue_id } ) ) {
3423
3431
3424
        # Get current actives quota for the patron
3432
            # Get current actives quota for the patron
3425
        if ( my $active_quotas = $patron->all_quotas->filter_by_active ) {
3433
            if ( my $active_quotas = $patron->all_quotas->filter_by_active ) {
3426
            my $all_exceeded = 1;
3434
                my $all_exceeded = 1;
3427
            while ( my $active_quota = $active_quotas->next ) {
3435
                while ( my $active_quota = $active_quotas->next ) {
3428
                if ( $active_quota->has_available_quota ) {
3436
                    if ( $active_quota->has_available_quota ) {
3429
                    $all_exceeded = 0;
3437
                        $all_exceeded = 0;
3438
                    }
3430
                }
3439
                }
3440
                return ( 0, "QUOTA_EXCEEDED" ) if $all_exceeded;
3431
            }
3441
            }
3432
            return ( 0, "QUOTA_EXCEEDED" ) if $all_exceeded;
3433
        }
3442
        }
3434
    }
3443
    }
3435
3444
Lines 3548-3561 sub AddRenewal { Link Here
3548
    my $circ_library = Koha::Libraries->find( _GetCircControlBranch( $item_object, $patron ) );
3557
    my $circ_library = Koha::Libraries->find( _GetCircControlBranch( $item_object, $patron ) );
3549
3558
3550
    # Check quotas and record usage if needed
3559
    # Check quotas and record usage if needed
3551
    if (my $quota_usage = Koha::Patron::Quota::Usages->find({ issue_id => $issue->issue_id })) {
3560
    if ( C4::Context->preference('EnableCirculationQuotas') ) {
3552
        # Get current active quota for the patron
3561
        if ( my $quota_usage = Koha::Patron::Quota::Usages->find( { issue_id => $issue->issue_id } ) ) {
3553
        if (my $active_quota = Koha::Patron::Quotas->find($quota_usage->patron_quota_id)) {
3562
3554
            # Update patron's used quota value
3563
            # Get current active quota for the patron
3555
                $active_quota->add_usage({
3564
            if ( my $active_quota = Koha::Patron::Quotas->find( $quota_usage->patron_quota_id ) ) {
3556
                    patron_id => $patron->borrowernumber,
3565
3557
                    issue_id  => $issue->issue_id,
3566
                # Update patron's used quota value
3558
                });
3567
                $active_quota->add_usage(
3568
                    {
3569
                        patron_id => $patron->borrowernumber,
3570
                        issue_id  => $issue->issue_id,
3571
                    }
3572
                );
3573
            }
3559
        }
3574
        }
3560
    }
3575
    }
3561
3576
(-)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 261-266 INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, ` Link Here
261
('EnableAdvancedCatalogingEditor','0',NULL,'Enable the Rancor advanced cataloging editor','YesNo'),
261
('EnableAdvancedCatalogingEditor','0',NULL,'Enable the Rancor advanced cataloging editor','YesNo'),
262
('EnableBooking','1',NULL,'If enabled, activate every functionalities related with Bookings module','YesNo'),
262
('EnableBooking','1',NULL,'If enabled, activate every functionalities related with Bookings module','YesNo'),
263
('EnableBorrowerFiles','0',NULL,'If enabled, allows librarians to upload and attach arbitrary files to a borrower record.','YesNo'),
263
('EnableBorrowerFiles','0',NULL,'If enabled, allows librarians to upload and attach arbitrary files to a borrower record.','YesNo'),
264
('EnableCirculationQuotas','0','','Enable or disable the circulation quotas feature','YesNo'),
264
('EnableExpiredPasswordReset', '0', NULL, 'Enable ability for patrons with expired password to reset their password directly', 'YesNo'),
265
('EnableExpiredPasswordReset', '0', NULL, 'Enable ability for patrons with expired password to reset their password directly', 'YesNo'),
265
('EnableItemGroupHolds','0',NULL,'Enable item groups holds feature','YesNo'),
266
('EnableItemGroupHolds','0',NULL,'Enable item groups holds feature','YesNo'),
266
('EnableItemGroups','0',NULL,'Enable the item groups feature','YesNo'),
267
('EnableItemGroups','0',NULL,'Enable the item groups feature','YesNo'),
(-)a/koha-tmpl/intranet-tmpl/prog/en/includes/circ-menu.inc (-4 / +6 lines)
Lines 211-220 Link Here
211
                    <a href="/cgi-bin/koha/members/holdshistory.pl?borrowernumber=[% patron.borrowernumber | uri %]">Holds history</a>
211
                    <a href="/cgi-bin/koha/members/holdshistory.pl?borrowernumber=[% patron.borrowernumber | uri %]">Holds history</a>
212
                </li>
212
                </li>
213
            [% END %]
213
            [% END %]
214
            [% IF patron.category.category_type == 'I' %]
214
            [% IF Koha.Preference('EnableCirculationQuotas') %]
215
                <li [% IF ( quotaview ) %]class="active"[% END %]>
215
                [% IF patron.category.category_type == 'I' %]
216
                    <a href="/cgi-bin/koha/members/circulation_quota.pl?borrowernumber=[% patron.borrowernumber | uri %]">Circulation quota</a>
216
                    <li [% IF ( quotaview ) %]class="active"[% END %]>
217
                </li>
217
                        <a href="/cgi-bin/koha/members/circulation_quota.pl?borrowernumber=[% patron.borrowernumber | uri %]">Circulation quota</a>
218
                    </li>
219
                [% END %]
218
            [% END %]
220
            [% END %]
219
            [% IF ( CAN_user_tools_view_system_logs ) %]
221
            [% IF ( CAN_user_tools_view_system_logs ) %]
220
                <li [% IF logview %]class="active"[% END %]>
222
                <li [% IF logview %]class="active"[% END %]>
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref (-13 / +19 lines)
Lines 402-419 Circulation: Link Here
402
                  1: Allow
402
                  1: Allow
403
                  0: "Don't allow"
403
                  0: "Don't allow"
404
            - staff to check out an item with age restriction.
404
            - staff to check out an item with age restriction.
405
        -
406
            - pref: AllowQuotaOverride
407
              choices:
408
                  1: "Allow"
409
                  0: "Don't allow" 
410
            - staff to check out items to patrons who have exceeded their quota limit.
411
        -
412
            - pref: UseGuarantorQuota
413
              choices:
414
                  1: "Use"
415
                  0: "Don't use"
416
            - guarantor's quota instead of guarantee's quota when checking out items if guarantor has an active quota and quota has enough availability.
417
        -
405
        -
418
            - Prevent patrons from checking out items if they have more than
406
            - Prevent patrons from checking out items if they have more than
419
            - pref: noissuescharge
407
            - pref: noissuescharge
Lines 1380-1385 Circulation: Link Here
1380
            - pref: SCOBatchCheckoutsValidCategories
1368
            - pref: SCOBatchCheckoutsValidCategories
1381
              choices: patron-categories
1369
              choices: patron-categories
1382
              class: multiple
1370
              class: multiple
1371
    Quotas:
1372
        -
1373
            - pref: EnableCirculationQuotas
1374
              choices:
1375
                  1: "Enable"
1376
                  0: "Disable"
1377
            - circulation quotas for patrons.
1378
        -
1379
            - pref: AllowQuotaOverride
1380
              choices:
1381
                  1: "Allow"
1382
                  0: "Don't allow" 
1383
            - staff to check out items to patrons who have exceeded their quota limit.
1384
        -
1385
            - pref: UseGuarantorQuota
1386
              choices:
1387
                  1: "Use"
1388
                  0: "Don't use"
1389
            - guarantor's quota instead of guarantee's quota when checking out items if guarantor has an active quota and quota has enough availability.
1383
    Course reserves:
1390
    Course reserves:
1384
        -
1391
        -
1385
            - pref: UseCourseReserves
1392
            - pref: UseCourseReserves
1386
- 

Return to bug 38924