@@ -, +, @@ --- Koha/Schema/Result/Issue.pm | 11 +- .../bug-17698_add-noteseen-column-to-issues.sql | 1 + ...-17698_add-permission-to-manage-issue-notes.sql | 1 + installer/data/mysql/kohastructure.sql | 1 + installer/data/mysql/userpermissions.sql | 1 + issue_notes/issue-notes.pl | 93 +++++----------- .../prog/en/modules/circ/circulation-home.tt | 2 +- .../intranet-tmpl/prog/en/modules/intranet-main.tt | 2 +- .../prog/en/modules/issue_notes/issue-notes.tt | 122 +++++++++++++++++++-- opac/opac-issue-note.pl | 2 +- opac/svc/patron_notes | 2 +- svc/issue_notes | 73 ++++++++++++ 12 files changed, 227 insertions(+), 84 deletions(-) create mode 100644 installer/data/mysql/atomicupdate/bug-17698_add-permission-to-manage-issue-notes.sql create mode 100755 svc/issue_notes --- a/Koha/Schema/Result/Issue.pm +++ a/Koha/Schema/Result/Issue.pm @@ -112,6 +112,11 @@ __PACKAGE__->table("issues"); datetime_undef_if_invalid: 1 is_nullable: 1 +=head2 noteseen + + data_type: 'integer' + is_nullable: 1 + =cut __PACKAGE__->add_columns( @@ -170,6 +175,8 @@ __PACKAGE__->add_columns( datetime_undef_if_invalid => 1, is_nullable => 1, }, + "noteseen", + { data_type => "integer", is_nullable => 1 }, ); =head1 PRIMARY KEY @@ -241,8 +248,8 @@ __PACKAGE__->belongs_to( ); -# Created by DBIx::Class::Schema::Loader v0.07042 @ 2016-12-01 02:20:55 -# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:a7FCuypwxtuE6oJjEnRJRg +# Created by DBIx::Class::Schema::Loader v0.07042 @ 2016-12-12 02:41:09 +# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:ZF/YAX9BT1WrgCLUsXSqXQ __PACKAGE__->belongs_to( "borrower", --- a/installer/data/mysql/atomicupdate/bug-17698_add-noteseen-column-to-issues.sql +++ a/installer/data/mysql/atomicupdate/bug-17698_add-noteseen-column-to-issues.sql @@ -1, +1,2 @@ ALTER IGNORE TABLE issues ADD `noteseen` int(1) default NULL; +ALTER IGNORE TABLE old_issues ADD `noteseen` int(1) default NULL; --- a/installer/data/mysql/atomicupdate/bug-17698_add-permission-to-manage-issue-notes.sql +++ a/installer/data/mysql/atomicupdate/bug-17698_add-permission-to-manage-issue-notes.sql @@ -0,0 +1, @@ +INSERT INTO permissions (module_bit, code, description) VALUES ( 1, 'manage_issue_notes', 'Mark issue notes as seen/not seen'); --- a/installer/data/mysql/kohastructure.sql +++ a/installer/data/mysql/kohastructure.sql @@ -1808,6 +1808,7 @@ CREATE TABLE `old_issues` ( -- lists items that were checked out and have been r `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) + `noteseen` int(1) default NULL, -- describes whether issue note has been seen 1, not been seen 0 or doesn't exist null PRIMARY KEY (`issue_id`), KEY `old_issuesborridx` (`borrowernumber`), KEY `old_issuesitemidx` (`itemnumber`), --- a/installer/data/mysql/userpermissions.sql +++ a/installer/data/mysql/userpermissions.sql @@ -5,6 +5,7 @@ INSERT INTO permissions (module_bit, code, description) VALUES ( 1, 'force_checkout', 'Force checkout if a limitation exists'), ( 1, 'manage_restrictions', 'Manage restrictions for accounts'), ( 1, 'self_checkout', 'Perform self checkout at the OPAC. It should be used for the patron matching the AutoSelfCheckID'), + ( 1, 'manage_issue_notes', 'Mark issue notes as seen/not seen'), ( 3, 'parameters_remaining_permissions', 'Remaining system parameters permissions'), ( 3, 'manage_circ_rules', 'Manage circulation rules'), ( 6, 'place_holds', 'Place holds for patrons'), --- a/issue_notes/issue-notes.pl +++ a/issue_notes/issue-notes.pl @@ -19,41 +19,13 @@ use Modern::Perl; -use strict; -use warnings; - use CGI qw ( -utf8 ); -use CGI::Cookie; # need to check cookies before having CGI parse the POST request use C4::Koha; use C4::Context; -use C4::Biblio; -use C4::Output qw(:DEFAULT :ajax); +use C4::Output; use C4::Auth; - -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; -} - -if (is_ajax()) { - my $input = &ajax_auth_cgi({}) || CGI->new(); - my ($note, $js_reply); - if ($note = $input->param('seen')) { - $js_reply = ( markseen($note) ? 'success' : 'failure') . "_seen('$note');\n"; - } - output_with_http_headers $input, undef, $js_reply, 'js'; - exit; -} +use C4::Biblio; +use Koha::Issues; my $query = new CGI; @@ -68,46 +40,35 @@ my ( $template, $loggedinuser, $cookie ) = get_template_and_user( } ); -my @notes = get_notes(); -my $pending_notes = Koha::Issues->search({ noteseen => 0 }); -#my $borrower = C4::Members::GetMember( borrowernumber => $notes->{'borrowernumber'} ); -#my $itemnumber = $notes->{'itemnumber'}; -#my $biblio = GetBiblioFromItemNumber($itemnumber); +my $schema = Koha::Database->new()->schema(); +my @notes = $schema->resultset('Issue')->search({ 'me.note' => { '!=', undef } }, { prefetch => [ 'borrower', { item => 'biblionumber' } ] }); $template->param( - notes => @notes, - pending => $pending_notes, -# title => $biblio->{'title'}, -# issuenote => $notes->{'note'}, -# barcode => $biblio->{'barcode'}, -# borrower => $borrower, -# date => $notes->{'notedate'}, + notes => \@notes, ); +my $action; +foreach (qw( seen notseen )) { + $action = $_ if ( $query->param("mark_selected-$_") ); +} +$action ||= 'none'; + +my @issue_ids = $query->multi_param('issue_ids'); -sub get_notes { - my $dbh = C4::Context->dbh; - my $q = "SELECT issues.borrowernumber AS borrowernumber, - issues.itemnumber AS itemnumber, - issues.note AS note, - issues.notedate AS notedate, - issues.noteseen AS noteseen, - borrowers.firstname AS firstname, - borrowers.surname AS surname, - items.barcode AS barcode, - biblio.title AS title, - biblio.author AS author - FROM issues - JOIN borrowers - ON issues.borrowernumber = borrowers.borrowernumber - JOIN items - ON issues.itemnumber = items.itemnumber - JOIN biblio - ON items.biblionumber = biblio.biblionumber - WHERE issues.note IS NOT NULL"; - my $sth = $dbh->prepare($q); - $sth->execute(); - return $sth->fetchall_arrayref({}); +if ( $action eq 'seen' ) { + foreach my $issue_id ( @issue_ids ) { + my $issue = Koha::Issues->find($issue_id); + $issue->set({ noteseen => 1 })->store; + } +} elsif ( $action eq 'notseen' ) { + foreach my $issue_id ( @issue_ids ) { + my $issue = Koha::Issues->find($issue_id); + $issue->set({ noteseen => 0 })->store; + } } +$template->param( + selected_count => scalar(@issue_ids), + action => $action, +); output_html_with_http_headers $query, $cookie, $template->output, undef, { force_no_caching => 1 }; --- a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation-home.tt +++ a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation-home.tt @@ -30,7 +30,7 @@
  • Fast cataloging
  • [% END %] [% END %] -
  • Issue notes
  • + [% IF ( CAN_user_circulate_manage_issue_notes ) %]
  • Issue notes
  • [% END %] --- a/koha-tmpl/intranet-tmpl/prog/en/modules/intranet-main.tt +++ a/koha-tmpl/intranet-tmpl/prog/en/modules/intranet-main.tt @@ -162,7 +162,7 @@ [% END %] - [% IF Koha.Preference('AllowIssueNotes') && pending_issue_notes %] + [% IF Koha.Preference('AllowIssueNotes') && CAN_user_circulate_manage_issue_notes && pending_issue_notes %]
    Issue notes pending: [% pending_issue_notes %] --- a/koha-tmpl/intranet-tmpl/prog/en/modules/issue_notes/issue-notes.tt +++ a/koha-tmpl/intranet-tmpl/prog/en/modules/issue_notes/issue-notes.tt @@ -2,10 +2,66 @@ [% USE KohaDates %] [% USE Branches %] [% INCLUDE 'doc-head-open.inc' %] -Home › Circulation › Issue Notes › Review Issue Notes +Home › Circulation › Issue Notes [% INCLUDE 'doc-head-close.inc' %] [% INCLUDE 'datatables.inc' %] + [% INCLUDE 'calendar.inc' %] @@ -14,41 +70,83 @@ -
    +

    Issue notes

    +
    + + [% IF ( selected_count ) %] +
    + [% IF ( action == 'seen' ) %] + [% selected_count %] note(s) marked as seen. + [% ELSIF ( action == 'notseen' ) %] + [% selected_count %] note(s) marked as not seen. + [% ELSE %] + Failed to change the status of [% selected_count %] item(s). + [% END %] +
    + Back to issue notes + [% ELSE %] + [% IF ( notes ) %] + +
    + Select all | Clear all +
    + +
    + + + - - + - [% FOREACH note in notes %] + [% FOREACH note IN notes %] + - - - - - + + + + + [% END %]
      NoteStatus TitleBarcode Date Set bySeenActions
    [% note.note %][% note.title %][% note.barcode %][% note.date %][% note.firstname %] [% note.surname %] ([% note.borrowernumber %])[% IF ( pending ) %][% ELSE %][% END %][% IF ( note.noteseen == 0 ) %] + Not seen + [% ELSIF ( note.noteseen == 1 ) %] + Seen + [% END %][% note.item.biblionumber.title %] - [% note.item.biblionumber.author %] ([% note.item.barcode %])[% note.notedate | $KohaDates %][% note.borrower.firstname %] [% note.borrower.surname %] ([% note.borrower.cardnumber %])[% IF ( note.noteseen == 1 ) %] + + [% ELSIF ( note.noteseen == 0 ) %] + + [% END %]
    - [% END %] + +
    + + +
    + +
    + + [% END %] + + [% END %]
    --- a/opac/opac-issue-note.pl +++ a/opac/opac-issue-note.pl @@ -67,7 +67,7 @@ if ( $action eq 'issuenote' && C4::Context->preference('AllowIssueNotes') ) { my $note = $query->param('note'); my $scrubber = C4::Scrubber->new(); my $clean_note = $scrubber->scrub($note); - if ( $issue->set({ notedate => dt_from_string(), note => $clean_note })->store ) { + if ( $issue->set({ notedate => dt_from_string(), note => $clean_note, noteseen => 0 })->store ) { if ($clean_note) { # only send email if note not empty my $branch = Koha::Libraries->find( $issue->branchcode ); my $letter = C4::Letters::GetPreparedLetter ( --- a/opac/svc/patron_notes +++ a/opac/svc/patron_notes @@ -79,7 +79,7 @@ if ($is_ajax) { $error = "Invalid issue id!"; } - if ( (not $error) && $issue->set({ notedate => dt_from_string(), note => $clean_note })->store ) { + if ( (not $error) && $issue->set({ notedate => dt_from_string(), note => $clean_note, noteseen => 0 })->store ) { if($clean_note) { # only send email if note not empty my $branch = Koha::Libraries->find( $issue->branchcode ); my $biblio = GetBiblioFromItemNumber($issue->itemnumber); --- a/svc/issue_notes +++ a/svc/issue_notes @@ -0,0 +1,73 @@ +#!/usr/bin/perl + +# This file is part of Koha. +# +# Copyright 2017 Aleisha Amohia +# +# Koha is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# Koha is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Koha; if not, see . + +use Modern::Perl; + +use C4::Service; +use C4::Auth qw /check_cookie_auth/; +use CGI; +use C4::Output qw(:DEFAULT :ajax); +use Koha::Issues; + +=head1 NAME + +svc/issue_notes - Web service for managing patron notes set on issues + +=head1 DESCRIPTION + +=cut + +# AJAX requests +my $is_ajax = is_ajax(); +my $query = new CGI; +my ( $auth_status, $sessionID ) = check_cookie_auth( $query->cookie('CGISESSID'), {} ); +if ( $auth_status ne "ok" ) { + exit 0; +} +if ($is_ajax) { + my $issue_id = $query->param('issue_id'); + my $issue = Koha::Issues->find($issue_id); + my $action = $query->param('action'); + my $status = 'success'; + if ($action eq 'seen'){ + $issue->set({ noteseen => 1 })->store; + if ( $issue->noteseen != 1 ) { + $status = 'failure'; + } + } elsif ($action eq 'notseen'){ + $issue->set({ noteseen => 0 })->store; + if ( $issue->noteseen != 0 ) { + $status = 'failure'; + } + } + my $response = "{\"status\": \"$status\"}"; + output_with_http_headers $query, undef, $response, 'js'; + exit; +} + +my ( $template, $borrowernumber, $cookie ) = get_template_and_user({ + template_name => "issue_notes/issue-notes.tt", + query => $query, + type => "intranet", + debug => 1, + authnotrequired => 0, + flagsrequired => { circulation => 'manage_issue_notes' }, +}); + + --