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

(-)a/Koha/Patron.pm (-3 / +14 lines)
Lines 401-407 sub store { Link Here
401
                }
401
                }
402
402
403
                # Actionlogs
403
                # Actionlogs
404
                if ( C4::Context->preference("BorrowersLog") ) {
404
                if ( C4::Context->preference("BorrowersLog") || C4::Context->preference("CardnumberLog") ) {
405
                    my $info;
405
                    my $info;
406
                    my $from_storage = $self_from_storage->unblessed;
406
                    my $from_storage = $self_from_storage->unblessed;
407
                    my $from_object  = $self->unblessed;
407
                    my $from_object  = $self->unblessed;
Lines 413-419 sub store { Link Here
413
                        if $from_object->{dateexpiry};
413
                        if $from_object->{dateexpiry};
414
414
415
                    my @skip_fields = (qw/lastseen updated_on/);
415
                    my @skip_fields = (qw/lastseen updated_on/);
416
                    for my $key ( keys %{$from_storage} ) {
416
                    my @keys        = C4::Context->preference("BorrowersLog") ? keys %{$from_storage} : ('cardnumber');
417
                    for my $key (@keys) {
417
                        next if any { /$key/ } @skip_fields;
418
                        next if any { /$key/ } @skip_fields;
418
                        my $storage_value = $from_storage->{$key} // q{};
419
                        my $storage_value = $from_storage->{$key} // q{};
419
                        my $object_value  = $from_object->{$key}  // q{};
420
                        my $object_value  = $from_object->{$key}  // q{};
Lines 436-442 sub store { Link Here
436
                                $info,
437
                                $info,
437
                                { utf8 => 1, pretty => 1, canonical => 1 }
438
                                { utf8 => 1, pretty => 1, canonical => 1 }
438
                            )
439
                            )
439
                        );
440
                        ) if C4::Context->preference("BorrowersLog");
441
                        logaction(
442
                            "MEMBERS",
443
                            "MODIFY_CARDNUMBER",
444
                            $self->borrowernumber,
445
                            to_json(
446
                                $info->{cardnumber},
447
                                { utf8 => 1, pretty => 1, canonical => 1 }
448
                            )
449
                        ) if defined $info->{cardnumber} && C4::Context->preference("CardnumberLog");
450
440
                    }
451
                    }
441
                }
452
                }
442
453
(-)a/installer/data/mysql/mandatory/sysprefs.sql (+1 lines)
Lines 144-149 INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, ` Link Here
144
('CanMarkHoldsToPullAsLost','do_not_allow','do_not_allow|allow|allow_and_notify','Add a button to the "Holds to pull" screen to mark an item as lost and notify the patron.','Choice'),
144
('CanMarkHoldsToPullAsLost','do_not_allow','do_not_allow|allow|allow_and_notify','Add a button to the "Holds to pull" screen to mark an item as lost and notify the patron.','Choice'),
145
('canreservefromotherbranches','1','','With Independent branches on, can a user from one library place a hold on an item from another library','YesNo'),
145
('canreservefromotherbranches','1','','With Independent branches on, can a user from one library place a hold on an item from another library','YesNo'),
146
('CardnumberLength', '', '', 'Set a length for card numbers with a maximum of 32 characters.', 'Free'),
146
('CardnumberLength', '', '', 'Set a length for card numbers with a maximum of 32 characters.', 'Free'),
147
('CardnumberLog','1',NULL,'If ON, log edit actions on patron cardnumbers','YesNo'),
147
('casAuthentication','0','','Enable or disable CAS authentication','YesNo'),
148
('casAuthentication','0','','Enable or disable CAS authentication','YesNo'),
148
('casLogout','0','','Does a logout from Koha should also log the user out of CAS?','YesNo'),
149
('casLogout','0','','Does a logout from Koha should also log the user out of CAS?','YesNo'),
149
('casServerUrl','https://localhost:8443/cas','','URL of the cas server','Free'),
150
('casServerUrl','https://localhost:8443/cas','','URL of the cas server','Free'),
(-)a/koha-tmpl/intranet-tmpl/prog/en/includes/action-logs.inc (+2 lines)
Lines 147-152 Link Here
147
        <span>Overdue</span>
147
        <span>Overdue</span>
148
    [% CASE 'EXPIRE' %]
148
    [% CASE 'EXPIRE' %]
149
        <span>Expire</span>
149
        <span>Expire</span>
150
    [% CASE 'MODIFY_CARDNUMBER' %]
151
        <span>Modify cardnumber</span>
150
    [% CASE %]
152
    [% CASE %]
151
        [% action | html %]
153
        [% action | html %]
152
    [% END %]
154
    [% END %]
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/logs.pref (+6 lines)
Lines 12-17 Logging: Link Here
12
                  1: Log
12
                  1: Log
13
                  0: "Don't log"
13
                  0: "Don't log"
14
            - changes to patron records and patron restrictions.
14
            - changes to patron records and patron restrictions.
15
        -
16
            - pref: CardnumberLog
17
              choices:
18
                  1: Log
19
                  0: "Don't log"
20
            - changes to patron cardnumbers.
15
        -
21
        -
16
            - pref: CataloguingLog
22
            - pref: CataloguingLog
17
              choices:
23
              choices:
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/viewlog.tt (-1 / +1 lines)
Lines 147-153 Link Here
147
                            <label for="actionALL" class="viewlog"><input type="checkbox" id="actionALL" name="actions" value="" /> All</label>
147
                            <label for="actionALL" class="viewlog"><input type="checkbox" id="actionALL" name="actions" value="" /> All</label>
148
                        [% END %]
148
                        [% END %]
149
149
150
                        [% FOREACH actx IN [ 'ADD' 'DELETE' 'MODIFY' 'ISSUE' 'RETURN' 'RENEW' 'CREATE' 'CANCEL' 'FILL' 'SUSPEND' 'RESUME' 'ADDCIRCMESSAGE' 'MODCIRCMESSAGE' 'DELCIRCMESSAGE' 'STATUS_CHANGE' 'PATRON_NOTICE' 'CHANGE PASS' 'RESET PASS' 'Run' 'End' 'EDIT_MAPPINGS' 'RESET_MAPPINGS' 'ADD_BASKET' 'MODIFY_BASKET' 'MODIFY_BASKET_HEADER' 'MODIFY_BASKET_USERS' 'CLOSE_BASKET' 'APPROVE_BASKET' 'REOPEN_BASKET' 'CANCEL_ORDER' 'CREATE_ORDER' 'MODIFY_ORDER' 'CREATE_INVOICE_ADJUSTMENT' 'UPDATE_INVOICE_ADJUSTMENT' 'DELETE_INVOICE_ADJUSTMENT' 'RECEIVE_ORDER' 'MODIFY_BUDGET' 'MODIFY_FUND' 'CREATE_FUND' 'DELETE_FUND' 'ACQUISITION CLAIM' 'ACQUISITION ORDER' 'OVERDUE' 'EXPIRE' 'CREATE_RESTRICTION' 'MODIFY_RESTRICTION' 'DELETE_RESTRICTION' ] %]
150
                        [% FOREACH actx IN [ 'ADD' 'DELETE' 'MODIFY' 'ISSUE' 'RETURN' 'RENEW' 'CREATE' 'CANCEL' 'FILL' 'SUSPEND' 'RESUME' 'ADDCIRCMESSAGE' 'MODCIRCMESSAGE' 'DELCIRCMESSAGE' 'STATUS_CHANGE' 'PATRON_NOTICE' 'CHANGE PASS' 'RESET PASS' 'Run' 'End' 'EDIT_MAPPINGS' 'RESET_MAPPINGS' 'ADD_BASKET' 'MODIFY_BASKET' 'MODIFY_BASKET_HEADER' 'MODIFY_BASKET_USERS' 'CLOSE_BASKET' 'APPROVE_BASKET' 'REOPEN_BASKET' 'CANCEL_ORDER' 'CREATE_ORDER' 'MODIFY_ORDER' 'CREATE_INVOICE_ADJUSTMENT' 'UPDATE_INVOICE_ADJUSTMENT' 'DELETE_INVOICE_ADJUSTMENT' 'RECEIVE_ORDER' 'MODIFY_BUDGET' 'MODIFY_FUND' 'CREATE_FUND' 'DELETE_FUND' 'ACQUISITION CLAIM' 'ACQUISITION ORDER' 'OVERDUE' 'EXPIRE' 'CREATE_RESTRICTION' 'MODIFY_RESTRICTION' 'DELETE_RESTRICTION' 'MODIFY_CARDNUMBER' ] %]
151
                            [% IF actions.grep(actx).size %]
151
                            [% IF actions.grep(actx).size %]
152
                                <label for="action[% actx| replace('\s+', '_') | html %]" class="viewlog"
152
                                <label for="action[% actx| replace('\s+', '_') | html %]" class="viewlog"
153
                                    ><input type="checkbox" id="action[% actx | replace('\s+', '_') | html %]" name="actions" value="[% actx | html %]" checked="checked" /> [% PROCESS translate_log_action action=actx %]</label
153
                                    ><input type="checkbox" id="action[% actx | replace('\s+', '_') | html %]" name="actions" value="[% actx | html %]" checked="checked" /> [% PROCESS translate_log_action action=actx %]</label
(-)a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-detail.tt (-1 / +1 lines)
Lines 1514-1520 Link Here
1514
                        <td class="barcode" property="serialNumber">[% ITEM_RESULT.barcode | html %]</td>
1514
                        <td class="barcode" property="serialNumber">[% ITEM_RESULT.barcode | html %]</td>
1515
                    [% END %]
1515
                    [% END %]
1516
1516
1517
                    [% IF item_level_holds > 0 %]
1517
                    [% IF item_level_holds > 0 || show_priority %]
1518
                        <td class="holds_count">
1518
                        <td class="holds_count">
1519
                            [% IF holds_count.defined %][% ITEM_RESULT.holds_count | html %][% END %]
1519
                            [% IF holds_count.defined %][% ITEM_RESULT.holds_count | html %][% END %]
1520
                            [% IF ITEM_RESULT.priority %]
1520
                            [% IF ITEM_RESULT.priority %]
(-)a/t/db_dependent/Koha/Patrons.t (-5 / +52 lines)
Lines 2019-2028 $nb_of_patrons = Koha::Patrons->search->count; Link Here
2019
$retrieved_patron_1->delete;
2019
$retrieved_patron_1->delete;
2020
is( Koha::Patrons->search->count, $nb_of_patrons - 1, 'Delete should have deleted the patron' );
2020
is( Koha::Patrons->search->count, $nb_of_patrons - 1, 'Delete should have deleted the patron' );
2021
2021
2022
subtest 'BorrowersLog tests' => sub {
2022
subtest 'BorrowersLog and CardnumberLog tests' => sub {
2023
    plan tests => 5;
2023
    plan tests => 13;
2024
2024
2025
    t::lib::Mocks::mock_preference( 'BorrowersLog', 1 );
2025
    t::lib::Mocks::mock_preference( 'BorrowersLog',  1 );
2026
    t::lib::Mocks::mock_preference( 'CardnumberLog', 0 );
2026
    my $patron = $builder->build_object( { class => 'Koha::Patrons' } );
2027
    my $patron = $builder->build_object( { class => 'Koha::Patrons' } );
2027
2028
2028
    my $cardnumber = $patron->cardnumber;
2029
    my $cardnumber = $patron->cardnumber;
Lines 2042-2048 subtest 'BorrowersLog tests' => sub { Link Here
2042
        ->search( { module => 'MEMBERS', action => 'MODIFY', object => $patron->borrowernumber } );
2043
        ->search( { module => 'MEMBERS', action => 'MODIFY', object => $patron->borrowernumber } );
2043
    is( scalar @logs, 1, 'With BorrowerLogs and TrackLastPatronActivityTriggers we should not spam the logs' );
2044
    is( scalar @logs, 1, 'With BorrowerLogs and TrackLastPatronActivityTriggers we should not spam the logs' );
2044
2045
2045
    Koha::ActionLogs->search()->delete();
2046
    # Clear the logs for this patron
2047
    Koha::ActionLogs->search( { object => $patron->borrowernumber } )->delete();
2046
    $patron->get_from_storage();
2048
    $patron->get_from_storage();
2047
    $patron->set( { debarred => "" } );
2049
    $patron->set( { debarred => "" } );
2048
    $patron->store;
2050
    $patron->store;
Lines 2057-2062 subtest 'BorrowersLog tests' => sub { Link Here
2057
        defined $log,
2059
        defined $log,
2058
        "No action log generated where incoming changed column is empty string and value in storage is NULL"
2060
        "No action log generated where incoming changed column is empty string and value in storage is NULL"
2059
    );
2061
    );
2062
2063
    t::lib::Mocks::mock_preference( 'CardnumberLog', 1 );
2064
    $patron->set( { cardnumber => 'TESTCARDNUMBER_1' } )->store;
2065
    @logs = $schema->resultset('ActionLog')
2066
        ->search( { module => 'MEMBERS', action => 'MODIFY', object => $patron->borrowernumber } );
2067
    is( scalar @logs, 1, 'With BorrowersLog, one detailed MODIFY action should be logged for the modification.' );
2068
    @logs = $schema->resultset('ActionLog')
2069
        ->search( { module => 'MEMBERS', action => 'MODIFY_CARDNUMBER', object => $patron->borrowernumber } );
2070
    is(
2071
        scalar @logs, 1,
2072
        'With CardnumberLog, one detailed MODIFY_CARDNUMBER action should be logged for the modification.'
2073
    );
2074
2075
    t::lib::Mocks::mock_preference( 'BorrowersLog', 0 );
2076
    $patron->set( { cardnumber => 'TESTCARDNUMBER' } )->store;
2077
    @logs = $schema->resultset('ActionLog')
2078
        ->search( { module => 'MEMBERS', action => 'MODIFY', object => $patron->borrowernumber } );
2079
    is(
2080
        scalar @logs, 1,
2081
        'With Cardnumberlog and not BorrowersLog, no more detailed MODIFY action should be logged for the modification.'
2082
    );
2083
    @logs = $schema->resultset('ActionLog')
2084
        ->search( { module => 'MEMBERS', action => 'MODIFY_CARDNUMBER', object => $patron->borrowernumber } );
2085
    is(
2086
        scalar @logs, 2,
2087
        'With CardnumberLogs, one more detailed MODIFY_CARDNUMBER action should be logged for the modification.'
2088
    );
2089
    $log_info = from_json( $logs[1]->info );
2090
    is( $log_info->{after},  'TESTCARDNUMBER',   'Got correct new cardnumber' );
2091
    is( $log_info->{before}, 'TESTCARDNUMBER_1', 'Got correct old cardnumber' );
2092
2093
    t::lib::Mocks::mock_preference( 'CardnumberLog', 0 );
2094
    $patron->set( { cardnumber => 'TESTCARDNUMBER_1' } )->store;
2095
    @logs = $schema->resultset('ActionLog')
2096
        ->search( { module => 'MEMBERS', action => 'MODIFY', object => $patron->borrowernumber } );
2097
    is(
2098
        scalar @logs, 1,
2099
        'With neither Cardnumberlog nor BorrowersLog, no more detailed MODIFY action should be logged for the modification.'
2100
    );
2101
    @logs = $schema->resultset('ActionLog')
2102
        ->search( { module => 'MEMBERS', action => 'MODIFY_CARDNUMBER', object => $patron->borrowernumber } );
2103
    is(
2104
        scalar @logs, 2,
2105
        'With neither CardnumberLog nor BorrowersLog, one detailed MODIFY_CARDNUMBER action should be logged for the modification.'
2106
    );
2107
2060
};
2108
};
2061
$schema->storage->txn_rollback;
2109
$schema->storage->txn_rollback;
2062
2110
2063
- 

Return to bug 39452