@@ -, +, @@
checked out. Hit ENTER to save/send.
specified for the branch which the item was checked out from.
---
C4/Circulation.pm | 43 +++++++-
circ/returns.pl | 3 +
.../bug_14224-add_new_issue_columns.sql | 2 +
installer/data/mysql/kohastructure.sql | 2 +
.../intranet-tmpl/prog/en/modules/circ/returns.tt | 10 ++
.../bootstrap/en/modules/opac-sendissuenote.tt | 21 ++++
.../opac-tmpl/bootstrap/en/modules/opac-user.tt | 45 ++++++++
opac/opac-user.pl | 120 ++++++++++++++++++++-
8 files changed, 242 insertions(+), 4 deletions(-)
create mode 100644 installer/data/mysql/atomicupdate/bug_14224-add_new_issue_columns.sql
create mode 100644 koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-sendissuenote.tt
--- a/C4/Circulation.pm
+++ a/C4/Circulation.pm
@@ -92,6 +92,7 @@ BEGIN {
&GetBranchItemRule
&GetBiblioIssues
&GetOpenIssue
+ &SetIssueNote
&AnonymiseIssueHistory
&CheckIfIssuedToPatron
&IsItemIssued
@@ -2450,7 +2451,7 @@ sub GetOpenIssue {
=head2 GetIssues
$issues = GetIssues({}); # return all issues!
- $issues = GetIssues({ borrowernumber => $borrowernumber, biblionumber => $biblionumber });
+ $issues = GetIssues({ borrowernumber => $borrowernumber, biblionumber => $biblionumber, issue_id => $issue_id });
Returns all pending issues that match given criteria.
Returns a arrayref or undef if an error occurs.
@@ -2465,6 +2466,8 @@ Allowed criteria are:
=item * itemnumber
+=item * issue_id
+
=back
=cut
@@ -2474,7 +2477,7 @@ sub GetIssues {
# Build filters
my @filters;
- my @allowed = qw(borrowernumber biblionumber itemnumber);
+ my @allowed = qw(borrowernumber biblionumber itemnumber issue_id);
foreach (@allowed) {
if (defined $criteria->{$_}) {
push @filters, {
@@ -3968,6 +3971,42 @@ sub GetPendingOnSiteCheckouts {
|, { Slice => {} } );
}
+=head2 SetIssueNote
+
+ &SetIssueNote($issue_id, $note);
+
+Sets a note to the issuenotes table for the given issue.
+
+=over 4
+
+=item C<$issue_id> is the id of the issue for which to set the note
+
+=item C<$note> is the note to set
+
+=back
+
+Returns:
+ True on success
+ False on failure
+
+=cut
+
+sub SetIssueNote {
+ my ( $issue_id, $note) = @_;
+
+ my $dbh = C4::Context->dbh;
+
+ if ( ! ( $issue_id && $note ) or not $issue_id =~ /\d+/) {
+ return;
+ }
+
+ my $query = "UPDATE issues SET notedate=NOW(),note=? WHERE issue_id=?";
+ my $sth = $dbh->prepare($query);
+ $sth->execute( $note, $issue_id );
+ return 1;
+}
+
+
__END__
=head1 AUTHOR
--- a/circ/returns.pl
+++ a/circ/returns.pl
@@ -269,6 +269,8 @@ if ($barcode) {
my $hbr = GetBranchItemRule($biblio->{'homebranch'}, $itemtype)->{'returnbranch'} || "homebranch";
my $returnbranch = $biblio->{$hbr} ;
+ my $issue = GetItemIssue($itemnumber);
+
$template->param(
title => $biblio->{'title'},
homebranch => $biblio->{'homebranch'},
@@ -281,6 +283,7 @@ if ($barcode) {
biblionumber => $biblio->{'biblionumber'},
borrower => $borrower,
additional_materials => $biblio->{'materials'},
+ issue => $issue,
);
my %input = (
--- a/installer/data/mysql/atomicupdate/bug_14224-add_new_issue_columns.sql
+++ a/installer/data/mysql/atomicupdate/bug_14224-add_new_issue_columns.sql
@@ -0,0 +1,2 @@
+ALTER TABLE issues ADD COLUMN `note` mediumtext default NULL; -- issue note text
+ALTER TABLE issues ADD COLUMN `notedate` datetime default NULL; -- datetime of issue note (yyyy-mm-dd hh:mm::ss)
--- a/installer/data/mysql/kohastructure.sql
+++ a/installer/data/mysql/kohastructure.sql
@@ -1156,6 +1156,8 @@ CREATE TABLE `issues` ( -- information related to check outs or issues
`timestamp` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP, -- the date and time this record was last touched
`issuedate` datetime default NULL, -- date the item was checked out or issued
`onsite_checkout` int(1) NOT NULL default 0, -- in house use flag
+ `note` mediumtext default NULL, -- issue note text
+ `notedate` datetime default NULL, -- datetime of issue note (yyyy-mm-dd hh:mm::ss)
PRIMARY KEY (`issue_id`),
KEY `issuesborridx` (`borrowernumber`),
KEY `itemnumber_idx` (`itemnumber`),
--- a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/returns.tt
+++ a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/returns.tt
@@ -123,6 +123,16 @@ $(document).ready(function () {
This item is part of a rotating collection and needs to be transferred to [% collectionBranch %]
[% END %]
+
+[% IF ( issue.note) %]
+
+
Patron note
+
[% issue.notedate %]
+
[% title |html %] [% author %]
+
[% issue.note %]
+
+[% END %]
+
[% IF ( fines ) %]
--- a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-sendissuenote.tt
+++ a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-sendissuenote.tt
@@ -0,0 +1,21 @@
+
+Issue note for [% title %] [% author %]
+
+
+[% USE HtmlToText %]
+
+
+[% FILTER html2text %]
+ Hi,
+ [% MEMBER.firstname %] [% MEMBER.surname %] sent you the following note related to the check out of
+
[% title %] [% author %].
+[% END %]
+
+
+
+
+[% FILTER html2text %]
+ [% note %]
+[% END %]
+
+
--- a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-user.tt
+++ a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-user.tt
@@ -98,6 +98,8 @@
[% END # / IF patron_flagged %]
+
+
[% SET OPACMySummaryNote = Koha.Preference('OPACMySummaryNote') %]
[% IF OPACMySummaryNote %][% OPACMySummaryNote %][% END %]
@@ -142,6 +144,7 @@
[% IF ( OPACMySummaryHTML ) %]
Links |
[% END %]
+ Note |
@@ -254,6 +257,9 @@
[% IF ( OPACMySummaryHTML ) %]
[% ISSUE.MySummaryHTML %] |
[% END %]
+
+
+ |
[% END # /FOREACH ISSUES %]
@@ -732,6 +738,45 @@
[% END %]
[% END %]
+ $("input[name='note']").keyup(function(e){
+ var self = $(this);
+ if(e.which == 13) {
+ e.preventDefault();
+ if(!self.val()) return;
+
+ var ajaxData = {
+ 'issue_id': $(this).data('issue_id'),
+ 'note': self.val()
+ };
+
+ $.ajax({
+ url: '/cgi-bin/koha/opac-user.pl',
+ type: 'POST',
+ dataType: 'json',
+ data: ajaxData,
+ })
+ .done(function(data) {
+ if(data.status == 'success') {
+ $("#notesaved").removeClass("alert-error");
+ $("#notesaved").addClass("alert-info");
+ $("#notesaved").html("Note saved and sent to library.");
+ } else {
+ $("#notesaved").removeClass("alert-info");
+ $("#notesaved").addClass("alert-error");
+ $("#notesaved").html(data.error);
+ }
+ })
+ .fail(function(data) {
+ $("#notesaved").removeClass("alert-info");
+ $("#notesaved").addClass("alert-error");
+ $("#notesaved").html("Ajax request failed. Could not save note.");
+ })
+ .always(function() {
+ $("#notesaved").show();
+ });
+ }
+ });
+
$( ".suspend-until" ).datepicker({ minDate: 1 }); // Require that "until date" be in the future
});
//]]>
--- a/opac/opac-user.pl
+++ a/opac/opac-user.pl
@@ -22,18 +22,24 @@ use strict;
use CGI qw ( -utf8 );
-use C4::Auth;
+use Mail::Sendmail;
+use MIME::QuotedPrint;
+use Carp;
+use C4::Auth qw(:DEFAULT check_cookie_auth);
use C4::Koha;
use C4::Circulation;
use C4::Reserves;
use C4::Members;
use C4::Members::AttributeTypes;
use C4::Members::Attributes qw/GetBorrowerAttributeValue/;
-use C4::Output;
+use CGI::Cookie; # need to check cookies before having CGI parse the POST request
+use C4::Output qw(:DEFAULT :ajax);
+use C4::Scrubber;
use C4::Biblio;
use C4::Items;
use C4::Letters;
use C4::Branch; # GetBranches
+use Koha::Email;
use Koha::DateUtils;
use Koha::Borrower::Debarments qw(IsDebarred);
@@ -54,6 +60,116 @@ BEGIN {
}
}
+sub ajax_auth_cgi { # returns CGI object
+ my $needed_flags = shift;
+ my %cookies = fetch CGI::Cookie;
+ my $input = CGI->new;
+ my $sessid = $cookies{'CGISESSID'}->value;
+ my ($auth_status, $auth_sessid) = check_cookie_auth($sessid, $needed_flags);
+ if ($auth_status ne "ok") {
+ output_with_http_headers $input, undef,
+ "window.alert('Your CGI session cookie ($sessid) is not current. " .
+ "Please refresh the page and try again.');\n", 'js';
+ exit 0;
+ }
+ return $input;
+}
+
+my $is_ajax = is_ajax();
+my $query = ($is_ajax) ? &ajax_auth_cgi({}) : CGI->new();
+if ($is_ajax) {
+ my $scrubber = C4::Scrubber->new();
+ my $note = $query->param('note');
+ my $issue_id = $query->param('issue_id');
+ my $clean_note = $scrubber->scrub($note);
+ my $status = "success";
+ my $error = "";
+ my ($error, $member, $issue);
+
+ my ( $template, $borrowernumber, $cookie ) = get_template_and_user(
+ {
+ template_name => "opac-sendissuenote.tt",
+ query => $query,
+ type => "opac",
+ authnotrequired => 1,
+ }
+ );
+
+ # verify issue_id
+ if ( $issue_id =~ /\d+/ ) {
+ $member = GetMember(borrowernumber => $borrowernumber);
+ ($issue) = @{C4::Circulation::GetIssues({issue_id => $issue_id})};
+
+ if ( $issue->{'borrowernumber'} != $borrowernumber ) {
+ $status = "fail";
+ $error = "Invalid issue id!";
+ }
+ } else {
+ $status = "fail";
+ $error = "Invalid issue id!";
+ }
+
+ if ( (not $error) && SetIssueNote($issue_id, $clean_note) ) {
+ my $branch = GetBranchDetail($issue->{'branchcode'});
+
+ if ( $branch->{'branchemail'} ) {
+ my $biblio = GetBiblioFromItemNumber($issue->{'itemnumber'});
+ my $message = Koha::Email->new();
+ my %mail = $message->create_message_headers();
+
+ $template->param(
+ author => $biblio->{'author'},
+ title => $biblio->{'title'},
+ MEMBER => $member,
+ note => $clean_note,
+ );
+
+ # Getting template result
+ my $template_res = $template->output();
+ my $body;
+
+ # Analysing information and getting mail properties
+ if ( $template_res =~ /(.*)/s ) {
+ $mail{subject} = $1;
+ $mail{subject} =~ s|\n?(.*)\n?|$1|;
+ }
+ else { $mail{'subject'} = "no subject"; }
+ $mail{subject} = Encode::encode("UTF-8", $mail{subject});
+
+ my $email_header = "";
+ if ( $template_res =~ /(.*)/s ) {
+ $email_header = $1;
+ $email_header =~ s|\n?(.*)\n?|$1|;
+ $email_header = encode_qp(Encode::encode("UTF-8", $email_header));
+ }
+
+ if ( $template_res =~ /(.*)/s ) {
+ $body = $1;
+ $body =~ s|\n?(.*)\n?|$1|;
+ $body = encode_qp(Encode::encode("UTF-8", $body));
+ }
+
+ $mail{to} = $branch->{'branchemail'};
+ $mail{from} = $member->{'email'} || ($branch->{'branchemail'}=~s/^.+@/noreply@/ && $branch->{'branchemail'});
+ $mail{body} = $email_header . $body;
+
+ unless ( sendmail(%mail) ) {
+ $status = "fail";
+ $error = "Could not send message to library. Message will still show at check in.";
+ carp "Error sending mail: $Mail::Sendmail::error \n";
+ }
+ }
+ } else {
+ $status = "fail";
+ $error = "Could not save note. Invalid issue id or empty note.";
+ }
+
+ my $response = "{\"status\": \"$status\", \"note\": \"$clean_note\", \"issue_id\": \"$issue_id\", \"error\": \"$error\"}";
+ output_with_http_headers($query, undef, $response, 'js');
+ exit;
+}
+
+
my ( $template, $borrowernumber, $cookie ) = get_template_and_user(
{
template_name => "opac-user.tt",
--