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

(-)a/C4/Circulation.pm (-1 lines)
Lines 2509-2515 sub GetOpenIssue { Link Here
2509
=head2 GetIssues
2509
=head2 GetIssues
2510
2510
2511
    $issues = GetIssues({});    # return all issues!
2511
    $issues = GetIssues({});    # return all issues!
2512
    $issues = GetIssues({ borrowernumber => $borrowernumber, biblionumber => $biblionumber });
2513
2512
2514
Returns all pending issues that match given criteria.
2513
Returns all pending issues that match given criteria.
2515
Returns a arrayref or undef if an error occurs.
2514
Returns a arrayref or undef if an error occurs.
(-)a/Koha/Issue.pm (+130 lines)
Lines 21-28 use Koha::Database; Link Here
21
21
22
use base qw(Koha::Object);
22
use base qw(Koha::Object);
23
23
24
use vars qw(@ISA @EXPORT);
25
26
BEGIN {
27
    require Exporter;
28
    @ISA = qw(Exporter);
29
30
    push @EXPORT, qw(
31
        &GetIssue
32
        &SetIssueNote
33
        &SendIssueNote
34
        &GetPatronNote
35
    );
36
}
37
24
sub _type {
38
sub _type {
25
    return 'Issue';
39
    return 'Issue';
26
}
40
}
27
41
42
=head2 GetIssue
43
44
    $issue = GetIssue({ issue_id => $issue_id });
45
46
Returns issue with provided issue_id
47
48
=cut
49
50
sub GetIssue {
51
    my ($criteria) = @_;
52
    # Build filters
53
    my @filters;
54
    my @allowed = qw(borrowernumber biblionumber itemnumber issue_id);
55
    foreach (@allowed) {
56
        if (defined $criteria->{$_}) {
57
            push @filters, {
58
               field => $_,
59
               value => $criteria->{$_},
60
            };
61
        }
62
    }
63
64
    # Build SQL query
65
    my $where = '';
66
    if (@filters) {
67
        $where = "WHERE " . join(' AND ', map { "$_->{field} = ?" } @filters);
68
    }
69
    my $query = q{
70
        SELECT issues.*
71
        FROM issues
72
    };
73
    $query .= $where;
74
75
    # Execute SQL query
76
    my $dbh = C4::Context->dbh;
77
    my $sth = $dbh->prepare($query);
78
    $sth->execute(map { $_->{value} } @filters);
79
80
    my $issue = $sth->fetchrow_hashref;
81
    return $issue;
82
}
83
84
=head2 SetIssueNote
85
86
    &SetIssueNote($issue_id, $note);
87
88
Sets a note to the issuenotes table for the given issue.
89
90
=over 4
91
92
=item C<$issue_id> is the id of the issue for which to set the note
93
94
=item C<$note> is the note to set
95
96
=back
97
98
Returns:
99
True on success
100
False on failure
101
102
=cut
103
104
sub SetIssueNote {
105
    my ( $issue_id, $note) = @_;
106
    my $dbh  = C4::Context->dbh;
107
    unless ( $issue_id =~ /\d+/ ) {
108
        return;
109
    }
110
111
    my $query = "UPDATE issues SET notedate=NOW(),note=? WHERE issue_id=?";
112
    my $sth = $dbh->prepare($query);
113
    return $sth->execute( $note, $issue_id );
114
}
115
116
=head2 SendIssueNote
117
118
    &SendIssueNote($biblio, $borrower, $branch);
119
120
Sends the issue note to the library (adds it to the message queue).
121
122
=cut
123
124
sub SendIssueNote {
125
    my $biblio = shift;
126
    my $borrower = shift;
127
    my $branch = shift;
128
    my $letter = C4::Letters::GetPreparedLetter (
129
        module => 'circulation',
130
        letter_code => 'PATRON_NOTE',
131
        branchcode => $branch,
132
        tables => {
133
            'biblio' => $biblio->{biblionumber},
134
            'borrowers' => $borrower->{borrowernumber},
135
        },
136
    );
137
    C4::Message->enqueue($letter, $borrower, 'email');
138
}
139
140
=head2 GetPatronNote
141
142
    &GetPatronNote($itemnumber);
143
144
Gets the patron note of an issue upon checkin using itemnumber
145
146
=cut
147
148
sub GetPatronNote {
149
    my $itemnumber = shift;
150
    my $dbh = C4::Context->dbh;
151
    my $query = "SELECT note FROM issues WHERE itemnumber = ?";
152
    my $sth = $dbh->prepare($query);
153
    $sth->execute($itemnumber);
154
    my $patronnote = $sth->fetchrow_hashref;
155
    return $patronnote->{note};
156
}
157
28
1;
158
1;
(-)a/circ/returns.pl (+3 lines)
Lines 282-287 if ($barcode) { Link Here
282
    my $descriptions = Koha::AuthorisedValues->get_description_by_koha_field({frameworkcode => '', kohafield =>'items.materials', authorised_value => $materials });
282
    my $descriptions = Koha::AuthorisedValues->get_description_by_koha_field({frameworkcode => '', kohafield =>'items.materials', authorised_value => $materials });
283
    $materials = $descriptions->{lib} // '';
283
    $materials = $descriptions->{lib} // '';
284
284
285
    my $issue = GetItemIssue($itemnumber);
286
285
    $template->param(
287
    $template->param(
286
        title            => $biblio->{'title'},
288
        title            => $biblio->{'title'},
287
        homebranch       => $biblio->{'homebranch'},
289
        homebranch       => $biblio->{'homebranch'},
Lines 295-300 if ($barcode) { Link Here
295
        biblionumber     => $biblio->{'biblionumber'},
297
        biblionumber     => $biblio->{'biblionumber'},
296
        borrower         => $borrower,
298
        borrower         => $borrower,
297
        additional_materials => $materials,
299
        additional_materials => $materials,
300
        issue            => $issue,
298
    );
301
    );
299
302
300
    my %input = (
303
    my %input = (
(-)a/installer/data/mysql/atomicupdate/bug_14224-add_new_issue_columns.sql (+2 lines)
Line 0 Link Here
1
ALTER IGNORE TABLE issues ADD `note` mediumtext default NULL;
2
ALTER IGNORE TABLE issues ADD `notedate` datetime default NULL;
(-)a/installer/data/mysql/atomicupdate/bug_14224-add_patron_notice_to_letters.sql (+1 lines)
Line 0 Link Here
1
INSERT IGNORE INTO letter (`module`, `code`, `branchcode`, `name`, `is_html`, `title`, `content`, `message_transport_type`) VALUES ('circulation', 'PATRON_NOTE', '', 'Patron note on item', '0', 'Patron issue note', '<<borrowers.firstname>> <<borrowers.surname>> has added a note to the item <<biblio.item>> - <<biblio.author>> (<<biblio.biblionumber>>).','email');
(-)a/installer/data/mysql/atomicupdate/bug_14224-issue_notes_syspref.sql (+1 lines)
Line 0 Link Here
1
INSERT IGNORE INTO systempreferences (`variable`, `value`, `options`, `explanation`,`type`) VALUES ('AllowIssueNotes', '0', NULL, 'Allow patrons to submit notes about checked out items.','YesNo');
(-)a/installer/data/mysql/kohastructure.sql (+30 lines)
Lines 841-846 CREATE TABLE `import_items` ( Link Here
841
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
841
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
842
842
843
--
843
--
844
-- Table structure for table `issues`
845
--
846
847
DROP TABLE IF EXISTS `issues`;
848
CREATE TABLE `issues` ( -- information related to check outs or issues
849
  `issue_id` int(11) NOT NULL AUTO_INCREMENT, -- primary key for issues table
850
  `borrowernumber` int(11), -- foreign key, linking this to the borrowers table for the patron this item was checked out to
851
  `itemnumber` int(11), -- foreign key, linking this to the items table for the item that was checked out
852
  `date_due` datetime default NULL, -- datetime the item is due (yyyy-mm-dd hh:mm::ss)
853
  `branchcode` varchar(10) default NULL, -- foreign key, linking to the branches table for the location the item was checked out
854
  `returndate` datetime default NULL, -- date the item was returned, will be NULL until moved to old_issues
855
  `lastreneweddate` datetime default NULL, -- date the item was last renewed
856
  `return` varchar(4) default NULL,
857
  `renewals` tinyint(4) default NULL, -- lists the number of times the item was renewed
858
  `auto_renew` BOOLEAN default FALSE, -- automatic renewal
859
  `timestamp` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP, -- the date and time this record was last touched
860
  `issuedate` datetime default NULL, -- date the item was checked out or issued
861
  `onsite_checkout` int(1) NOT NULL default 0, -- in house use flag
862
  `note` mediumtext default NULL, -- issue note text
863
  `notedate` datetime default NULL, -- datetime of issue note (yyyy-mm-dd hh:mm::ss)
864
  PRIMARY KEY (`issue_id`),
865
  KEY `issuesborridx` (`borrowernumber`),
866
  KEY `itemnumber_idx` (`itemnumber`),
867
  KEY `branchcode_idx` (`branchcode`),
868
  KEY `bordate` (`borrowernumber`,`timestamp`),
869
  CONSTRAINT `issues_ibfk_1` FOREIGN KEY (`borrowernumber`) REFERENCES `borrowers` (`borrowernumber`) ON DELETE RESTRICT ON UPDATE CASCADE,
870
  CONSTRAINT `issues_ibfk_2` FOREIGN KEY (`itemnumber`) REFERENCES `items` (`itemnumber`) ON DELETE RESTRICT ON UPDATE CASCADE
871
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
872
873
--
844
-- Table structure for table `issuingrules`
874
-- Table structure for table `issuingrules`
845
--
875
--
846
876
(-)a/installer/data/mysql/sysprefs.sql (+1 lines)
Lines 29-34 INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, ` Link Here
29
('AllowNotForLoanOverride','0','','If ON, Koha will allow the librarian to loan a not for loan item.','YesNo'),
29
('AllowNotForLoanOverride','0','','If ON, Koha will allow the librarian to loan a not for loan item.','YesNo'),
30
('AllowOfflineCirculation','0','','If on, enables HTML5 offline circulation functionality.','YesNo'),
30
('AllowOfflineCirculation','0','','If on, enables HTML5 offline circulation functionality.','YesNo'),
31
('AllowPatronToSetCheckoutsVisibilityForGuarantor',  '0', NULL, 'If enabled, the patron can set checkouts to be visible to his or her guarantor',  'YesNo'),
31
('AllowPatronToSetCheckoutsVisibilityForGuarantor',  '0', NULL, 'If enabled, the patron can set checkouts to be visible to his or her guarantor',  'YesNo'),
32
('AllowIssueNotes', '0', NULL, 'Allow patrons to submit notes about checked out items.','YesNo'),
32
('AllowPKIAuth','None','None|Common Name|emailAddress','Use the field from a client-side SSL certificate to look a user in the Koha database','Choice'),
33
('AllowPKIAuth','None','None|Common Name|emailAddress','Use the field from a client-side SSL certificate to look a user in the Koha database','Choice'),
33
('AllowPurchaseSuggestionBranchChoice','0','1','Allow user to choose branch when making a purchase suggestion','YesNo'),
34
('AllowPurchaseSuggestionBranchChoice','0','1','Allow user to choose branch when making a purchase suggestion','YesNo'),
34
('AllowRenewalIfOtherItemsAvailable','0',NULL,'If enabled, allow a patron to renew an item with unfilled holds if other available items can fill that hold.','YesNo'),
35
('AllowRenewalIfOtherItemsAvailable','0',NULL,'If enabled, allow a patron to renew an item with unfilled holds if other available items can fill that hold.','YesNo'),
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref (+6 lines)
Lines 136-141 Circulation: Link Here
136
                  yes: Show
136
                  yes: Show
137
                  no: "Do not show"
137
                  no: "Do not show"
138
            - all items in the "Checked-in items" list, even items that were not checked out.
138
            - all items in the "Checked-in items" list, even items that were not checked out.
139
        -
140
            - pref: AllowIssueNotes
141
              choices:
142
                  yes: Allow
143
                  no: "Don't allow"
144
            - patrons to submit notes about checked out items.
139
145
140
    Checkout Policy:
146
    Checkout Policy:
141
        -
147
        -
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/returns.tt (+10 lines)
Lines 183-188 $(document).ready(function () { Link Here
183
</div>
183
</div>
184
[% END %]
184
[% END %]
185
185
186
<!-- Patron has added an issue note -->
187
[% IF ( issue.note) %]
188
    <div class="dialog message">
189
        <h1>Patron note</h1>
190
        <p>[% issue.notedate %]</p>
191
        <p><a href="/cgi-bin/koha/catalogue/detail.pl?biblionumber=[% itembiblionumber %]"> [% title |html %]</a> [% author %]</p>
192
        <p>[% issue.note %]</p>
193
    </div>
194
[% END %]
195
186
<!-- Patron has fines -->
196
<!-- Patron has fines -->
187
[% IF ( fines ) %]
197
[% IF ( fines ) %]
188
    <div class="dialog alert">
198
    <div class="dialog alert">
(-)a/koha-tmpl/intranet-tmpl/prog/js/checkouts.js (-4 / +9 lines)
Lines 67-72 $(document).ready(function() { Link Here
67
                    content = CIRCULATION_RETURNED;
67
                    content = CIRCULATION_RETURNED;
68
                    $(id).parent().parent().addClass('ok');
68
                    $(id).parent().parent().addClass('ok');
69
                    $('#date_due_' + data.itemnumber).html(CIRCULATION_RETURNED);
69
                    $('#date_due_' + data.itemnumber).html(CIRCULATION_RETURNED);
70
                    $('#patron_note_' + data.itemnumber).html("Patron note: " + data.patronnote);
70
                } else {
71
                } else {
71
                    content = CIRCULATION_NOT_RETURNED;
72
                    content = CIRCULATION_NOT_RETURNED;
72
                    $(id).parent().parent().addClass('warn');
73
                    $(id).parent().parent().addClass('warn');
Lines 218-224 $(document).ready(function() { Link Here
218
                },
219
                },
219
                {
220
                {
220
                    "mDataProp": function ( oObj ) {
221
                    "mDataProp": function ( oObj ) {
221
                        title = "<span class='strong'><a href='/cgi-bin/koha/catalogue/detail.pl?biblionumber="
222
                        title = "<span id='title_" + oObj.itemnumber + "' class='strong'><a href='/cgi-bin/koha/catalogue/detail.pl?biblionumber="
222
                              + oObj.biblionumber
223
                              + oObj.biblionumber
223
                              + "'>"
224
                              + "'>"
224
                              + oObj.title;
225
                              + oObj.title;
Lines 242-248 $(document).ready(function() { Link Here
242
                            if ( $.datepicker.formatDate('yy-mm-dd', new Date(oObj.issuedate) ) == ymd ) {
243
                            if ( $.datepicker.formatDate('yy-mm-dd', new Date(oObj.issuedate) ) == ymd ) {
243
                                span_class = "circ-hlt";
244
                                span_class = "circ-hlt";
244
                            }
245
                            }
245
                            title += " - <span class='" + span_class + "'>" + oObj.itemnotes + "</span>"
246
                            title += " - <span class='" + span_class + "'>" + oObj.itemnotes + "</span>";
246
                        }
247
                        }
247
248
248
                        if ( oObj.itemnotes_nonpublic ) {
249
                        if ( oObj.itemnotes_nonpublic ) {
Lines 250-256 $(document).ready(function() { Link Here
250
                            if ( $.datepicker.formatDate('yy-mm-dd', new Date(oObj.issuedate) ) == ymd ) {
251
                            if ( $.datepicker.formatDate('yy-mm-dd', new Date(oObj.issuedate) ) == ymd ) {
251
                                span_class = "circ-hlt";
252
                                span_class = "circ-hlt";
252
                            }
253
                            }
253
                            title += " - <span class='" + span_class + "'>" + oObj.itemnotes_nonpublic + "</span>"
254
                            title += " - <span class='" + span_class + "'>" + oObj.itemnotes_nonpublic + "</span>";
254
                        }
255
                        }
255
256
256
                        var onsite_checkout = '';
257
                        var onsite_checkout = '';
Lines 258-263 $(document).ready(function() { Link Here
258
                            onsite_checkout += " <span class='onsite_checkout'>(" + INHOUSE_USE + ")</span>";
259
                            onsite_checkout += " <span class='onsite_checkout'>(" + INHOUSE_USE + ")</span>";
259
                        }
260
                        }
260
261
262
                        var patron_note = " <span id='patron_note_" + oObj.itemnumber + "'></span>";
263
261
                        title += " "
264
                        title += " "
262
                              + "<a href='/cgi-bin/koha/catalogue/moredetail.pl?biblionumber="
265
                              + "<a href='/cgi-bin/koha/catalogue/moredetail.pl?biblionumber="
263
                              + oObj.biblionumber
266
                              + oObj.biblionumber
Lines 268-274 $(document).ready(function() { Link Here
268
                              + "'>"
271
                              + "'>"
269
                              + oObj.barcode
272
                              + oObj.barcode
270
                              + "</a>"
273
                              + "</a>"
271
                              + onsite_checkout;
274
                              + onsite_checkout
275
                              + "<br>"
276
                              + patron_note
272
277
273
                        return title;
278
                        return title;
274
                    },
279
                    },
(-)a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-issue-note.tt (+54 lines)
Line 0 Link Here
1
[% USE Koha %]
2
[% USE KohaDates %]
3
[% USE Branches %]
4
[% INCLUDE 'doc-head-open.inc' %]
5
<title>[% IF ( LibraryNameTitle ) %][% LibraryNameTitle %][% ELSE %]Koha online[% END %] catalog &rsaquo; Your library home</title>
6
[% INCLUDE 'doc-head-close.inc' %]
7
[% BLOCK cssinclude %][% END %]
8
</head>
9
[% INCLUDE 'bodytag.inc' bodyid='opac-issue-note' %]
10
[% INCLUDE 'masthead.inc' %]
11
12
<div class="main">
13
    <ul class="breadcrumb">
14
        <li><a href="/cgi-bin/koha/opac-main.pl">Home</a> <span class="divider">&rsaquo;</span></li>
15
        <li><a href="/cgi-bin/koha/opac-user.pl">[% firstname %] [% surname %]</a><span class="divider">&rsaquo;</span></li>
16
        <li><a href="#">Editing issue note for [% ISSUE.title %] - [% ISSUE.author %]</a></li>
17
    </ul>
18
19
    <div class="container-fluid">
20
        <div class="row-fluid">
21
            <div class="span2">
22
                <div id="navigation">
23
                    [% INCLUDE 'navigation.inc' IsPatronPage=1 %]
24
                </div>
25
            </div>
26
            <div class="span10">
27
                <div id="issuenote" class="maincontent">
28
                    <h3>Editing issue note for [% title %] [% author %]</h3>
29
                        [% IF not(Koha.Preference("AllowIssueNotes")) %]
30
                            Issue notes have not been enabled. Please contact the library.
31
                        [% ELSE %]
32
                            <form id="issue-note" action="/cgi-bin/koha/opac-issue-note.pl" method="post">
33
                                <fieldset>
34
                                    <label for="note" class="required">Note:</label>
35
                                    <input type="text" name="note" value="[% note %]">
36
                                    <input type="hidden" name="borrowernumber" value="[% borrowernumber %]">
37
                                    <input type="hidden" name="itemnumber" value="[% itemnumber %]">
38
                                    <input type="hidden" name="issue_id" value="[% issue_id %]">
39
                                    <input type="hidden" name="action" value="issuenote">
40
                                </fieldset>
41
                                <fieldset class="action">
42
                                    <input type="submit" value="Submit note" class="btn"><a href="/cgi-bin/koha/opac-user.pl" class="cancel">Cancel</a>
43
                                </fieldset>
44
                            </form> <!-- issue-note -->
45
                        [% END %]
46
                </div> <!-- issuenote -->
47
            </div> <!-- span10 -->
48
        </div> <!-- row-fluid -->
49
    </div> <!-- container-fluid -->
50
51
</div> <!-- main -->
52
53
[% INCLUDE 'opac-bottom.inc' %]
54
[% BLOCK jsinclude %][% END %]
(-)a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-user.tt (+94 lines)
Lines 120-125 Using this account is not recommended because some parts of Koha will not functi Link Here
120
                        </div>
120
                        </div>
121
                    [% END # / IF patron_flagged %]
121
                    [% END # / IF patron_flagged %]
122
122
123
                    <div class="alert alert-info" id="notesaved" style="display:none;"></div>
124
123
                    [% SET OPACMySummaryNote = Koha.Preference('OPACMySummaryNote') %]
125
                    [% SET OPACMySummaryNote = Koha.Preference('OPACMySummaryNote') %]
124
                    [% IF OPACMySummaryNote %][% OPACMySummaryNote %][% END %]
126
                    [% IF OPACMySummaryNote %][% OPACMySummaryNote %][% END %]
125
127
Lines 165-170 Using this account is not recommended because some parts of Koha will not functi Link Here
165
                                                [% IF ( OPACMySummaryHTML ) %]
167
                                                [% IF ( OPACMySummaryHTML ) %]
166
                                                    <th class="nosort">Links</th>
168
                                                    <th class="nosort">Links</th>
167
                                                [% END %]
169
                                                [% END %]
170
                                                [% IF ( AllowIssueNotes ) %]
171
                                                    <th class="nosort">Note</th>
172
                                                [% END %]
168
                                            </tr>
173
                                            </tr>
169
                                        </thead>
174
                                        </thead>
170
                                        <tbody>
175
                                        <tbody>
Lines 283-288 Using this account is not recommended because some parts of Koha will not functi Link Here
283
                                                [% IF ( OPACMySummaryHTML ) %]
288
                                                [% IF ( OPACMySummaryHTML ) %]
284
                                                    <td class="links">[% ISSUE.MySummaryHTML %]</td>
289
                                                    <td class="links">[% ISSUE.MySummaryHTML %]</td>
285
                                                [% END %]
290
                                                [% END %]
291
                                                [% IF ( AllowIssueNotes ) %]
292
                                                    <td class="note">
293
                                                        <input type="text" name="note" data-issue_id="[% ISSUE.issue_id %]" data-origvalue="[% ISSUE.note %]" value="[% ISSUE.note %]" readonly>
294
                                                        <a class="btn" name="js_submitnote" id="save_[% ISSUE.issue_id %]" style="display:none;">Submit note</a>
295
                                                        <a class="btn" name="nonjs_submitnote" href="/cgi-bin/koha/opac-issue-note.pl?issue_id=[% ISSUE.issue_id | url %]">Edit / Create note</a>
296
                                                    </td>
297
                                                [% END %]
286
                                            </tr>
298
                                            </tr>
287
                                        [% END # /FOREACH ISSUES %]
299
                                        [% END # /FOREACH ISSUES %]
288
                                    </tbody>
300
                                    </tbody>
Lines 883-888 Using this account is not recommended because some parts of Koha will not functi Link Here
883
                [% END %]
895
                [% END %]
884
            [% END %]
896
            [% END %]
885
897
898
            [% IF ( AllowIssueNotes ) %]
899
900
                /* If JS enabled, show button, otherwise show link to redirect to a page where note can be submitted */
901
                $("a[name='nonjs_submitnote']").hide();
902
903
                $("input[name='note']").prop('readonly', false);
904
                $("input[name='note']").keyup(function(e){
905
                    /* prevent submitting of renewselected form */
906
                    if(e.which == 13)
907
                        e.preventDefault();
908
909
                    var $btn_save = $('#save_'+$(this).data('issue_id'));
910
                    var origvalue = $(this).data('origvalue');
911
                    var value = $(this).val();
912
913
                    if(origvalue != value) {
914
                        if(origvalue != "")
915
                            $btn_save.text('Submit changes');
916
                        else
917
                            $btn_save.text('Submit note');
918
                        $btn_save.show();
919
                    } else {
920
                        $btn_save.hide();
921
                    }
922
                });
923
924
                $("a[name='js_submitnote']").click(function(e){
925
                    var $self = $(this);
926
                    var title = $(this).parent().siblings('.title').html();
927
                    var $noteinput = $(this).siblings('input[name="note"]').first();
928
929
                    var ajaxData = {
930
                        'action': 'issuenote',
931
                        'issue_id': $noteinput.data('issue_id'),
932
                        'note': $noteinput.val(),
933
                    };
934
935
                    $.ajax({
936
                        url: '/cgi-bin/koha/svc/patron_notes/',
937
                        type: 'POST',
938
                        dataType: 'json',
939
                        data: ajaxData,
940
                    })
941
                    .done(function(data) {
942
                        var message = "";
943
                        if(data.status == 'saved') {
944
                            $("#notesaved").removeClass("alert-error");
945
                            $("#notesaved").addClass("alert-info");
946
                            $noteinput.data('origvalue', data.note);
947
                            $noteinput.val(data.note);
948
                            message = "<p>Your note about " + title + " has been saved and sent to the library.</p>";
949
                            $self.hide();
950
                        } else if(data.status == 'removed') {
951
                            $("#notesaved").removeClass("alert-error");
952
                            $("#notesaved").addClass("alert-info");
953
                            $noteinput.data('origvalue', "");
954
                            $noteinput.val("");
955
                            message = "<p>Your note about " + title + " was removed.</p>";
956
                            $self.hide();
957
                        } else {
958
                            $("#notesaved").removeClass("alert-info");
959
                            $("#notesaved").addClass("alert-error");
960
                            message = "<p>Your note about " + title + " could not be saved.</p>" +
961
                                      "<p style=\"font-weight:bold;\">" + data.error + "</p>";
962
                        }
963
964
                        message += "<p style=\"font-style:italic;\">" + data.note + "</p>";
965
                        $("#notesaved").html(message);
966
                    })
967
                    .fail(function(data) {
968
                        $("#notesaved").removeClass("alert-info");
969
                        $("#notesaved").addClass("alert-error");
970
                        var message = "<p>Your note about " + title + " could not be saved.</p>" +
971
                                      "<p style=\"font-weight:bold;\">Ajax request has failed.</p>";
972
                        $("#notesaved").html(message);
973
                    })
974
                    .always(function() {
975
                        $("#notesaved").show();
976
                    });
977
                });
978
            [% END %]
979
886
            $( ".suspend-until" ).datepicker({ minDate: 1 }); // Require that "until date" be in the future
980
            $( ".suspend-until" ).datepicker({ minDate: 1 }); // Require that "until date" be in the future
887
        });
981
        });
888
        //]]>
982
        //]]>
(-)a/opac/opac-issue-note.pl (+81 lines)
Line 0 Link Here
1
#!/usr/bin/perl
2
3
# Copyright 2016 Aleisha Amohia <aleisha@catalyst.net.nz>
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it
8
# under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Koha is distributed in the hope that it will be useful, but
13
# WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20
use Modern::Perl;
21
22
use strict;
23
use warnings;
24
25
use CGI qw ( -utf8 );
26
use C4::Koha;
27
use C4::Context;
28
use C4::Scrubber;
29
use C4::Members;
30
use C4::Output;
31
use C4::Auth;
32
use C4::Biblio;
33
use Koha::Issue;
34
use Koha::Issues;
35
36
my $query = new CGI;
37
38
my ( $template, $borrowernumber, $cookie ) = get_template_and_user(
39
    {
40
        template_name   => "opac-issue-note.tt",
41
        query           => $query,
42
        type            => "opac",
43
        authnotrequired => 0,
44
        debug           => 1,
45
    }
46
);
47
48
my $member = C4::Members::GetMember( borrowernumber => $borrowernumber );
49
$template->param(
50
    firstname      => $member->{'firstname'},
51
    surname        => $member->{'surname'},
52
    borrowernumber => $borrowernumber,
53
);
54
55
my $issue_id = $query->param('issue_id');
56
my $issue = Koha::Issue::GetIssue({ issue_id => $issue_id });
57
my $itemnumber = $issue->{'itemnumber'};
58
my $biblio = GetBiblioFromItemNumber($itemnumber);
59
$template->param(
60
    issue_id   => $issue_id,
61
    title      => $biblio->{'title'},
62
    author     => $biblio->{'author'},
63
    note       => $issue->{'note'},
64
    itemnumber => $issue->{'itemnumber'},
65
);
66
67
my $action = $query->param('action') || "";
68
if ( $action eq 'issuenote' && C4::Context->preference('AllowIssueNotes') ) {
69
    my $note = $query->param('note');
70
    my $scrubber = C4::Scrubber->new();
71
    my $clean_note = $scrubber->scrub($note);
72
    if ( Koha::Issue::SetIssueNote($issue_id, $clean_note) ) {
73
        if ($clean_note) { # only send email if note not empty
74
            my $branch = Koha::Libraries->find( $issue->{branchcode} );
75
            Koha::Issue::SendIssueNote($biblio, $member, $branch);
76
        }
77
    }
78
    print $query->redirect("/cgi-bin/koha/opac-user.pl");
79
}
80
81
output_html_with_http_headers $query, $cookie, $template->output, undef, { force_no_caching => 1 };
(-)a/opac/opac-user.pl (+3 lines)
Lines 33-38 use C4::Output; Link Here
33
use C4::Biblio;
33
use C4::Biblio;
34
use C4::Items;
34
use C4::Items;
35
use C4::Letters;
35
use C4::Letters;
36
use Koha::Libraries;
36
use Koha::DateUtils;
37
use Koha::DateUtils;
37
use Koha::Holds;
38
use Koha::Holds;
38
use Koha::Database;
39
use Koha::Database;
Lines 260-265 if ($issues){ Link Here
260
}
261
}
261
my $overduesblockrenewing = C4::Context->preference('OverduesBlockRenewing');
262
my $overduesblockrenewing = C4::Context->preference('OverduesBlockRenewing');
262
$canrenew = 0 if ($overduesblockrenewing ne 'allow' and $overdues_count == $count);
263
$canrenew = 0 if ($overduesblockrenewing ne 'allow' and $overdues_count == $count);
264
265
$template->param( AllowIssueNotes => C4::Context->preference('AllowIssueNotes') );
263
$template->param( ISSUES       => \@issuedat );
266
$template->param( ISSUES       => \@issuedat );
264
$template->param( issues_count => $count );
267
$template->param( issues_count => $count );
265
$template->param( canrenew     => $canrenew );
268
$template->param( canrenew     => $canrenew );
(-)a/opac/svc/patron_notes (+109 lines)
Line 0 Link Here
1
#!/usr/bin/perl
2
3
# This file is part of Koha.
4
#
5
# Copyright 2014 BibLibre
6
#
7
# Koha is free software; you can redistribute it and/or modify it
8
# under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Koha is distributed in the hope that it will be useful, but
13
# WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20
use Modern::Perl;
21
22
use C4::Service;
23
use C4::Auth qw /check_cookie_auth/;
24
use C4::Letters qw( GetLetters );
25
use CGI::Cookie; # need to check cookies before having CGI parse the POST request
26
use C4::Output qw(:DEFAULT :ajax);
27
use C4::Scrubber;
28
use C4::Circulation;
29
use C4::Members;
30
use C4::Biblio;
31
use Koha::Issue;
32
33
=head1 NAME
34
35
svc/patron_notes - Web service for setting patron notes on items
36
37
=head1 DESCRIPTION
38
39
=cut
40
41
sub ajax_auth_cgi {     # returns CGI object
42
    my $needed_flags = shift;
43
    my %cookies = fetch CGI::Cookie;
44
    my $input = CGI->new;
45
    my $sessid = $cookies{'CGISESSID'}->value;
46
    my ($auth_status, $auth_sessid) = check_cookie_auth($sessid, $needed_flags);
47
    if ($auth_status ne "ok") {
48
        output_with_http_headers $input, undef,
49
        "window.alert('Your CGI session cookie ($sessid) is not current.  " .
50
        "Please refresh the page and try again.');\n", 'js';
51
        exit 0;
52
    }
53
    return $input;
54
}
55
56
# AJAX requests
57
my $is_ajax = is_ajax();
58
my $query = ($is_ajax) ? &ajax_auth_cgi({}) : CGI->new();
59
if ($is_ajax) {
60
    my $action = $query->param('action');
61
62
    # Issue Note
63
    if ( $action eq 'issuenote' && C4::Context->preference('AllowIssueNotes') ) {
64
        my $scrubber = C4::Scrubber->new();
65
        my $note = $query->param('note');
66
        my $issue_id = $query->param('issue_id');
67
        my $clean_note = $scrubber->scrub($note);
68
        my $status = "saved";
69
        my $error = "";
70
        my ($member, $issue);
71
72
        my ( $template, $borrowernumber, $cookie ) = C4::Auth::get_template_and_user({
73
            template_name   => "opac-user.tt",
74
            query           => $query,
75
            type            => "opac",
76
            authnotrequired => 1,
77
        });
78
79
        # verify issue_id
80
        if ( $issue_id =~ /\d+/ ) {
81
            $member = GetMember(borrowernumber => $borrowernumber);
82
            $issue = Koha::Issue::GetIssue({issue_id => $issue_id});
83
            if ( $issue->{'borrowernumber'} != $borrowernumber ) {
84
                $status = "fail";
85
                $error = "Invalid issue id!";
86
            }
87
        } else {
88
            $status = "fail";
89
            $error = "Invalid issue id!";
90
        }
91
92
        if ( (not $error) && SetIssueNote($issue_id, $clean_note) ) {
93
            if($clean_note) { # only send email if note not empty
94
                my $branch = Koha::Libraries->find( $issue->{branchcode} );
95
                my $biblio = GetBiblioFromItemNumber($issue->{'itemnumber'});
96
                SendIssueNote($biblio, $member, $branch);
97
            } else { # note empty, i.e removed
98
                $status = "removed";
99
            }
100
        } else {
101
            $status = "fail";
102
            $error = "Perhaps the item has already been checked in?";
103
        }
104
105
        my $response = "{\"status\": \"$status\", \"note\": \"$clean_note\", \"issue_id\": \"$issue_id\", \"error\": \"$error\"}";
106
        output_with_http_headers($query, undef, $response, 'js');
107
        exit;
108
    } # END Issue Note
109
}
(-)a/svc/checkin (-1 / +4 lines)
Lines 26-31 use C4::Circulation; Link Here
26
use C4::Items qw(GetBarcodeFromItemnumber GetItem ModItem);
26
use C4::Items qw(GetBarcodeFromItemnumber GetItem ModItem);
27
use C4::Context;
27
use C4::Context;
28
use C4::Auth qw(check_cookie_auth);
28
use C4::Auth qw(check_cookie_auth);
29
use Koha::Issue;
29
30
30
my $input = new CGI;
31
my $input = new CGI;
31
32
Lines 72-77 if ( C4::Context->preference("ReturnToShelvingCart") ) { Link Here
72
    ModItem( $item, $item->{'biblionumber'}, $item->{'itemnumber'} );
73
    ModItem( $item, $item->{'biblionumber'}, $item->{'itemnumber'} );
73
}
74
}
74
75
76
my $patronnote = GetPatronNote($itemnumber);
77
$data->{patronnote} = $patronnote;
78
75
( $data->{returned} ) = AddReturn( $barcode, $branchcode, $exempt_fine );
79
( $data->{returned} ) = AddReturn( $barcode, $branchcode, $exempt_fine );
76
80
77
print to_json($data);
81
print to_json($data);
78
- 

Return to bug 14224