From 050ea1b9ff151a7b15d0b7d62c9aa55eee8d2e56 Mon Sep 17 00:00:00 2001 From: Jonathan Druart Date: Wed, 8 Jan 2014 18:35:39 +0100 Subject: [PATCH] Bug 8007: Discharge management This patch is the main patch. It adds new package and files for the new pages (opac-discharge, members/discharge and members/discharges). At the intranet, it is now possible to generate a discharge for a patron. At the opac, a patron can request a discharge and a discharge if it has been validated by a librarian. Requirements: aptitude install python-pisa New sysprefs: - useDischarge: Allows librarians to discharge borrowers and borrowers to request a discharge New letter with a letter_code DISCHARGE. Test plan: - Switch on the syspref useDischarge. - Verify a new tab appears in the patron page (intranet and opac). - Verify the discharge cannot be generated if the patron has issues. - Verify the patron can request a discharge from it's opac area. - The request appears on the main page (intranet). - Generate the discharge from the intranet. - Try to download it (from the opac and the intranet). --- Koha/DataObject/Discharge.pm | 86 ++++++++++ Koha/Service/Borrower/Discharge.pm | 169 ++++++++++++++++++++ .../prog/en/modules/members/discharge.tt | 41 +++++ .../prog/en/modules/members/discharges.tt | 41 +++++ .../opac-tmpl/prog/en/modules/opac-discharge.tt | 51 ++++++ members/discharge.pl | 123 ++++++++++++++ members/discharges.pl | 59 +++++++ opac/opac-discharge.pl | 107 +++++++++++++ 8 files changed, 677 insertions(+) create mode 100644 Koha/DataObject/Discharge.pm create mode 100644 Koha/Service/Borrower/Discharge.pm create mode 100644 koha-tmpl/intranet-tmpl/prog/en/modules/members/discharge.tt create mode 100644 koha-tmpl/intranet-tmpl/prog/en/modules/members/discharges.tt create mode 100644 koha-tmpl/opac-tmpl/prog/en/modules/opac-discharge.tt create mode 100755 members/discharge.pl create mode 100755 members/discharges.pl create mode 100755 opac/opac-discharge.pl diff --git a/Koha/DataObject/Discharge.pm b/Koha/DataObject/Discharge.pm new file mode 100644 index 0000000..46ee23c --- /dev/null +++ b/Koha/DataObject/Discharge.pm @@ -0,0 +1,86 @@ +package Koha::DataObject::Discharge; + +use Modern::Perl; +use List::MoreUtils qw( uniq ); + +use Koha::Database; + +use C4::Members qw( GetMember ); + +use base qw( Class::Accessor ); +__PACKAGE__->mk_accessors(qw( borrowernumber needed validated )); + +my $rs = Koha::Database->new->schema->resultset('Discharge'); + +sub new { + my ( $class, $discharge ) = @_; + + my $self = $class->SUPER::new( + { + borrowernumber => $discharge->{borrowernumber}, + needed => $discharge->{needed}, + validated => $discharge->{validated}, + } + ); + + bless $self, $class; + return $self; +} + +sub insert { + my ($self) = @_; + return $rs->create( + { + borrower => $self->borrowernumber, + needed => $self->needed, + validated => $self->validated, + } + ); +} + +sub update { + my ($self) = @_; + return $rs->update( + { + borrower => $self->borrowernumber, + needed => $self->needed, + validated => $self->validated, + } + ); +} + +sub fetch { + my ($self) = @_; + my $data = $rs->single( { borrower => $self->borrowernumber } ); + $self->needed( $data->needed ); + $self->validated( $data->validated ); + return $self; +} + +sub search { + my ($params) = @_; + + my $values = $params; + my @joins; + for my $v ( keys %$values ) { + if ( $v eq 'branchcode' ) { + push @joins, 'borrower'; + } + } + + return $rs->search( $params, { join => [ uniq @joins ], } ); +} + +sub borrower { + my ($self) = @_; + + return $self->{borrower} + if exists $self->{borrower}; + + $self->{borrower} = + C4::Members::GetMember( borrowernumber => $self->borrowernumber ); + + return $self->{borrower}; +} + +1; diff --git a/Koha/Service/Borrower/Discharge.pm b/Koha/Service/Borrower/Discharge.pm new file mode 100644 index 0000000..ecb54c1 --- /dev/null +++ b/Koha/Service/Borrower/Discharge.pm @@ -0,0 +1,169 @@ +package Koha::Service::Borrower::Discharge; + +use Modern::Perl; +use CGI; +use File::Temp qw( :POSIX ); + +use C4::Members qw( GetPendingIssues ); +use C4::Reserves qw( GetReservesFromBorrowernumber CancelReserve ); + +use Koha::Database; +use Koha::DataObject::Discharge; +use Koha::DateUtils qw( dt_from_string output_pref ); + +sub count { + my ($params) = @_; + my $values = {}; + + if ( $params->{borrowernumber} ) { + $values->{borrower} = $params->{borrowernumber}; + } + if ( $params->{pending} ) { + $values->{needed} = { '!=', undef }; + $values->{validated} = undef; + } + elsif ( $params->{validated} ) { + $values->{validated} = { '!=', undef }; + } + + return Koha::DataObject::Discharge::search( { %$values } )->count; +} + +sub can_be_discharged { + my ($params) = @_; + + return unless $params->{borrowernumber}; + + my $issues = GetPendingIssues( $params->{borrowernumber} ); + + return 'has_issues', 0 + if @$issues; + + return 1; +} + +sub request { + my ($params) = @_; + + return + unless $params->{borrowernumber} + and + can_be_discharged( { borrowernumber => $params->{borrowernumber} } ); + + my $count = count($params); + + die +"This patron ($params->{borrowernumber}) has already asked for a discharge" + if $count; + + my $discharge = Koha::DataObject::Discharge->new( + { + borrowernumber => $params->{borrowernumber}, + needed => dt_from_string, + } + ); + + return $discharge->insert; +} + +sub discharge { + my ($params) = @_; + + my $borrowernumber = $params->{borrowernumber}; + return + unless $borrowernumber + and can_be_discharged( { borrowernumber => $borrowernumber } ); + + # Calcel reserves + my @reserves = GetReservesFromBorrowernumber($borrowernumber); + for my $reserve (@reserves) { + CancelReserve( { reserve_id => $reserve->{reserve_id} } ); + } + + # Debar the member + Koha::Borrower::Debarments::AddDebarment( + { + borrowernumber => $borrowernumber, + type => 'DISCHARGE' + } + ); + + # Generate the discharge + my $discharge = Koha::DataObject::Discharge->new( + { borrowernumber => $borrowernumber, } ); + + unless ( $discharge->fetch ) { + $discharge->insert; + } + + $discharge->validated(dt_from_string); + return $discharge->update; +} + +sub generate_as_pdf { + my ($params) = @_; + + return unless $params->{borrowernumber}; + + my $letter = C4::Letters::GetPreparedLetter( + module => 'members', + letter_code => 'DISCHARGE', + tables => { borrowers => $params->{borrowernumber}, }, + ); + + my $today = output_pref( dt_from_string() ); + $letter->{'title'} =~ s/<>/$today/g; + $letter->{'content'} =~ s/<>/$today/g; + + my $template = + C4::Templates::gettemplate( 'batch/print-notices.tt', 'intranet', new CGI, + ); + + $template->param( + stylesheet => C4::Context->preference("NoticeCSS"), + today => $today, + messages => [$letter], + ); + + my $html_path = tmpnam(); + open my $fh, '>', $html_path; + print $fh $template->output; + close $fh; + my $pdf_path = tmpnam(); + qx{xhtml2pdf $html_path $pdf_path}; + return $pdf_path; +} + +sub get_pendings { + my ($params) = @_; + my $branchcode = $params->{branchcode}; + my $borrowernumber = $params->{borrowernumber}; + my $rs = Koha::DataObject::Discharge::search( + { + needed => { '!=', undef }, + validated => undef, + ( defined $branchcode ? ( branchcode => $branchcode ) : () ), + ( + defined $borrowernumber + ? ( borrowernumber => $borrowernumber ) + : () + ), + } + ); + + my @discharges; + while ( my $discharge = $rs->next ) { + push @discharges, + Koha::DataObject::Discharge->new( + { + borrowernumber => $discharge->borrower->borrowernumber, + needed => $discharge->needed, + validated => $discharge->validated, + } + ); + } + + return \@discharges; +} + +1; diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/members/discharge.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/members/discharge.tt new file mode 100644 index 0000000..12a2516 --- /dev/null +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/members/discharge.tt @@ -0,0 +1,41 @@ +[% INCLUDE 'doc-head-open.inc' %] +Koha › Patrons › [% IF (unknowuser) %]Patron does not exist[% ELSE %]Discharge for [% firstname %] [% surname %] ([% cardnumber %])[% END %] +[% INCLUDE 'doc-head-close.inc' %] + + +[% INCLUDE 'header.inc' %] +[% INCLUDE 'patron-search.inc' %] + + + +
+
+
+
+
+

Discharge

+[% UNLESS can_be_discharged %] +

Cannot edit discharge: borrower has issues.

+[% ELSE %] + [% IF hasreserves %] +

Borrower has reserves: they will be canceled if the discharge is generated.

+ [% END %] +
+ + +
+[% END %] +
+ + +
+
+
+[% INCLUDE 'circ-menu.inc' %] +
+
+[% INCLUDE 'intranet-bottom.inc' %] diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/members/discharges.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/members/discharges.tt new file mode 100644 index 0000000..ae08aeb --- /dev/null +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/members/discharges.tt @@ -0,0 +1,41 @@ +[% INCLUDE 'doc-head-open.inc' %] +Koha › Patrons › Pending discharge requests +[% INCLUDE 'doc-head-close.inc' %] + + +[% INCLUDE 'header.inc' %] +[% INCLUDE 'patron-search.inc' %] + + + +
+
+
+ [% IF pending_discharges %] +

Pending discharge requests

+
+ + + + + + + + + [% FOR d IN pending_discharges %] + + + + + [% END %] + +
PatronAllow
[% d.borrower.surname %], [% d.borrower.firstname %]Allow
+
+ [% ELSE %] +
+

There are no pending discharge requests.

+
+ [% END %] +
+
+[% INCLUDE 'intranet-bottom.inc' %] diff --git a/koha-tmpl/opac-tmpl/prog/en/modules/opac-discharge.tt b/koha-tmpl/opac-tmpl/prog/en/modules/opac-discharge.tt new file mode 100644 index 0000000..a3b5120 --- /dev/null +++ b/koha-tmpl/opac-tmpl/prog/en/modules/opac-discharge.tt @@ -0,0 +1,51 @@ +[% INCLUDE 'doc-head-open.inc' %] +[% IF (LibraryNameTitle) %][% LibraryNameTitle %][% ELSE %]Koha Online[% END %] Catalog +[% INCLUDE 'doc-head-close.inc' %] + + +[% IF OpacNav or loggedinusername %] +
+[% ELSE %] +
+[% END %] +
+[% INCLUDE 'masthead.inc' %] + +
+
+
+
+

Discharge

+ [% IF generated %] + [% IF success %] +

Your discharge request has been sent. Your discharge will be available on this page within a few days.

+ [% ELSE %] +

Your discharge request could not be sent. Please retry later or contact an administrator.

+ [% END %] + [% ELSIF available %] + Get your discharge + [% ELSIF pending %] +

Your discharge will be available on this page within a few days.

+ [% ELSIF has_issues %] +

You cannot be discharged, you have issues. Please return items before asking for a discharge.

+ [% ELSE %] +

What is a discharge?

+

This document certifies that you have returned all borrowed items. It is sometimes asked during a file transfer from a school to another. The discharge is sent by us to your school. You will also find it available on your reader account.

+

Warning: This request is only valid if you are in good standing with the library. Once the application is made, you can not borrow library materials.

+ Ask for a discharge + [% END %] +
+
+
+
+ +[% IF ( OpacNav || loggedinusername ) %] +
+
+ [% INCLUDE 'navigation.inc' %] + [% INCLUDE 'usermenu.inc' %] +
+
+[% END %] +
+[% INCLUDE 'opac-bottom.inc' %] diff --git a/members/discharge.pl b/members/discharge.pl new file mode 100755 index 0000000..de84dee --- /dev/null +++ b/members/discharge.pl @@ -0,0 +1,123 @@ +#!/usr/bin/perl + +# This file is part of Koha. +# +# Copyright 2013 BibLibre +# +# 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 . + +=head1 NAME + +discharges.pl + +=head1 DESCRIPTION + +Allows librarian to edit and/or manage borrowers' discharges + +=cut + +use Modern::Perl; + +use CGI; +use C4::Auth; +use C4::Output; +use C4::Members; +use C4::Reserves; +use C4::Letters; +use Koha::Service::Borrower::Discharge; + +use Koha::DateUtils; + +my $input = new CGI; +my ( $template, $loggedinuser, $cookie, $flags ) = get_template_and_user( + { + template_name => 'members/discharge.tt', + query => $input, + type => 'intranet', + authnotrequired => 0, + flagsrequired => { 'borrowers' => '*' }, + } +); + +my $borrowernumber; +my $data; +if ( $input->param('borrowernumber') ) { + $borrowernumber = $input->param('borrowernumber'); + + # Getting member data + $data = GetMember( borrowernumber => $borrowernumber ); + + my $can_be_discharged = + Koha::Service::Borrower::Discharge::can_be_discharged( + { borrowernumber => $borrowernumber, } ); + + # Getting reserves + my @reserves = GetReservesFromBorrowernumber($borrowernumber); + my $hasreserves = scalar(@reserves); + + # Generating discharge if needed + if ( $input->param('discharge') and $can_be_discharged ) { + my $is_discharged = Koha::Service::Borrower::Discharge::count( + { + borrowernumber => $borrowernumber, + validated => 1, + } + ); + unless ($is_discharged) { + Koha::Service::Borrower::Discharge::discharge( + { borrowernumber => $borrowernumber, } ); + } + my $pdf_path = Koha::Service::Borrower::Discharge::generate_as_pdf( + { borrowernumber => $borrowernumber, } ); + + print $input->header( + -type => 'application/pdf', + -charset => 'utf-8', + -attachment => "discharge_$borrowernumber.pdf", + ); + open my $fh, '<', $pdf_path; + my @lines = <$fh>; + close $fh; + print @lines; + exit; + } + + $template->param( + borrowernumber => $borrowernumber, + biblionumber => $data->{'biblionumber'}, + title => $data->{'title'}, + initials => $data->{'initials'}, + surname => $data->{'surname'}, + borrowernumber => $borrowernumber, + firstname => $data->{'firstname'}, + cardnumber => $data->{'cardnumber'}, + categorycode => $data->{'categorycode'}, + category_type => $data->{'category_type'}, + categoryname => $data->{'description'}, + address => $data->{'address'}, + address2 => $data->{'address2'}, + city => $data->{'city'}, + zipcode => $data->{'zipcode'}, + country => $data->{'country'}, + phone => $data->{'phone'}, + email => $data->{'email'}, + branchcode => $data->{'branchcode'}, + hasreserves => $hasreserves, + can_be_discharged => $can_be_discharged, + ); +} + +$template->param( dischargeview => 1, ); + +output_html_with_http_headers $input, $cookie, $template->output; diff --git a/members/discharges.pl b/members/discharges.pl new file mode 100755 index 0000000..3542aaa --- /dev/null +++ b/members/discharges.pl @@ -0,0 +1,59 @@ +#!/usr/bin/perl + +# This file is part of Koha. +# +# Copyright 2013 BibLibre +# +# 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 CGI; +use C4::Auth; +use C4::Output; +use C4::Context; +use Koha::Service::Borrower::Discharge; + +my $input = new CGI; +my $op = $input->param('op') // 'list'; + +my ( $template, $loggedinuser, $cookie, $flags ) = get_template_and_user( + { + template_name => "members/discharges.tt", + query => $input, + type => "intranet", + authnotrequired => 0, + flagsrequired => { borrowers => 1 }, + } +); + +my $branchcode = + ( C4::Context->preference("IndependentBranches") + and not C4::Context->IsSuperLibrarian() ) + ? C4::Context->userenv()->{'branch'} + : undef; + +if ( $op eq 'allow' ) { + my $borrowernumber = $input->param('borrowernumber'); + Koha::Service::Borrower::Discharge::discharge( + { borrowernumber => $borrowernumber } ) + if $borrowernumber; +} + +my $pending_discharges = Koha::Service::Borrower::Discharge::get_pendings( + { branchcode => $branchcode } ); + +$template->param( pending_discharges => $pending_discharges, ); + +output_html_with_http_headers $input, $cookie, $template->output; diff --git a/opac/opac-discharge.pl b/opac/opac-discharge.pl new file mode 100755 index 0000000..b83c4c4 --- /dev/null +++ b/opac/opac-discharge.pl @@ -0,0 +1,107 @@ +#!/usr/bin/perl + +# This file is part of Koha. +# +# Copyright 2013 BibLibre +# +# 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::Auth qw(:DEFAULT get_session); +use CGI; +use C4::Context; +use C4::Output; +use C4::Log; +use C4::Debug; +use C4::Branch; +use C4::Members; +use C4::Discharges; +use Koha::Service::Borrower::Discharge; +use Koha::DateUtils; +use Mail::Sendmail; + +my $input = new CGI; + +my $op = $input->param("op") // 'show'; + +# Getting the template and auth +my ( $template, $loggedinuser, $cookie ) = get_template_and_user( + { + template_name => "opac-discharge.tt", + query => $input, + type => "opac", + debug => 1, + } +); + +# Sending an email to the librarian if user requested a discharge +if ( $op eq 'request' ) { + my $can_be_discharged = + Koha::Service::Borrower::Discharge::can_be_discharged( + { borrowernumber => $loggedinuser } ); + + if ($can_be_discharged) { + eval { + Koha::Service::Borrower::Discharge::request( + { borrowernumber => $loggedinuser, } ); + }; + warn $@ if $@; + my $success = $@ ? 0 : 1; + $template->param( + success => $success, + generated => 1, + ); + } + else { + $template->param( has_issues => 1 ); + } +} +elsif ( $op eq 'get' ) { + my $pdf_path = Koha::Service::Borrower::Discharge::generate_as_pdf( + { borrowernumber => $loggedinuser, } ); + + print $input->header( + -type => 'application/pdf', + -charset => 'utf-8', + -attachment => "discharge_$loggedinuser.pdf", + ); + open my $fh, '<', $pdf_path; + my @lines = <$fh>; + close $fh; + print @lines; + exit; +} +else { + my $pending = Koha::Service::Borrower::Discharge::count( + { + borrowernumber => $loggedinuser, + pending => 1, + } + ); + my $available = Koha::Service::Borrower::Discharge::count( + { + borrowernumber => $loggedinuser, + validated => 1, + } + ); + $template->param( + available => $available, + pending => $pending, + ); +} + +$template->param( dischargeview => 1 ); + +output_html_with_http_headers $input, $cookie, $template->output; -- 1.7.10.4