From a99e3b031f589f94f34d10bda3b03c345805ad83 Mon Sep 17 00:00:00 2001
From: Yohann Dufour <dufour.yohann@gmail.com>
Date: Mon, 4 Aug 2014 16:09:42 +0200
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:
    The perl module HTML::HTMLDoc

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/Borrower/Discharge.pm                         | 135 +++++++++++++++++++++
 .../prog/en/modules/members/discharge.tt           |  41 +++++++
 .../prog/en/modules/members/discharges.tt          |  41 +++++++
 .../bootstrap/en/modules/opac-discharge.tt         |  47 +++++++
 members/discharge.pl                               | 120 ++++++++++++++++++
 members/discharges.pl                              |  58 +++++++++
 opac/opac-discharge.pl                             |  90 ++++++++++++++
 7 files changed, 532 insertions(+)
 create mode 100644 Koha/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/bootstrap/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/Borrower/Discharge.pm b/Koha/Borrower/Discharge.pm
new file mode 100644
index 0000000..6027e7e
--- /dev/null
+++ b/Koha/Borrower/Discharge.pm
@@ -0,0 +1,135 @@
+package Koha::Borrower::Discharge;
+
+use Modern::Perl;
+use CGI;
+use File::Temp qw( :POSIX );
+use HTML::HTMLDoc;
+
+use C4::Members qw( GetPendingIssues );
+use C4::Reserves qw( GetReservesFromBorrowernumber CancelReserve );
+
+use Koha::Database;
+use Koha::DateUtils qw( dt_from_string output_pref );
+
+my $rs = Koha::Database->new->schema->resultset('Discharge');
+
+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 $rs->search( $values )->count;
+}
+
+sub can_be_discharged {
+    my ($params) = @_;
+    return unless $params->{borrowernumber};
+
+    my $issues = GetPendingIssues( $params->{borrowernumber} );
+    if( @$issues ) {
+        return 0;
+    }
+    else {
+        return 1;
+    }
+}
+
+sub request {
+    my ($params) = @_;
+    my $borrowernumber = $params->{borrowernumber};
+    return unless $borrowernumber;
+    return unless can_be_discharged({ borrowernumber => $borrowernumber });
+    return if count($params);
+
+    return $rs->create({
+        borrower => $borrowernumber,
+        needed   => dt_from_string,
+    });
+}
+
+sub discharge {
+    my ($params) = @_;
+    my $borrowernumber = $params->{borrowernumber};
+    return unless $borrowernumber and can_be_discharged( { borrowernumber => $borrowernumber } );
+
+    # Cancel 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 = $rs->search({ borrower => $borrowernumber });
+    if( $discharge->count > 0 ) {
+        $discharge->update({ validated => dt_from_string });
+    }
+    else {
+        $rs->create({
+            borrower  => $borrowernumber,
+            validated => dt_from_string,
+        });
+    }
+}
+
+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>>/$today/g;
+    $letter->{'content'} =~ s/<<today>>/$today/g;
+
+    my $tmpl = C4::Templates::gettemplate('batch/print-notices.tt', 'intranet', new CGI);
+    $tmpl->param(
+        stylesheet => C4::Context->preference("NoticeCSS"),
+        today      => $today,
+        messages   => [$letter],
+    );
+
+    my $pdf_path = tmpnam();
+    my $htmldoc  = new HTML::HTMLDoc();
+    $htmldoc->set_html_content($tmpl->output);
+    $htmldoc->generate_pdf()->to_file($pdf_path);
+
+    return $pdf_path;
+}
+
+sub get_pendings {
+    my ($params)       = @_;
+    my $branchcode     = $params->{branchcode};
+    my $borrowernumber = $params->{borrowernumber};
+
+    my $cond = {
+        'me.needed'    => { '!=', undef },
+        'me.validated' => undef,
+        ( defined $borrowernumber ? ( 'me.borrower' => $borrowernumber ) : () ),
+        ( defined $branchcode ? ( 'borrower.branchcode' => $branchcode ) : () ),
+    };
+
+    my @rs = $rs->search( $cond, { join => 'borrower' } );
+    return \@rs;
+}
+
+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..c487506
--- /dev/null
+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/members/discharge.tt
@@ -0,0 +1,41 @@
+[% INCLUDE 'doc-head-open.inc' %]
+<title>Koha &rsaquo; Patrons &rsaquo; [% IF (unknowuser) %]Patron does not exist[% ELSE %]Discharge for [% firstname %] [% surname %] ([% cardnumber %])[% END %]</title>
+[% INCLUDE 'doc-head-close.inc' %]
+</head>
+<body>
+[% INCLUDE 'header.inc' %]
+[% INCLUDE 'patron-search.inc' %]
+
+<div id="breadcrumbs">
+         <a href="/cgi-bin/koha/mainpage.pl">Home</a>
+&rsaquo; <a href="/cgi-bin/koha/members/members-home.pl">Patrons</a>
+&rsaquo; [% IF (unknowuser) %]Patron does not exist[% ELSE %]Discharge for [% firstname %] [% surname %] ([% cardnumber %])[% END %]
+</div>
+
+<div id="doc3" class="yui-t1">
+   <div id="bd">
+    <div id="yui-main">
+    <div class="yui-b">
+<div class="yui-g">
+<h3>Discharge</h3>
+[% UNLESS can_be_discharged %]
+    <p>Cannot edit discharge: borrower has issues.</p>
+[% ELSE %]
+    [% IF has_reserves %]
+        <p>Borrower has reserves: they will be canceled if the discharge is generated.</p>
+    [% END %]
+    <form method="post">
+        <input type="submit" value="Generate discharge" name="discharge" />
+        <input type="hidden" value="[% borrowernumber %]" name="borrowernumber" />
+    </form>
+[% END %]
+</div>
+
+
+</div>
+</div>
+<div class="yui-b">
+[% INCLUDE 'circ-menu.inc' %]
+</div>
+</div>
+[% 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' %]
+<title>Koha &rsaquo; Patrons &rsaquo; Pending discharge requests</title>
+[% INCLUDE 'doc-head-close.inc' %]
+</head>
+<body id="pat_discharges" class="pat">
+[% INCLUDE 'header.inc' %]
+[% INCLUDE 'patron-search.inc' %]
+
+<div id="breadcrumbs"><a href="/cgi-bin/koha/mainpage.pl">Home</a> &rsaquo; <a href="/cgi-bin/koha/members/members-home.pl">Patrons</a> &rsaquo; Pending discharge requests</div>
+
+<div id="doc2" class="yui-t7">
+<div id="bd">
+  <div id="yui-main">
+    [% IF pending_discharges %]
+      <h2>Pending discharge requests</h2>
+      <div id="pending_updates">
+        <table>
+          <thead>
+            <tr>
+              <th>Patron</th>
+              <th>Allow</th>
+            </tr>
+          </thead>
+          <tbody>
+            [% FOR d IN pending_discharges %]
+              <tr>
+                <td><a href="/cgi-bin/koha/members/discharge.pl?borrowernumber=[% d.borrower.borrowernumber %]">[% d.borrower.surname %], [% d.borrower.firstname %]</a></td>
+                <td><a href="/cgi-bin/koha/members/discharges.pl?op=allow&borrowernumber=[% d.borrower.borrowernumber %]">Allow</a></td>
+              </tr>
+            [% END %]
+          </tbody>
+        </table>
+      </div>
+    [% ELSE %]
+      <div class="dialog message">
+        <p>There are no pending discharge requests.</p>
+      </div>
+    [% END %]
+  </div>
+</div>
+[% INCLUDE 'intranet-bottom.inc' %]
diff --git a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-discharge.tt b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-discharge.tt
new file mode 100644
index 0000000..c775336
--- /dev/null
+++ b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-discharge.tt
@@ -0,0 +1,47 @@
+[% USE Koha %]
+[% INCLUDE 'doc-head-open.inc' %]
+[% IF ( LibraryNameTitle ) %][% LibraryNameTitle %][% ELSE %]Koha online[% END %] catalog &rsaquo; Discharge
+[% INCLUDE 'doc-head-close.inc' %]
+[% BLOCK cssinclude %][% END %]
+</head>
+<body id="opac-discharge" class="scrollto">
+[% INCLUDE 'masthead.inc' %]
+
+<div class="main">
+    <ul class="breadcrumb">
+        <li><a href="/cgi-bin/koha/opac-main.pl">Home</a> <span class="divider">&rsaquo;</span></li>
+        <li><a href="#">Discharge</a></li>
+    </ul>
+
+    <div class="container-fluid">
+        <div class="row-fluid">
+            <div class="span2">
+                <div id="navigation">
+                    [% INCLUDE 'navigation.inc' IsPatronPage=1 %]
+                </div>
+            </div>
+            <div class="span10">
+                <div id="discharge" class="maincontainer">
+                    <h1>Discharge</h1>
+                    [% IF success %]
+                        <p>Your discharge request has been sent. Your discharge will be available on this page within a few days.</p>
+                    [% ELSIF available %]
+                        <a href="/cgi-bin/koha/opac-discharge.pl?op=get">Get your discharge</a></li>
+                    [% ELSIF pending %]
+                        <p>Your discharge will be available on this page within a few days.</p>
+                    [% ELSIF has_issues %]
+                        <p>You cannot be discharged, you have issues. Please return items before asking for a discharge.</p>
+                    [% ELSE %]
+                        <h2>What is a discharge?</h2>
+                        <p>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.</p>
+                        <p><strong>Warning</strong>: 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.</p>
+                        <a href="/cgi-bin/koha/opac-discharge.pl?op=request">Ask for a discharge</a>
+                    [% END %]
+                </div> <!-- / #discharge -->
+            </div> <!-- / .span10 -->
+        </div> <!-- / .row-fluid -->
+    </div>  <!-- / .container-fluid -->
+</div> <!-- / .main -->
+
+[% INCLUDE 'opac-bottom.inc' %]
+[% BLOCK jsinclude %][% END %]
diff --git a/members/discharge.pl b/members/discharge.pl
new file mode 100755
index 0000000..54a9f46
--- /dev/null
+++ b/members/discharge.pl
@@ -0,0 +1,120 @@
+#!/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 <http://www.gnu.org/licenses>.
+
+=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::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::Borrower::Discharge::can_be_discharged({
+        borrowernumber => $borrowernumber
+    });
+
+    # Getting reserves
+    my @reserves    = GetReservesFromBorrowernumber($borrowernumber);
+    my $has_reserves = scalar(@reserves);
+
+    # Generating discharge if needed
+    if ( $input->param('discharge') and $can_be_discharged ) {
+        my $is_discharged = Koha::Borrower::Discharge::count({
+            borrowernumber => $borrowernumber,
+            validated      => 1,
+        });
+        unless ($is_discharged) {
+            Koha::Borrower::Discharge::discharge({
+                borrowernumber => $borrowernumber
+            });
+        }
+        my $pdf_path = Koha::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'},
+        has_reserves      => $has_reserves,
+        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..d318e00
--- /dev/null
+++ b/members/discharges.pl
@@ -0,0 +1,58 @@
+#!/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 <http://www.gnu.org/licenses>.
+
+use Modern::Perl;
+
+use CGI;
+use C4::Auth;
+use C4::Output;
+use C4::Context;
+use Koha::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::Borrower::Discharge::discharge({
+        borrowernumber => $borrowernumber
+    }) if $borrowernumber;
+}
+
+my $pending_discharges = Koha::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..8338d05
--- /dev/null
+++ b/opac/opac-discharge.pl
@@ -0,0 +1,90 @@
+#!/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 <http://www.gnu.org/licenses>.
+
+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 Koha::Borrower::Discharge;
+use Koha::DateUtils;
+
+my $input = new CGI;
+
+my $op = $input->param("op");
+
+# Getting the template and auth
+my ( $template, $loggedinuser, $cookie ) = get_template_and_user({
+    template_name => "opac-discharge.tt",
+    query         => $input,
+    type          => "opac",
+    debug         => 1,
+});
+
+if ( $op eq 'request' ) {
+    my $success = Koha::Borrower::Discharge::request({
+        borrowernumber => $loggedinuser,
+    });
+
+    if ($success) {
+        $template->param( success => 1 );
+    }
+    else {
+        $template->param( has_issues => 1 );
+    }
+}
+elsif ( $op eq 'get' ) {
+    my $pdf_path = Koha::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::Borrower::Discharge::count({
+        borrowernumber => $loggedinuser,
+        pending        => 1,
+    });
+    my $available = Koha::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.9.1