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

(-)a/Koha/REST/V1/Patrons/Holds.pm (+174 lines)
Line 0 Link Here
1
package Koha::REST::V1::Patrons::Holds;
2
3
# This file is part of Koha.
4
#
5
# Koha is free software; you can redistribute it and/or modify it under the
6
# terms of the GNU General Public License as published by the Free Software
7
# Foundation; either version 3 of the License, or (at your option) any later
8
# version.
9
#
10
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
11
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
12
# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
13
#
14
# You should have received a copy of the GNU General Public License along
15
# with Koha; if not, write to the Free Software Foundation, Inc.,
16
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17
18
use Modern::Perl;
19
20
use Mojo::Base 'Mojolicious::Controller';
21
22
use Koha::Patrons;
23
24
use Scalar::Util qw(blessed);
25
use Koha::DateUtils;
26
use Try::Tiny;
27
28
=head1 NAME
29
30
Koha::REST::V1::Patrons::Holds
31
32
=head1 API
33
34
=head2 Methods
35
36
=head3 list
37
38
Mehtod that handles listing patron's holds
39
40
=cut
41
42
sub list {
43
    my $c = shift->openapi->valid_input or return;
44
    my $patron_id = $c->validation->param('patron_id');
45
    my $old = $c->validation->param('old');
46
    my $patron    = Koha::Patrons->find($patron_id);
47
48
    unless ($patron) {
49
        return $c->render( status => 404, openapi => { error => "Patron not found." } );
50
    }
51
52
    return try {
53
        my $holds_set;
54
        if($old) {
55
            $holds_set = Koha::Old::Holds->new;
56
        } else {
57
            $holds_set = Koha::Holds->new;
58
        }
59
60
        delete $c->validation->output->{old};
61
        #$c->stash_embed( {spec => $c->match->endpoint->pattern->defaults->{'openapi.op_spec'}} );
62
        my $holds     = $c->objects->search( $holds_set );
63
        return $c->render( status => 200, openapi => $holds );
64
    }
65
    catch {
66
        warn $_;
67
use Data::Printer colored=>1;
68
p($_);
69
        warn $_->{trace};
70
        if ( blessed $_ && $_->isa('Koha::Exceptions') ) {
71
            return $c->render(
72
                status  => 500,
73
                openapi => { error => "$_" }
74
            );
75
        }
76
        else {
77
            return $c->render(
78
                status  => 500,
79
                openapi => { error => "Something went wrong, check Koha logs for details." }
80
            );
81
        }
82
    };
83
}
84
85
=head2 Internal methods
86
87
=head3 _to_model
88
89
Helper function that maps REST api objects into Koha::Hold
90
attribute names.
91
92
=cut
93
94
sub _to_model {
95
    my $hold = shift;
96
use Data::Printer colored=>1;
97
p($hold);
98
    foreach my $attribute ( keys %{ $Koha::REST::V1::Patrons::Holds::to_model_mapping } ) {
99
        my $mapped_attribute = $Koha::REST::V1::Patrons::Holds::to_model_mapping->{$attribute};
100
        if (    exists $hold->{ $attribute }
101
             && defined $mapped_attribute )
102
        {
103
            # key => !undef
104
            $hold->{ $mapped_attribute } = delete $hold->{ $attribute };
105
        }
106
        elsif (    exists $hold->{ $attribute }
107
                && !defined $mapped_attribute )
108
        {
109
            # key => undef / to be deleted
110
            delete $hold->{ $attribute };
111
        }
112
    }
113
114
    if ( exists $hold->{lowestPriority} ) {
115
        $hold->{lowestPriority} = ($hold->{lowestPriority}) ? 1 : 0;
116
    }
117
118
    if ( exists $hold->{suspend} ) {
119
        $hold->{suspend} = ($hold->{suspend}) ? 1 : 0;
120
    }
121
122
    if ( exists $hold->{reservedate} && $hold->{reservedate} != 1 ) {
123
        $hold->{reservedate} = output_pref({ str => $hold->{reservedate}, dateformat => 'sql' });
124
    }
125
126
    if ( exists $hold->{cancellationdate} && $hold->{cancellationdate} != 1 ) {
127
        $hold->{cancellationdate} = output_pref({ str => $hold->{cancellationdate}, dateformat => 'sql' });
128
    }
129
130
    if ( exists $hold->{timestamp} && $hold->{timestamp} != 1 ) {
131
        $hold->{timestamp} = output_pref({ str => $hold->{timestamp}, dateformat => 'sql' });
132
    }
133
134
    if ( exists $hold->{waitingdate} && $hold->{waitingdate} != 1 ) {
135
        $hold->{waitingdate} = output_pref({ str => $hold->{waitingdate}, dateformat => 'sql' });
136
    }
137
138
    if ( exists $hold->{expirationdate} && $hold->{expirationdate} != 1 ) {
139
        $hold->{expirationdate} = output_pref({ str => $hold->{expirationdate}, dateformat => 'sql' });
140
    }
141
142
    if ( exists $hold->{suspend_until} && $hold->{suspend_until} != 1 ) {
143
        $hold->{suspend_until} = output_pref({ str => $hold->{suspend_until}, dateformat => 'sql' });
144
    }
145
146
    return $hold;
147
}
148
149
=head2 Global variables
150
151
=head3 $to_model_mapping
152
153
=cut
154
155
our $to_model_mapping = {
156
    hold_id           => 'reserve_id',
157
    patron_id         => 'borrowernumber',
158
    hold_date         => 'reservedate',
159
    biblio_id         => 'biblionumber',
160
    pickup_library_id => 'branchcode',
161
    cancelation_date  => 'cancellationdate',
162
    notes             => 'reservenotes',
163
    status            => 'found',
164
    item_id           => 'itemnumber',
165
    waiting_date      => 'waitingdate',
166
    expiration_date   => 'expirationdate',
167
    lowest_priority   => 'lowestPriority',
168
    suspended         => 'suspend',
169
    suspended_until   => 'suspend_until',
170
    item_type         => 'itemtype',
171
    item_level        => 'item_level_hold',
172
};
173
174
1;
(-)a/Koha/Schema/Result/Biblio.pm (+20 lines)
Lines 428-431 __PACKAGE__->add_columns( Link Here
428
    "+serial" => { is_boolean => 1 }
428
    "+serial" => { is_boolean => 1 }
429
);
429
);
430
430
431
=head2 koha_objects_class
432
433
Returns related Koha::Objects class name
434
435
=cut
436
437
sub koha_objects_class {
438
    'Koha::Biblios';
439
}
440
441
=head2 koha_object_class
442
443
Returns related Koha::Object class name
444
445
=cut
446
447
sub koha_object_class {
448
    'Koha::Biblio';
449
}
450
431
1;
451
1;
(-)a/Koha/Schema/Result/Item.pm (+27 lines)
Lines 760-765 __PACKAGE__->belongs_to( Link Here
760
);
760
);
761
761
762
use C4::Context;
762
use C4::Context;
763
764
=head2 koha_objects_class
765
766
Returns item's effective itemtype
767
768
=cut
769
763
sub effective_itemtype {
770
sub effective_itemtype {
764
    my ( $self ) = @_;
771
    my ( $self ) = @_;
765
772
Lines 773-776 sub effective_itemtype { Link Here
773
    }
780
    }
774
}
781
}
775
782
783
=head2 koha_objects_class
784
785
Returns related Koha::Objects class name
786
787
=cut
788
789
sub koha_objects_class {
790
    'Koha::Items';
791
}
792
793
=head2 koha_object_class
794
795
Returns related Koha::Object class name
796
797
=cut
798
799
sub koha_object_class {
800
    'Koha::Item';
801
}
802
776
1;
803
1;
(-)a/Koha/Schema/Result/OldReserve.pm (+43 lines)
Lines 300-305 __PACKAGE__->belongs_to( Link Here
300
# Created by DBIx::Class::Schema::Loader v0.07046 @ 2019-06-17 07:24:39
300
# Created by DBIx::Class::Schema::Loader v0.07046 @ 2019-06-17 07:24:39
301
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:ZgGAW7ODBby3hGNJ41eeMA
301
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:ZgGAW7ODBby3hGNJ41eeMA
302
302
303
__PACKAGE__->belongs_to(
304
  "item",
305
  "Koha::Schema::Result::Item",
306
  { itemnumber => "itemnumber" },
307
  {
308
    is_deferrable => 1,
309
    join_type     => "LEFT",
310
    on_delete     => "CASCADE",
311
    on_update     => "CASCADE",
312
  },
313
);
314
315
__PACKAGE__->belongs_to(
316
  "branch",
317
  "Koha::Schema::Result::Branch",
318
  { branchcode => "branchcode" },
319
  {
320
    is_deferrable => 1,
321
    join_type     => "LEFT",
322
    on_delete     => "CASCADE",
323
    on_update     => "CASCADE",
324
  },
325
);
326
327
328
__PACKAGE__->belongs_to(
329
  "biblio",
330
  "Koha::Schema::Result::Biblio",
331
  { biblionumber => "biblionumber" },
332
  {
333
    is_deferrable => 1,
334
    join_type     => "LEFT",
335
    on_delete     => "CASCADE",
336
    on_update     => "CASCADE",
337
  },
338
);
339
340
__PACKAGE__->add_columns(
341
    '+item_level_hold' => { is_boolean => 1 },
342
    '+lowestPriority'  => { is_boolean => 1 },
343
    '+suspend'         => { is_boolean => 1 }
344
);
345
303
sub koha_object_class {
346
sub koha_object_class {
304
    'Koha::Old::Hold';
347
    'Koha::Old::Hold';
305
}
348
}
(-)a/api/v1/swagger/paths.json (+3 lines)
Lines 98-103 Link Here
98
  "/public/patrons/{patron_id}/guarantors/can_see_checkouts": {
98
  "/public/patrons/{patron_id}/guarantors/can_see_checkouts": {
99
    "$ref": "paths/public_patrons.json#/~1public~1patrons~1{patron_id}~1guarantors~1can_see_checkouts"
99
    "$ref": "paths/public_patrons.json#/~1public~1patrons~1{patron_id}~1guarantors~1can_see_checkouts"
100
  },
100
  },
101
  "/public/patrons/{patron_id}/holds": {
102
    "$ref": "paths/public_patrons.json#/~1public~1patrons~1{patron_id}~1holds"
103
  },
101
  "/return_claims": {
104
  "/return_claims": {
102
    "$ref": "paths/return_claims.json#/~1return_claims"
105
    "$ref": "paths/return_claims.json#/~1return_claims"
103
  },
106
  },
(-)a/api/v1/swagger/paths/public_patrons.json (+188 lines)
Lines 236-240 Link Here
236
                "allow-owner": true
236
                "allow-owner": true
237
            }
237
            }
238
        }
238
        }
239
    },
240
    "/public/patrons/{patron_id}/holds": {
241
        "get": {
242
            "x-mojo-to": "Patrons::Holds#list",
243
            "operationId": "listPatronsOldHolds",
244
            "tags": [
245
                "patron"
246
            ],
247
            "parameters": [
248
                {
249
                    "$ref": "../parameters.json#/patron_id_pp"
250
                },
251
                {
252
                    "name": "hold_id",
253
                    "in": "query",
254
                    "description": "Internal reserve identifier",
255
                    "type": "integer"
256
                  },
257
                  {
258
                    "name": "hold_date",
259
                    "in": "query",
260
                    "description": "Hold",
261
                    "type": "string",
262
                    "format": "date"
263
                  },
264
                  {
265
                    "name": "biblio_id",
266
                    "in": "query",
267
                    "description": "Internal biblio identifier",
268
                    "type": "integer"
269
                  },
270
                  {
271
                    "name": "pickup_library_id",
272
                    "in": "query",
273
                    "description": "Internal library identifier for the pickup library",
274
                    "type": "string"
275
                  },
276
                  {
277
                    "name": "cancelation_date",
278
                    "in": "query",
279
                    "description": "The date the hold was cancelled",
280
                    "type": "string",
281
                    "format": "date"
282
                  },
283
                  {
284
                    "name": "notes",
285
                    "in": "query",
286
                    "description": "Notes related to this hold",
287
                    "type": "string"
288
                  },
289
                  {
290
                    "name": "priority",
291
                    "in": "query",
292
                    "description": "Where in the queue the patron sits",
293
                    "type": "integer"
294
                  },
295
                  {
296
                    "name": "status",
297
                    "in": "query",
298
                    "description": "Found status",
299
                    "type": "string"
300
                  },
301
                  {
302
                    "name": "timestamp",
303
                    "in": "query",
304
                    "description": "Time of latest update",
305
                    "type": "string"
306
                  },
307
                  {
308
                    "name": "item_id",
309
                    "in": "query",
310
                    "description": "Internal item identifier",
311
                    "type": "integer"
312
                  },
313
                  {
314
                    "name": "waiting_date",
315
                    "in": "query",
316
                    "description": "Date the item was marked as waiting for the patron",
317
                    "type": "string"
318
                  },
319
                  {
320
                    "name": "expiration_date",
321
                    "in": "query",
322
                    "description": "Date the hold expires",
323
                    "type": "string"
324
                  },
325
                  {
326
                    "name": "lowest_priority",
327
                    "in": "query",
328
                    "description": "Lowest priority",
329
                    "type": "boolean"
330
                  },
331
                  {
332
                    "name": "suspended",
333
                    "in": "query",
334
                    "description": "Suspended",
335
                    "type": "boolean"
336
                  },
337
                  {
338
                    "name": "suspended_until",
339
                    "in": "query",
340
                    "description": "Suspended until",
341
                    "type": "string"
342
                  },
343
                  {
344
                    "name": "old",
345
                    "in": "query",
346
                    "description": "Fetch holds history",
347
                    "type": "boolean"
348
                  },
349
                  {
350
                      "$ref": "../parameters.json#/match"
351
                  },
352
                  {
353
                      "$ref": "../parameters.json#/order_by"
354
                  },
355
                  {
356
                      "$ref": "../parameters.json#/page"
357
                  },
358
                  {
359
                      "$ref": "../parameters.json#/per_page"
360
                  },
361
                  {
362
                      "$ref": "../parameters.json#/q_param"
363
                  },
364
                  {
365
                      "$ref": "../parameters.json#/q_body"
366
                  },
367
                  {
368
                      "$ref": "../parameters.json#/q_header"
369
                  }
370
            ],
371
            "produces": [
372
                "application/json"
373
            ],
374
            "responses": {
375
                "200": {
376
                    "description": "List of holds history",
377
                    "schema": {
378
                        "$ref": "../definitions.json#/holds"
379
                    }
380
                },
381
                "400": {
382
                    "description": "Bad request",
383
                    "schema": {
384
                        "$ref": "../definitions.json#/error"
385
                    }
386
                },
387
                "401": {
388
                    "description": "Authentication required",
389
                    "schema": {
390
                        "$ref": "../definitions.json#/error"
391
                    }
392
                },
393
                "403": {
394
                    "description": "Access forbidden",
395
                    "schema": {
396
                        "$ref": "../definitions.json#/error"
397
                    }
398
                },
399
                "404": {
400
                    "description": "Patron not found",
401
                    "schema": {
402
                        "$ref": "../definitions.json#/error"
403
                    }
404
                },
405
                "500": {
406
                    "description": "Internal server error",
407
                    "schema": {
408
                        "$ref": "../definitions.json#/error"
409
                    }
410
                },
411
                "503": {
412
                    "description": "Under maintenance",
413
                    "schema": {
414
                        "$ref": "../definitions.json#/error"
415
                    }
416
                }
417
            },
418
            "x-koha-authorization": {
419
                "allow-owner": true
420
            },
421
            "x-koha-embed": [
422
                "item",
423
                "biblio",
424
                "branch"
425
            ]
426
        }
239
    }
427
    }
240
}
428
}
(-)a/koha-tmpl/opac-tmpl/bootstrap/en/includes/usermenu.inc (-7 / +17 lines)
Lines 58-71 Link Here
58
                <a href="/cgi-bin/koha/opac-search-history.pl">your search history</a></li>
58
                <a href="/cgi-bin/koha/opac-search-history.pl">your search history</a></li>
59
            [% END %]
59
            [% END %]
60
60
61
            [% IF ( opacreadinghistory ) %]
61
            [% IF opacreadinghistory || Koha.Preference('OPACHoldsHistory') == 1 %]
62
                [% IF ( readingrecview ) %]
62
                [% IF opacreadinghistory %]
63
                    <li class="active">
63
                    [% IF ( readingrecview ) %]
64
                [% ELSE %]
64
                        <li class="active">
65
                    <li>
65
                    [% ELSE %]
66
                        <li>
67
                    [% END %]
68
                    <a href="/cgi-bin/koha/opac-readingrecord.pl">your reading history</a></li>
69
                [% END %]
70
                [% IF Koha.Preference('OPACHoldsHistory') == 1 %]
71
                    [% IF ( holdsrecview ) %]
72
                        <li class="active">
73
                    [% ELSE %]
74
                        <li>
75
                    [% END %]
76
                    <a href="/cgi-bin/koha/opac-holdsrecord.pl">your holds history</a></li>
66
                [% END %]
77
                [% END %]
67
                <a href="/cgi-bin/koha/opac-readingrecord.pl">your reading history</a></li>
78
                [% IF ( OPACPrivacy || Koha.Preference('OPACHoldsPrivacy') == 1 ) %]
68
                [% IF ( OPACPrivacy ) %]
69
                    [% IF ( privacyview ) %]
79
                    [% IF ( privacyview ) %]
70
                        <li class="active">
80
                        <li class="active">
71
                    [% ELSE %]
81
                    [% ELSE %]
(-)a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-holdsrecord.tt (+247 lines)
Line 0 Link Here
1
[% USE raw %]
2
[% USE Koha %]
3
[% USE KohaDates %]
4
[% INCLUDE 'doc-head-open.inc' %]
5
<title>[% IF ( LibraryNameTitle ) %][% LibraryNameTitle | html %][% ELSE %]Koha online[% END %] catalog &rsaquo; Your holds history</title>
6
[% INCLUDE 'doc-head-close.inc' %]
7
[% BLOCK cssinclude %]
8
    <style>
9
        .controls {
10
            font-size: 75%;
11
        }
12
13
        .controls .paginate_button {
14
            font-family: 'FontAwesome';
15
            text-decoration: none;
16
        }
17
18
        .controls .paginate_button:not(.disabled) {
19
            cursor: pointer;
20
        }
21
22
        .controls .paginate_button.disabled {
23
            color: grey;
24
        }
25
26
        .controls .previous:before {
27
            content: "\f104";
28
            padding-right: .5em;
29
        }
30
31
        .controls .next:after {
32
            content: "\f105";
33
            padding-left: .5em;
34
        }
35
    </style>
36
[% END %]
37
</head>
38
[% INCLUDE 'bodytag.inc' bodyid='opac-holdsrecord' %]
39
[% INCLUDE 'masthead.inc' %]
40
[% #SET AdlibrisEnabled = Koha.Preference('AdlibrisCoversEnabled') %]
41
[% #SET AdlibrisURL = Koha.Preference('AdlibrisCoversURL') %]
42
43
[% #IF Koha.Preference('AmazonAssocTag') %]
44
    [% #AmazonAssocTag = '?tag=' _ Koha.Preference('AmazonAssocTag') %]
45
[% #ELSE %]
46
    [% #AmazonAssocTag = '' %]
47
[% #END %]
48
49
<div class="main">
50
    <ul class="breadcrumb">
51
        <li><a href="/cgi-bin/koha/opac-main.pl">Home</a> <span class="divider">&rsaquo;</span></li>
52
        <li><a href="/cgi-bin/koha/opac-user.pl">[% INCLUDE 'patron-title.inc' patron = logged_in_user %]</a> <span class="divider">&rsaquo;</span></li>
53
        <li><a href="#">Your holds history</a></li>
54
    </ul>
55
56
    <div class="container-fluid">
57
        <div class="row-fluid">
58
            <div class="span2">
59
                <div id="navigation">
60
                    [% INCLUDE 'navigation.inc' IsPatronPage=1 %]
61
                </div>
62
            </div>
63
            <div class="span10">
64
                <div id="userholdsrecord">
65
                    <h3>Holds history</h3>
66
67
                    [% IF READING_RECORD.size == 0 %]
68
                        You have never placed a hold from this library.
69
                    [% ELSE %]
70
                        <div id="opac-user-holdsrec">
71
                            <div id="tabs-container" style="overflow:auto">
72
                                <div class="controls">
73
                                    <div class="span3 info">
74
75
                                    </div>
76
                                    <div class="span2">
77
                                        <input type="text" class="search" placeholder="search" autofocus/>
78
                                    </div>
79
                                    <div class="span1">
80
                                        <a class="paginate_button previous disabled" aria-controls="holdsrec" data-dt-idx="1">Previous</a>
81
                                    </div>
82
                                    <div class="span1">
83
                                        <a class="paginate_button next disabled" aria-controls="holdsrec" data-dt-idx="1">Next</a>
84
                                    </div>
85
                                </div>
86
                                <table id="holdsrec" class="table table-bordered table-striped">
87
                                    <thead>
88
                                        <tr>
89
                                            <th class="anti-the">Title</th>
90
                                            <th class="">Author</th>
91
                                            <th class="">Barcode</th>
92
                                            <th class="">Library</th>
93
                                            <th class="title-string">Hold date</th>
94
                                            <th class="title-string">Expiration date</th>
95
                                            <th class="title-string">Waiting date</th>
96
                                            <th class="title-string">Cancellation date</th>
97
                                            <th>Status</th>
98
                                        </tr>
99
                                    </thead>
100
                                    <tbody>
101
102
                                    </tbody>
103
                                </table>
104
                                <div class="controls">
105
                                    <div class="span3 info">
106
107
                                    </div>
108
                                    <div class="span1">
109
                                        <a class="paginate_button previous disabled" aria-controls="holdsrec" data-dt-idx="1">Previous</a>
110
                                    </div>
111
                                    <div class="span1">
112
                                        <a class="paginate_button next disabled" aria-controls="holdsrec" data-dt-idx="1">Next</a>
113
                                    </div>
114
                                </div>
115
                            </div> <!-- / .tabs-container -->
116
                        </div> <!-- / .opac-user-readingrec -->
117
                    [% END # / IF READING_RECORD.size %]
118
                </div> <!-- / .userreadingrecord -->
119
            </div> <!-- / .span10 -->
120
        </div> <!-- / .row-fluid -->
121
    </div> <!-- / .container-fluid -->
122
</div> <!-- / .main -->
123
124
[% INCLUDE 'opac-bottom.inc' %]
125
[% BLOCK jsinclude %]
126
[% INCLUDE 'datatables.inc' %]
127
[% INCLUDE 'js-date-format.inc' %]
128
<script>
129
    $(document).ready(function(){
130
        [% IF ( GoogleJackets ) %]KOHA.Google.GetCoverFromIsbn();[% END %]
131
        $('#order').change(function() {
132
            $('#sortform').submit();
133
        });
134
135
        var table = $("#holdsrec").api({
136
            "ajax": {
137
                "url": "/api/v1/public/patrons/[% borrowernumber | html %]/holds?old=true"
138
            },
139
            "embed": [
140
                "item",
141
                "biblio",
142
                "branch"
143
            ],
144
            'order': [[ 4, "desc" ]],
145
            "columnDefs": [
146
                { "targets": [ "nosort" ],"sortable": false,"searchable": false },
147
                { "type": "anti-the", "targets" : [ "anti-the" ] },
148
                { "type": "title-string", "targets" : [ "title-string" ] }
149
            ],
150
            "columns": [
151
                {
152
                    "data": "biblio.title",
153
                    "render": function(data, type, row, meta) {
154
                        if (type != 'display') return data;
155
                        return '<a href="opac-detail.pl?biblionumber='+row.biblio_id+'">'+data+'</a>';
156
                    }
157
                },
158
                {"data": "biblio.author"},
159
                {
160
                    "data": "item.external_id",
161
                    "render": function(data, type, row, meta) {
162
                        if(data) return data;
163
                        return '';
164
                    }
165
                },
166
                {"data": "branch.name"},
167
                {
168
                    "data": "hold_date",
169
                    "render": function(data, type, row, meta) {
170
                        return (data&&$date(data))||'';
171
                    }
172
                },
173
                {
174
                    "data": "expiration_date",
175
                    "render": function(data, type, row, meta) {
176
                        return (data&&$date(data))||'';
177
                    }
178
                },
179
                {
180
                    "data": "waiting_date",
181
                    "render": function(data, type, row, meta) {
182
                        return (data&&$date(data))||'';
183
                    }
184
                },
185
                {
186
                    "data": "cancelation_date",
187
                    "render": function(data, type, row, meta) {
188
                        return (data&&$date(data))||'';
189
                    }
190
                },
191
                {
192
                    "data": "status",
193
                    "render": function(data, type, row, meta) {
194
                        if (type != 'display') return data;
195
                        if(row.cancelation_date) return 'Canceled';
196
                        if (data == 'F') return 'Fulfilled';
197
                        if (data == 'W') return 'Waiting';
198
                        if (data == 'T') return 'In Transit';
199
                        return 'Pending';
200
                    }
201
                }
202
            ]
203
        }).DataTable();
204
205
        table.on('draw.dt', function(event, settings) {
206
            var page_info = table.page.info();
207
            $(".controls .info").html(_("Showing page %s of %s").format(page_info.page+1, page_info.pages));
208
            if(!page_info.page) {
209
                $('.controls .previous').addClass('disabled');
210
            } else {
211
                $('.controls .previous').removeClass('disabled');
212
            }
213
            if(page_info.pages-1===page_info.page) {
214
                $('.controls .next').addClass('disabled');
215
            } else {
216
                $('.controls .next').removeClass('disabled');
217
            }
218
        })
219
220
        $('.controls .previous').click(function() {
221
            table.page('previous').draw('page');
222
        });
223
224
        $('.controls .next').click(function() {
225
            table.page('next').draw('page');
226
        });
227
        function debounce(func, wait, immediate) {
228
            var timeout;
229
            return function() {
230
                var context = this, args = arguments;
231
                var later = function() {
232
                    timeout = null;
233
                    if (!immediate) func.apply(context, args);
234
                };
235
                var callNow = immediate && !timeout;
236
                clearTimeout(timeout);
237
                timeout = setTimeout(later, wait);
238
                if (callNow) func.apply(context, args);
239
            };
240
        };
241
242
        $(".controls .search").keypress(debounce(function(event) {
243
            table.search(this.value).draw();
244
        }, 300));
245
    });
246
</script>
247
[% END %]
(-)a/opac/opac-holdsrecord.pl (-1 / +161 lines)
Line 0 Link Here
0
- 
1
#!/usr/bin/perl
2
3
# This file is part of Koha.
4
#
5
# Koha is free software; you can redistribute it and/or modify it
6
# under the terms of the GNU General Public License as published by
7
# the Free Software Foundation; either version 3 of the License, or
8
# (at your option) any later version.
9
#
10
# Koha is distributed in the hope that it will be useful, but
11
# WITHOUT ANY WARRANTY; without even the implied warranty of
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
# GNU General Public License for more details.
14
#
15
# You should have received a copy of the GNU General Public License
16
# along with Koha; if not, see <http://www.gnu.org/licenses>.
17
18
19
use Modern::Perl;
20
21
use CGI qw ( -utf8 );
22
23
use C4::Auth;
24
use C4::Koha;
25
use C4::Biblio;
26
use C4::Circulation;
27
use C4::Members;
28
use Koha::DateUtils;
29
use MARC::Record;
30
31
use C4::Output;
32
use C4::Charset qw(StripNonXmlChars);
33
use Koha::Patrons;
34
35
use Koha::ItemTypes;
36
use Koha::Ratings;
37
38
my $query = new CGI;
39
40
# if opacreadinghistory is disabled, leave immediately
41
if ( ! C4::Context->preference('OPACHoldsHistory') ) {
42
    print $query->redirect("/cgi-bin/koha/errors/404.pl");
43
    exit;
44
}
45
46
my ( $template, $borrowernumber, $cookie ) = get_template_and_user(
47
    {
48
        template_name   => "opac-holdsrecord.tt",
49
        query           => $query,
50
        type            => "opac",
51
        authnotrequired => 0,
52
        debug           => 1,
53
    }
54
);
55
56
my $borr = Koha::Patrons->find( $borrowernumber )->unblessed;
57
58
$template->param(%{$borr});
59
60
# my $itemtypes = { map { $_->{itemtype} => $_ } @{ Koha::ItemTypes->search_with_localization->unblessed } };
61
62
# # get the record
63
# my $order = $query->param('order') || '';
64
# if ( $order eq 'title' ) {
65
#     $template->param( orderbytitle => 1 );
66
# }
67
# elsif ( $order eq 'author' ) {
68
#     $template->param( orderbyauthor => 1 );
69
# }
70
# else {
71
#     $order = "date_due desc";
72
#     $template->param( orderbydate => 1 );
73
# }
74
75
76
# my $limit = $query->param('limit');
77
# $limit //= '';
78
# $limit = ( $limit eq 'full' ) ? 0 : 50;
79
80
# # my $issues = GetAllIssues( $borrowernumber, $order, $limit );
81
82
# # my $itype_attribute =
83
# #   ( C4::Context->preference('item-level_itypes') ) ? 'itype' : 'itemtype';
84
85
# # my $opac_summary_html = C4::Context->preference('OPACMySummaryHTML');
86
# foreach my $issue ( @{$issues} ) {
87
#     $issue->{normalized_isbn} = GetNormalizedISBN( $issue->{isbn} );
88
#     if ( $issue->{$itype_attribute} ) {
89
#         $issue->{translated_description} =
90
#           $itemtypes->{ $issue->{$itype_attribute} }->{translated_description};
91
#         $issue->{imageurl} =
92
#           getitemtypeimagelocation( 'opac',
93
#             $itemtypes->{ $issue->{$itype_attribute} }->{imageurl} );
94
#     }
95
#     my $marcxml = C4::Biblio::GetXmlBiblio( $issue->{biblionumber} );
96
#     if ( $marcxml ) {
97
#         $marcxml = StripNonXmlChars( $marcxml );
98
#         my $marc_rec =
99
#           MARC::Record::new_from_xml( $marcxml, 'utf8',
100
#             C4::Context->preference('marcflavour') );
101
#         $issue->{normalized_upc} = GetNormalizedUPC( $marc_rec, C4::Context->preference('marcflavour') );
102
#     }
103
#     # My Summary HTML
104
#     if ($opac_summary_html) {
105
#         my $my_summary_html = $opac_summary_html;
106
#         $issue->{author}
107
#           ? $my_summary_html =~ s/{AUTHOR}/$issue->{author}/g
108
#           : $my_summary_html =~ s/{AUTHOR}//g;
109
#         my $title = $issue->{title};
110
#         $title =~ s/\/+$//;    # remove trailing slash
111
#         $title =~ s/\s+$//;    # remove trailing space
112
#         $title
113
#           ? $my_summary_html =~ s/{TITLE}/$title/g
114
#           : $my_summary_html =~ s/{TITLE}//g;
115
#         $issue->{normalized_isbn}
116
#           ? $my_summary_html =~ s/{ISBN}/$issue->{normalized_isbn}/g
117
#           : $my_summary_html =~ s/{ISBN}//g;
118
#         $issue->{biblionumber}
119
#           ? $my_summary_html =~ s/{BIBLIONUMBER}/$issue->{biblionumber}/g
120
#           : $my_summary_html =~ s/{BIBLIONUMBER}//g;
121
#         $issue->{MySummaryHTML} = $my_summary_html;
122
#     }
123
#     # Star ratings
124
#     if ( C4::Context->preference('OpacStarRatings') eq 'all' ) {
125
#         my $ratings = Koha::Ratings->search({ biblionumber => $issue->{biblionumber} });
126
#         $issue->{ratings} = $ratings;
127
#         $issue->{my_rating} = $borrowernumber ? $ratings->search({ borrowernumber => $borrowernumber })->next : undef;
128
#     }
129
# }
130
131
# if (C4::Context->preference('BakerTaylorEnabled')) {
132
#   $template->param(
133
#     JacketImages=>1,
134
#     BakerTaylorEnabled  => 1,
135
#     BakerTaylorImageURL => &image_url(),
136
#     BakerTaylorLinkURL  => &link_url(),
137
#     BakerTaylorBookstoreURL => C4::Context->preference('BakerTaylorBookstoreURL'),
138
#   );
139
# }
140
141
# BEGIN {
142
#   if (C4::Context->preference('BakerTaylorEnabled')) {
143
#     require C4::External::BakerTaylor;
144
#     import C4::External::BakerTaylor qw(&image_url &link_url);
145
#   }
146
# }
147
148
# for(qw(AmazonCoverImages GoogleJackets)) { # BakerTaylorEnabled handled above
149
#   C4::Context->preference($_) or next;
150
#   $template->param($_=>1);
151
#   $template->param(JacketImages=>1);
152
# }
153
154
$template->param(
155
#     READING_RECORD => $issues,
156
#     limit          => $limit,
157
    holdsrecview => 1,
158
#     OPACMySummaryHTML => $opac_summary_html ? 1 : 0,
159
);
160
161
output_html_with_http_headers $query, $cookie, $template->output, undef, { force_no_caching => 1 };

Return to bug 20936