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

(-)a/installer/data/mysql/atomicupdate/bug_36135.pl (-4 / +6 lines)
Lines 1-13 Link Here
1
use Modern::Perl;
1
use Modern::Perl;
2
2
3
return {
3
return {
4
    bug_number => "36135",
4
    bug_number  => "36135",
5
    description => "Add new permission batch_modify_holds",
5
    description => "Add new permission batch_modify_holds",
6
    up => sub {
6
    up          => sub {
7
        my ($args) = @_;
7
        my ($args) = @_;
8
        my ($dbh, $out) = @$args{qw(dbh out)};
8
        my ( $dbh, $out ) = @$args{qw(dbh out)};
9
9
10
        $dbh->do(q{INSERT IGNORE permissions (module_bit, code, description) VALUES (13, 'batch_modify_holds', 'Perform batch modification of holds')});
10
        $dbh->do(
11
            q{INSERT IGNORE permissions (module_bit, code, description) VALUES (13, 'batch_modify_holds', 'Perform batch modification of holds')}
12
        );
11
13
12
        say $out "Added new permission 'batch_modify_holds'";
14
        say $out "Added new permission 'batch_modify_holds'";
13
    },
15
    },
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/batch_modify_holds.tt (-61 / +65 lines)
Lines 48-62 Link Here
48
                                <span class="hint">NOTE! Column patron_expiration_date is used as a main filter for expiration date field. Otherwise column expirationdate is used.</span>
48
                                <span class="hint">NOTE! Column patron_expiration_date is used as a main filter for expiration date field. Otherwise column expirationdate is used.</span>
49
                                <ol>
49
                                <ol>
50
                                    <li>
50
                                    <li>
51
                                        <label for="suspend_until">Expiration date:</label>
51
                                        <label for="expirationdate_from">Expiration date from:</label>
52
                                        <li>
52
                                        <input type="text" size="10" id="expirationdate_from" name="expirationdate_from" class="flatpickr" data-date_to="to" />
53
                                            <label for="expirationdate_from">From</label>
53
                                    </li>
54
                                            <input type="text" size="10" id="from" name="expirationdate_from" class="flatpickr" data-date_to="to" />
54
                                    <li>
55
                                        </li>
55
                                        <label for="expirationdate_to">Expiration date to:</label>
56
                                        <li>
56
                                        <input type="text" size="10" id="expirationdate_to" name="expirationdate_to" class="flatpickr"/>
57
                                            <label for="expirationdate_to">To</label>
58
                                            <input type="text" size="10" id="to" name="expirationdate_to" class="flatpickr"/>
59
                                        </li>
60
                                    </li>
57
                                    </li>
61
                                    <li>
58
                                    <li>
62
                                        <label for="branchcodes">Libraries:</label>
59
                                        <label for="branchcodes">Libraries:</label>
Lines 82-96 Link Here
82
                                        </select>
79
                                        </select>
83
                                    </li>
80
                                    </li>
84
                                    <li>
81
                                    <li>
85
                                        <label for="suspend_until">Suspended until:</label>
82
                                        <label for="suspend_until_from">Suspended until from:</label>
86
                                        <li>
83
                                        <input type="text" size="10" id="suspend_until_from" name="suspend_until_from" class="flatpickr" data-date_to="to" />
87
                                            <label for="suspend_until_from">From</label>
84
                                    </li>
88
                                            <input type="text" size="10" id="from" name="suspend_until_from" class="flatpickr" data-date_to="to" />
85
                                    <li>
89
                                        </li>
86
                                        <label for="suspend_until_to">Suspended until to:</label>
90
                                        <li>
87
                                        <input type="text" size="10" id="suspend_until_to" name="suspend_until_to" class="flatpickr"/>
91
                                            <label for="suspend_until_to">To</label>
92
                                            <input type="text" size="10" id="to" name="suspend_until_to" class="flatpickr"/>
93
                                        </li>
94
                                    </li>
88
                                    </li>
95
                                    <li>
89
                                    <li>
96
                                        <label for="reservenotes">Hold note:</label>
90
                                        <label for="reservenotes">Hold note:</label>
Lines 108-114 Link Here
108
                        <form action="/cgi-bin/koha/tools/batch_modify_holds.pl" method="post" id="process">
102
                        <form action="/cgi-bin/koha/tools/batch_modify_holds.pl" method="post" id="process">
109
                            [% INCLUDE 'csrf-token.inc' %]
103
                            [% INCLUDE 'csrf-token.inc' %]
110
                        [% IF holds.count %]
104
                        [% IF holds.count %]
111
                            <div><p>Found [% holds.count | html %][% IF holds.count > 1 %] holds [% ELSE %] hold [% END %]to modify.</p><div>
105
                            <div><p>Found [% holds.count | html %][% IF holds.count > 1 %] holds [% ELSE %] hold [% END %]to modify.</p></div>
112
                            <div class="page-section">
106
                            <div class="page-section">
113
                                <div class="btn-toolbar selections-toolbar">
107
                                <div class="btn-toolbar selections-toolbar">
114
                                    <a id="selectall" href="#"><i class="fa fa-check"></i> Select all</a>
108
                                    <a id="selectall" href="#"><i class="fa fa-check"></i> Select all</a>
Lines 120-126 Link Here
120
                                            <th>&nbsp;</th>
114
                                            <th>&nbsp;</th>
121
                                            <th>Expiration date</th>
115
                                            <th>Expiration date</th>
122
                                            <th>Patron expiration date</th>
116
                                            <th>Patron expiration date</th>
123
                                            <th>Title</title>
117
                                            <th>Title</th>
124
                                            <th>Barcode</th>
118
                                            <th>Barcode</th>
125
                                            <th>Status</th>
119
                                            <th>Status</th>
126
                                            <th>Hold pickup library</th>
120
                                            <th>Hold pickup library</th>
Lines 131-141 Link Here
131
                                    </thead>
125
                                    </thead>
132
                                    <tbody>
126
                                    <tbody>
133
                                        [% FOREACH hold IN holds %]
127
                                        [% FOREACH hold IN holds %]
134
                                            <tr [% IF hold.found %]class="highlighted-row"[% END %]>
128
                                            [% IF hold.found %]
129
                                                <tr class="highlighted-row">
130
                                            [% ELSE %]
131
                                                <tr>
132
                                            [% END %]
135
                                                <td><input type="checkbox" name="hold_id" value="[% hold.reserve_id | html %]"/></td>
133
                                                <td><input type="checkbox" name="hold_id" value="[% hold.reserve_id | html %]"/></td>
136
                                                <td>[% hold.expirationdate | $KohaDates %]</td>
134
                                                <td>[% hold.expirationdate | $KohaDates %]</td>
137
                                                <td>[% hold.patron_expiration_date | $KohaDates %]</td>
135
                                                <td>[% hold.patron_expiration_date | $KohaDates %]</td>
138
                                                <td><a href="/cgi-bin/koha/catalogue/detail.pl?biblionumber=[% hold.item.biblio.biblionumber | uri %]">[% hold.item.biblio.title | html %]</a></td>
136
                                                <td><a href="/cgi-bin/koha/catalogue/detail.pl?biblionumber=[% hold.item.biblio.biblionumber | uri %]">[% hold.biblio.title | html %]</a></td>
139
                                                <td><a href="/cgi-bin/koha/catalogue/moredetail.pl?itemnumber=[% hold.itemnumber | uri %]&biblionumber=[% hold.item.biblio.biblionumber | uri %]&bi=[% hold.item.biblio.biblionumber | uri %]#item[% hold.itemnumber | uri %]">[% hold.item.barcode | html %]</a></td>
137
                                                <td><a href="/cgi-bin/koha/catalogue/moredetail.pl?itemnumber=[% hold.itemnumber | uri %]&biblionumber=[% hold.item.biblio.biblionumber | uri %]&bi=[% hold.item.biblio.biblionumber | uri %]#item[% hold.itemnumber | uri %]">[% hold.item.barcode | html %]</a></td>
140
                                                <td class="found_status" data-found="[% hold.found | html %]">
138
                                                <td class="found_status" data-found="[% hold.found | html %]">
141
                                                    [% IF hold.found == "T" %]
139
                                                    [% IF hold.found == "T" %]
Lines 158-200 Link Here
158
                                </table> <!-- /#holds -->
156
                                </table> <!-- /#holds -->
159
                            </div> <!-- /.page-section -->
157
                            </div> <!-- /.page-section -->
160
                            <h2>Modify holds</h2>
158
                            <h2>Modify holds</h2>
161
                            <table id="hold_modifies">
159
                            <div class="page-section">
162
                                <thead>
160
                                <table id="hold_modifies">
163
                                    <tr>
161
                                    <thead>
164
                                        <th>New expiration date</th>
162
                                        <tr>
165
                                        <th>New pickup library</th>
163
                                            <th>New expiration date</th>
166
                                        <th>Suspend holds</th>
164
                                            <th>New pickup library</th>
167
                                        <th>Suspend until</th>
165
                                            <th>Suspend holds</th>
168
                                        <th>New reserve note</th>
166
                                            <th>Suspend until</th>
169
                                    </tr>
167
                                            <th>New reserve note</th>
170
                                </thead>
168
                                        </tr>
171
                                <tbody>
169
                                    </thead>
172
                                    <tr>
170
                                    <tbody>
173
                                        <td>
171
                                        <tr>
174
                                            <input type="text" id="new_expiration_date" name="new_expiration_date" class="flatpickr" data-flatpickr-futuredate="true"/>
172
                                            <td>
175
                                        </td>
173
                                                <input type="text" id="new_expiration_date" name="new_expiration_date" class="flatpickr" data-flatpickr-futuredate="true"/>
176
                                        <td>
174
                                            </td>
177
                                            <select id="new_pickup_loc" name="new_pickup_loc">
175
                                            <td>
178
                                                <option value="" selected="selected"></option>
176
                                                <select id="new_pickup_loc" name="new_pickup_loc">
179
                                                [% PROCESS options_for_libraries libraries => Branches.pickup_locations(selected = "") %]
177
                                                    <option value="" selected="selected"></option>
180
                                            </select>
178
                                                    [% PROCESS options_for_libraries libraries => Branches.pickup_locations(selected = "") %]
181
                                        </td>
179
                                                </select>
182
                                        <td>
180
                                            </td>
183
                                            <select id="new_suspend_status" name="new_suspend_status">
181
                                            <td>
184
                                                <option value="" selected="selected"></option>
182
                                                <select id="new_suspend_status" name="new_suspend_status">
185
                                                <option value="not_suspended">Not suspended</option>
183
                                                    <option value="" selected="selected"></option>
186
                                                <option value="suspend">Suspend</option>
184
                                                    <option value="not_suspended">Not suspended</option>
187
                                            </select>
185
                                                    <option value="suspend">Suspend</option>
188
                                        </td>
186
                                                </select>
189
                                        <td>
187
                                            </td>
190
                                            <input type="text" id="new_suspend_date" name="new_suspend_date" class="flatpickr" data-flatpickr-futuredate="true"/>
188
                                            <td>
191
                                        </td>
189
                                                <input type="text" id="new_suspend_date" name="new_suspend_date" class="flatpickr" data-flatpickr-futuredate="true"/>
192
                                        <td>
190
                                            </td>
193
                                           <input type="text" id="new_reserve_note" name="new_reserve_note"/>
191
                                            <td>
194
                                        </td>
192
                                               <input type="text" id="new_reserve_note" name="new_reserve_note"/>
195
                                    </tr>
193
                                            </td>
196
                                </tbody>
194
                                        </tr>
197
                            </table> <!-- /#hold_modifies -->
195
                                    </tbody>
196
                                </table> <!-- /#hold_modifies -->
197
                            </div>
198
                            <fieldset class="action">
198
                            <fieldset class="action">
199
                                <input type="hidden" name="op" value="cud-modify"/>
199
                                <input type="hidden" name="op" value="cud-modify"/>
200
                                <input type="submit" class="btn btn-primary" value="Modify selected holds"/>
200
                                <input type="submit" class="btn btn-primary" value="Modify selected holds"/>
Lines 209-221 Link Here
209
                        [% END %]
209
                        [% END %]
210
                    [% ELSIF view == 'report' %]
210
                    [% ELSIF view == 'report' %]
211
                        <div class="dialog message">
211
                        <div class="dialog message">
212
                            Holds have been modified!
212
                            [% updated_holds.count | html %] holds have been modified!
213
                        </div>
213
                        </div>
214
                        <div class="page-section">
214
                        <div class="page-section">
215
                            <table id="holds">
215
                            <table id="holds">
216
                                <thead>
216
                                <thead>
217
                                    <tr>
217
                                    <tr>
218
                                        <th>Expiration date</th>
218
                                        <th>Expiration date</th>
219
                                        <th>Title</th>
220
                                        <th>Barcode</th>
219
                                        <th>Hold pickup library</th>
221
                                        <th>Hold pickup library</th>
220
                                        <th>Suspended</th>
222
                                        <th>Suspended</th>
221
                                        <th>Suspended until</th>
223
                                        <th>Suspended until</th>
Lines 226-231 Link Here
226
                                    [% FOREACH hold IN updated_holds %]
228
                                    [% FOREACH hold IN updated_holds %]
227
                                        <tr>
229
                                        <tr>
228
                                            <td>[% hold.expirationdate | $KohaDates %]</td>
230
                                            <td>[% hold.expirationdate | $KohaDates %]</td>
231
                                            <td><a href="/cgi-bin/koha/catalogue/detail.pl?biblionumber=[% hold.item.biblio.biblionumber | uri %]">[% hold.biblio.title | html %]</a></td>
232
                                            <td><a href="/cgi-bin/koha/catalogue/moredetail.pl?itemnumber=[% hold.itemnumber | uri %]&biblionumber=[% hold.item.biblio.biblionumber | uri %]&bi=[% hold.item.biblio.biblionumber | uri %]#item[% hold.itemnumber | uri %]">[% hold.item.barcode | html %]</a></td>
229
                                            <td>[% Branches.GetName( hold.branchcode ) | html %]</td>
233
                                            <td>[% Branches.GetName( hold.branchcode ) | html %]</td>
230
                                            <td>[% IF hold.suspend == 0 %]No[% ELSE %]Yes[% END %]</td>
234
                                            <td>[% IF hold.suspend == 0 %]No[% ELSE %]Yes[% END %]</td>
231
                                            <td>[% hold.suspend_until | $KohaDates %]</td>
235
                                            <td>[% hold.suspend_until | $KohaDates %]</td>
Lines 309-315 Link Here
309
                }
313
                }
310
                if( ( !new_suspend_status || new_suspend_status == "not_suspended") && new_suspend_date ){
314
                if( ( !new_suspend_status || new_suspend_status == "not_suspended") && new_suspend_date ){
311
                    e.preventDefault();
315
                    e.preventDefault();
312
                    alert(_('You have to suspend holds if new suspend until date is set.'));
316
                    alert(_("You have to suspend holds if new suspend until date is set."));
313
                    return false;
317
                    return false;
314
                }
318
                }
315
319
(-)a/tools/batch_modify_holds.pl (-43 / +43 lines)
Lines 29-42 use Koha::DateUtils qw( dt_from_string ); Link Here
29
use Koha::Holds;
29
use Koha::Holds;
30
30
31
my $input = CGI->new;
31
my $input = CGI->new;
32
my $op = $input->param('op') // q|form|;
32
my $op    = $input->param('op') // q|form|;
33
33
34
my ( $template, $loggedinuser, $cookie ) = get_template_and_user(
34
my ( $template, $loggedinuser, $cookie ) = get_template_and_user(
35
    {
35
    {
36
        template_name   => 'tools/batch_modify_holds.tt',
36
        template_name => 'tools/batch_modify_holds.tt',
37
        query           => $input,
37
        query         => $input,
38
        type            => "intranet",
38
        type          => "intranet",
39
        flagsrequired   => { tools => 'batch_modify_holds.tt' },
39
        flagsrequired => { tools => 'batch_modify_holds.tt' },
40
    }
40
    }
41
);
41
);
42
42
Lines 44-51 my @hold_ids; Link Here
44
44
45
if ( $op eq 'form' ) {
45
if ( $op eq 'form' ) {
46
    $template->param( view => 'form', );
46
    $template->param( view => 'form', );
47
}
47
} elsif ( $op eq 'list' ) {
48
elsif ( $op eq 'list' ) {
49
48
50
    my @reserve_ids         = $input->multi_param('reserve_ids');
49
    my @reserve_ids         = $input->multi_param('reserve_ids');
51
    my $expirationdate_from = $input->param('expirationdate_from');
50
    my $expirationdate_from = $input->param('expirationdate_from');
Lines 59-94 elsif ( $op eq 'list' ) { Link Here
59
58
60
    my $search_params;
59
    my $search_params;
61
60
62
    if( @reserve_ids ){
61
    if (@reserve_ids) {
63
        $search_params->{'me.reserve_id'} = { -in => \@reserve_ids };
62
        $search_params->{'me.reserve_id'} = { -in => \@reserve_ids };
64
    } else {
63
    } else {
65
        if( $expirationdate_from && $expirationdate_to ){
64
        if ( $expirationdate_from && $expirationdate_to ) {
66
            my $expirationdate_params = { -or => {
65
            my $expirationdate_params = {
67
                patron_expiration_date => {
66
                -or => {
68
                    -between => [
67
                    patron_expiration_date => {
69
                        $expirationdate_from,
68
                        -between => [
70
                        $expirationdate_to
69
                            $expirationdate_from,
71
                    ]
70
                            $expirationdate_to
72
                },
71
                        ]
73
                expirationdate => {
72
                    },
74
                    -between => [
73
                    expirationdate => {
75
                        $expirationdate_from,
74
                        -between => [
76
                        $expirationdate_to
75
                            $expirationdate_from,
77
                    ]
76
                            $expirationdate_to
77
                        ]
78
                    }
78
                }
79
                }
79
            }};
80
            };
80
81
81
            $search_params = $expirationdate_params;
82
            $search_params = $expirationdate_params;
82
        }
83
        }
83
84
84
        if ( @branchcodes ) {
85
        if (@branchcodes) {
85
            $search_params->{'me.branchcode'} = { -in => \@branchcodes };
86
            $search_params->{'me.branchcode'} = { -in => \@branchcodes };
86
        }
87
        }
87
88
88
        if ( @found_status ) {
89
        if (@found_status) {
89
            my $found_params = {};
90
            my $found_params = {};
91
90
            # if NULL is used as filter, use it as "is" param
92
            # if NULL is used as filter, use it as "is" param
91
            if( grep {$_ eq "NULL"} @found_status ) {
93
            if ( grep { $_ eq "NULL" } @found_status ) {
92
                $found_params->{'-or'}{'-is'} = undef;
94
                $found_params->{'-or'}{'-is'} = undef;
93
                $found_params->{'-or'}{'-in'} = \@found_status;
95
                $found_params->{'-or'}{'-in'} = \@found_status;
94
            } else {
96
            } else {
Lines 98-108 elsif ( $op eq 'list' ) { Link Here
98
            $search_params->{'me.found'} = $found_params;
100
            $search_params->{'me.found'} = $found_params;
99
        }
101
        }
100
102
101
        if( $suspend_status ne "none" ){
103
        if ( $suspend_status ne "none" ) {
102
            $search_params->{'me.suspend'} = $suspend_status;
104
            $search_params->{'me.suspend'} = $suspend_status;
103
        }
105
        }
104
106
105
        if( $suspend_until_from && $suspend_until_to ){
107
        if ( $suspend_until_from && $suspend_until_to ) {
106
            $search_params->{'me.suspend_until'} = {
108
            $search_params->{'me.suspend_until'} = {
107
                -between => [
109
                -between => [
108
                    $suspend_until_from,
110
                    $suspend_until_from,
Lines 111-126 elsif ( $op eq 'list' ) { Link Here
111
            };
113
            };
112
        }
114
        }
113
115
114
        if( $reservenotes ){
116
        if ($reservenotes) {
115
            $search_params->{'me.reservenotes'} = { -like => "%".$reservenotes."%" }
117
            $search_params->{'me.reservenotes'} = { -like => "%" . $reservenotes . "%" };
116
        }
118
        }
117
    }
119
    }
118
120
119
    my $holds = Koha::Holds->search(
121
    my $holds = Koha::Holds->search(
120
        $search_params,
122
        $search_params,
121
        {
123
        { join => [ "item", "biblio" ] }
122
            join => ["item"]
123
        }
124
    );
124
    );
125
125
126
    $template->param(
126
    $template->param(
Lines 139-171 if ( $op eq 'cud-modify' ) { Link Here
139
139
140
    @hold_ids = $input->multi_param('hold_id');
140
    @hold_ids = $input->multi_param('hold_id');
141
141
142
    my $holds_to_update = Koha::Holds->search( { reserve_id => { -in => \@hold_ids } } );
142
    my $holds_to_update =
143
        Koha::Holds->search( { reserve_id => { -in => \@hold_ids } }, { join => [ "item", "biblio" ] } );
143
144
144
    while ( my $hold = $holds_to_update->next ) {
145
    while ( my $hold = $holds_to_update->next ) {
145
146
146
        if( $new_expiration_date ){
147
        if ($new_expiration_date) {
147
            $hold->expirationdate($new_expiration_date)->store;
148
            $hold->expirationdate($new_expiration_date)->store;
148
        }
149
        }
149
150
150
        if($new_pickup_loc && ($hold->branchcode ne $new_pickup_loc)){
151
        if ( $new_pickup_loc && ( $hold->branchcode ne $new_pickup_loc ) ) {
151
            $hold->branchcode($new_pickup_loc)->store;
152
            $hold->branchcode($new_pickup_loc)->store;
152
        }
153
        }
153
154
154
        if( $new_suspend_status && !$hold->is_found ){
155
        if ( $new_suspend_status && !$hold->is_found ) {
155
            if( $new_suspend_status eq "suspend" ){
156
            if ( $new_suspend_status eq "suspend" ) {
156
                $hold->suspend(1)->store;
157
                $hold->suspend(1)->store;
157
                if( $new_suspend_date ){
158
                if ($new_suspend_date) {
158
                    $hold->suspend_until( $new_suspend_date )->store;
159
                    $hold->suspend_until($new_suspend_date)->store;
159
                } else {
160
                } else {
160
                    $hold->suspend_until( undef )->store;
161
                    $hold->suspend_until(undef)->store;
161
                }
162
                }
162
            } else {
163
            } else {
163
                $hold->suspend(0)->store;
164
                $hold->suspend(0)->store;
164
                $hold->suspend_until( undef )->store;
165
                $hold->suspend_until(undef)->store;
165
            }
166
            }
166
        }
167
        }
167
168
168
        if( $new_reserve_note ){
169
        if ($new_reserve_note) {
169
            $hold->reservenotes($new_reserve_note)->store;
170
            $hold->reservenotes($new_reserve_note)->store;
170
        }
171
        }
171
    }
172
    }
172
- 

Return to bug 36135