Commit df6c6bca authored by tipaul's avatar tipaul

Letters / alert system, continuing...

* adding a package Letters.pm, that manages Letters & alerts.
* adding feature : it's now possible to define a "letter" for any subscription created. If a letter is defined, users in OPAC can put an alert on the subscription. When an issue is marked "arrived", all users in the alert will recieve a mail (as defined in the "letter"). This last part (= send the mail) is not yet developped. (Should be done this week)
* adding feature : it's now possible to "put to an alert" in OPAC, for any serial subscription. The alert is stored in a new table, called alert. An alert can be put only if the librarian has activated them in subscription (and they activate it just by choosing a "letter" to sent to borrowers on new issues)
* adding feature : librarian can see in borrower detail which alerts they have put, and a user can see in opac-detail which alert they have put too.
Note that the system should be generic enough to manage any type of alert.
I plan to extend it soon to virtual shelves : a borrower will be able to put an alert on a virtual shelf, to be warned when something is changed in the virtual shelf (mail being sent once a day by cron, or manually by the shelf owner. Anyway, a mail won't be sent on every change, users would be spammed by Koha ;-) )
parent cb39259b
package C4::Letters;
# Copyright 2000-2002 Katipo Communications
#
# This file is part of Koha.
#
# 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place,
# Suite 330, Boston, MA 02111-1307 USA
use strict;
use C4::Date;
use Date::Manip;
use C4::Suggestions;
require Exporter;
use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
# set the version for version checking
$VERSION = 0.01;
=head1 NAME
C4::Letters - Give functions for Letters management
=head1 SYNOPSIS
use C4::Letters;
=head1 DESCRIPTION
"Letters" is the tool used in Koha to manage informations sent to the patrons and/or the library. This include some cron jobs like
late issues, as well as other tasks like sending a mail to users that have subscribed to a "serial issue alert" (= being warned every time a new issue has arrived at the library)
Letters are managed through "alerts" sent by Koha on some events. All "alert" related functions are in this module too.
=cut
@ISA = qw(Exporter);
@EXPORT = qw(&GetLetterList &addalert &getalert &delalert &findrelatedto);
=head2 GetLetterList
parameter : $module : the name of the module
This sub returns an array of hashes with all letters from a given module
Each hash entry contains :
- module : the module name
- code : the code of the letter, char(20)
- name : the complete name of the letter, char(200)
- title : the title that will be used as "subject" in mails, char(200)
- content : the content of the letter. Each field to be replaced by a value at runtime is enclosed in << and >>. The fields usually have the same name as in the DB
=cut
sub GetLetterList {
my ($module) = @_;
my $dbh = C4::Context->dbh;
my $sth = $dbh->prepare("select * from letter where module=?");
$sth->execute($module);
my @result;
while (my $line = $sth->fetchrow_hashref) {
push @result,$line;
}
return @result;
}
=head2 addalert
parameters :
- $borrowernumber : the number of the borrower subscribing to the alert
- $type : the type of alert.
- externalid : the primary key of the object to put alert on. For issues, the alert is made on subscriptionid.
create an alert and return the alertid (primary key)
=cut
sub addalert {
my ($borrowernumber,$type,$externalid) = @_;
my $dbh=C4::Context->dbh;
my $sth = $dbh->prepare("insert into alert (borrowernumber, type, externalid) values (?,?,?)");
$sth->execute($borrowernumber,$type,$externalid);
# get the alert number newly created and return it
my $alertid = $dbh->{'mysql_insertid'};
return $alertid;
}
=head2 delalert
parameters :
- alertid : the alert id
deletes the alert
=cut
sub delalert {
my ($alertid)=@_;
# warn "ALERTID : $alertid";
my $dbh = C4::Context->dbh;
my $sth = $dbh->prepare("delete from alert where alertid=?");
$sth->execute($alertid);
}
=head2 getalert
parameters :
- $borrowernumber : the number of the borrower subscribing to the alert
- $type : the type of alert.
- externalid : the primary key of the object to put alert on. For issues, the alert is made on subscriptionid.
all parameters NON mandatory. If a parameter is omitted, the query is done without the corresponding parameter. For example, without $externalid, returns all alerts for a borrower on a topic.
=cut
sub getalert {
my ($borrowernumber,$type,$externalid) = @_;
my $dbh=C4::Context->dbh;
my $query = "select * from alert where";
my @bind;
if ($borrowernumber) {
$query .= " borrowernumber=? and";
push @bind,$borrowernumber;
}
if ($type) {
$query .= " type=? and";
push @bind,$type;
}
if ($externalid) {
$query .= " externalid=? and";
push @bind,$externalid;
}
$query =~ s/ and$//;
# warn "Q : $query";
my $sth = $dbh->prepare($query);
$sth->execute(@bind);
my @result;
while (my $line = $sth->fetchrow_hashref) {
push @result,$line;
}
return \@result if $#result >=0; # return only if there is one result.
return;
}
=head2 findrelatedto
parameters :
- $type : the type of alert
- $externalid : the id of the "object" to query
In the table alert, a "id" is stored in the externalid field. This "id" is related to another table, depending on the type of the alert.
When type=issue, the id is related to a subscriptionid and this sub returns the name of the biblio.
When type=virtual, the id is related to a virtual shelf and this sub returns the name of the sub
=cut
sub findrelatedto {
my ($type,$externalid) = @_;
my $dbh=C4::Context->dbh;
my $sth;
if ($type eq "issue") {
$sth=$dbh->prepare("select title as result from subscription left join biblio on subscription.biblionumber=biblio.biblionumber where subscriptionid=?");
}
$sth->execute($externalid);
my ($result) = $sth->fetchrow;
return $result;
}
END { } # module clean-up code here (global destructor)
......@@ -71,6 +71,7 @@ my $searchfield=$input->param('searchfield');
my $offset=$input->param('offset');
my $script_name="/cgi-bin/koha/admin/letter.pl";
my $code=$input->param('code');
my $module = $input->param('module');
my $pagesize=20;
my $op = $input->param('op');
$searchfield=~ s/\,//g;
......@@ -100,8 +101,8 @@ if ($op eq 'add_form') {
#---- if primkey exists, it's a modify action, so read values to modify...
my $letter;
if ($code) {
my $sth=$dbh->prepare("select * from letter where code=?");
$sth->execute($code);
my $sth=$dbh->prepare("select * from letter where module=? and code=?");
$sth->execute($module,$code);
$letter=$sth->fetchrow_hashref;
$sth->finish;
}
......@@ -144,6 +145,7 @@ if ($op eq 'add_form') {
}
$template->param(name => $letter->{name},title => $letter->{title},
content => $letter->{content},
$letter->{module} => 1,
SQLfieldname => \@SQLfieldname,);
# END $OP eq ADD_FORM
################## ADD_VALIDATE ##################################
......
......@@ -13,6 +13,7 @@ use C4::Interface::CGI::Output;
use C4::Context;
use HTML::Template;
use C4::Bull;
use C4::Letters;
my $query = new CGI;
my $op = $query->param('op');
......@@ -23,7 +24,7 @@ my ($subscriptionid,$auser,$librarian,$cost,$aqbooksellerid, $aqbooksellername,$
$add2,$every2,$whenmorethan2,$setto2,$lastvalue2,$innerloop2,
$add3,$every3,$whenmorethan3,$setto3,$lastvalue3,$innerloop3,
$numberingmethod, $status, $biblionumber,
$bibliotitle, $notes);
$bibliotitle, $notes, $letter);
my @budgets;
my ($template, $loggedinuser, $cookie)
......@@ -82,6 +83,7 @@ if ($op eq 'mod') {
$biblionumber = $subs->{'biblionumber'};
$bibliotitle = $subs->{'bibliotitle'},
$notes = $subs->{'notes'};
$letter = $subs->{'letter'};
$template->param(
$op => 1,
user => $auser,
......@@ -120,6 +122,7 @@ if ($op eq 'mod') {
biblionumber => $biblionumber,
bibliotitle => $bibliotitle,
notes => $notes,
letter => $letter,
subscriptionid => $subscriptionid,
);
$template->param(
......@@ -138,6 +141,13 @@ for (my $i=0;$i<=$#budgets;$i++) {
$template->param(budgets => \@budgets);
#FIXME : END Added by hdl on July, 14 2005
my @letterlist = GetLetterList('serial');
for (my $i=0;$i<=$#letterlist;$i++) {
warn "$letterlist[$i]->{'code'} eq ".$letter;
$letterlist[$i]->{'selected'} =1 if $letterlist[$i]->{'code'} eq $letter;
}
$template->param(letters => \@letterlist);
if ($op eq 'addsubscription') {
my $auser = $query->param('user');
my $aqbooksellerid = $query->param('aqbooksellerid');
......@@ -168,12 +178,13 @@ if ($op eq 'addsubscription') {
my $status = 1;
my $biblionumber = $query->param('biblionumber');
my $notes = $query->param('notes');
my $letter = $query->param('letter');
my $subscriptionid = newsubscription($auser,$aqbooksellerid,$cost,$aqbudgetid,$biblionumber,
$startdate,$periodicity,$dow,$numberlength,$weeklength,$monthlength,
$add1,$every1,$whenmorethan1,$setto1,$lastvalue1,
$add2,$every2,$whenmorethan2,$setto2,$lastvalue2,
$add3,$every3,$whenmorethan3,$setto3,$lastvalue3,
$numberingmethod, $status, $notes
$numberingmethod, $status, $notes, $letter
);
print $query->redirect("/cgi-bin/koha/bull/subscription-detail.pl?subscriptionid=$subscriptionid");
} else {
......
......@@ -22,7 +22,7 @@ my ($subscriptionid,$auser,$librarian,$cost,$aqbooksellerid, $aqbooksellername,$
$add1,$every1,$whenmorethan1,$setto1,$lastvalue1,$innerloop1,
$add2,$every2,$whenmorethan2,$setto2,$lastvalue2,$innerloop2,
$add3,$every3,$whenmorethan3,$setto3,$lastvalue3,$innerloop3,
$numberingmethod, $status, $biblionumber, $bibliotitle, $notes);
$numberingmethod, $status, $biblionumber, $bibliotitle, $notes,$letter);
$subscriptionid = $query->param('subscriptionid');
......@@ -60,13 +60,14 @@ if ($op eq 'modsubscription') {
$numberingmethod = $query->param('numberingmethod');
$status = 1;
$notes = $query->param('notes');
$letter = $query->param('letter');
&modsubscription($auser,$aqbooksellerid,$cost,$aqbudgetid,$startdate,
$periodicity,$dow,$numberlength,$weeklength,$monthlength,
$add1,$every1,$whenmorethan1,$setto1,$lastvalue1,$innerloop1,
$add2,$every2,$whenmorethan2,$setto2,$lastvalue2,$innerloop2,
$add3,$every3,$whenmorethan3,$setto3,$lastvalue3,$innerloop3,
$numberingmethod, $status, $biblionumber, $notes, $subscriptionid);
$numberingmethod, $status, $biblionumber, $notes, $letter, $subscriptionid);
}
if ($op eq 'del') {
......@@ -78,7 +79,6 @@ if ($op eq 'del') {
my $subs = &getsubscription($subscriptionid);
my ($totalissues,@serialslist) = getserials($subscriptionid);
$totalissues-- if $totalissues; # the -1 is to have 0 if this is a new subscription (only 1 issue)
# the subscription must be deletable if there is NO issues for a reason or another (should not happend, but...)
($template, $loggedinuser, $cookie)
= get_template_and_user({template_name => "bull/subscription-detail.tmpl",
......@@ -89,8 +89,7 @@ $totalissues-- if $totalissues; # the -1 is to have 0 if this is a new subscript
debug => 1,
});
my ($user, $cookie, $sessionID, $flags)
= checkauth($query, 0, {catalogue => 1}, "intranet");
my ($user, $cookie, $sessionID, $flags) = checkauth($query, 0, {catalogue => 1}, "intranet");
$template->param(
user => $subs->{auser},
......@@ -129,6 +128,7 @@ $template->param(
biblionumber => $subs->{biblionumber},
bibliotitle => $subs->{bibliotitle},
notes => $subs->{notes},
letter => $subs->{letter},
subscriptionid => $subs->{subscriptionid},
serialslist => \@serialslist,
totalissues => $totalissues,
......
......@@ -15,9 +15,21 @@
<input type="hidden" name="op" value="addsubscription">
<input type="hidden" name="user" value="<!-- TMPL_VAR name="user" -->">
<p>Librarian</td><td> <!-- TMPL_VAR name="user" --></p>
<p><label>Supplier</label><input type="text" name="aqbooksellerid" value="<!-- TMPL_VAR name="aqbooksellerid" -->" size=4> (<input type="text" name="aqbooksellername" value="<!-- TMPL_VAR name="aqbooksellername" -->" disabled readonly>)<a href="#" onClick="FindAcqui(f)">...</a></p>
<p><label>Biblio</label><input type="text" name="biblionumber" value="<!-- TMPL_VAR name="biblionumber" -->" size=4> (<input type="text" name="title" value="<!-- TMPL_VAR name="bibliotitle" -->" disabled readonly>)<a href="#" onClick="Plugin(f)">...</a></p>
<p><label>Notes</label><textarea name="notes" cols="30" rows="2"><!-- TMPL_VAR name="notes" --></textarea></p>
<p><label class="label100">Supplier</label><input type="text" name="aqbooksellerid" value="<!-- TMPL_VAR name="aqbooksellerid" -->" size=4> (<input type="text" name="aqbooksellername" value="<!-- TMPL_VAR name="aqbooksellername" -->" disabled readonly>)<a href="#" onClick="FindAcqui(f)">...</a></p>
<p><label class="label100">Biblio</label><input type="text" name="biblionumber" value="<!-- TMPL_VAR name="biblionumber" -->" size=4> (<input type="text" name="title" value="<!-- TMPL_VAR name="bibliotitle" -->" disabled readonly>)<a href="#" onClick="Plugin(f)">...</a></p>
<p><label class="label100">Notes</label><textarea name="notes" cols="30" rows="2"><!-- TMPL_VAR name="notes" --></textarea></p>
<p><label class="label100">Enable issue alert</label>
<select name="letter">
<option value=""></option>
<!-- TMPL_LOOP name="letters" -->
<!-- TMPL_IF name="selected" -->
<option value="<!-- TMPL_VAR name="code" -->" selected><!-- TMPL_VAR name="name" --></option>
<!-- TMPL_ELSE -->
<option value="<!-- TMPL_VAR name="code" -->"><!-- TMPL_VAR name="name" --></option>
<!-- /TMPL_IF -->
<!-- /TMPL_LOOP -->
</select>
</p>
<p class="problem">warning</p>
<ul>
<li>remember you <b>must</b> have created a biblio <b>before</b> creating a subscription</li>
......
......@@ -14,11 +14,18 @@
<div id="bloc25">
<h2 class="bull">Subscription information</h2>
<p>Librarian identity :</td><td> <!-- TMPL_VAR name="librarian" --></p>
<p><label>Supplier </label><!-- TMPL_VAR name="aqbooksellername" --></p>
<p><label>Cost</label><!-- TMPL_VAR name="cost" --></p>
<p><label>Budget </label><!-- TMPL_VAR name="bookfundid" --></p>
<p><label>Biblio</label><i>(<!-- TMPL_VAR name="biblionumber" -->)</i> <!-- TMPL_VAR name="bibliotitle" --></p>
<p><label>Notes:</label><!-- TMPL_VAR name="notes" --></p>
<p><label class="label100">Supplier </label><!-- TMPL_VAR name="aqbooksellername" --></p>
<p><label class="label100">Cost</label><!-- TMPL_VAR name="cost" --></p>
<p><label class="label100">Budget </label><!-- TMPL_VAR name="bookfundid" --></p>
<p><label class="label100">Biblio</label><i>(<!-- TMPL_VAR name="biblionumber" -->)</i> <!-- TMPL_VAR name="bibliotitle" --></p>
<p><label class="label100">Notes:</label><!-- TMPL_VAR name="notes" --></p>
<p>
<!-- TMPL_IF name="letter" -->
<label class="label100">Issue alert with letter:</label><!-- TMPL_VAR name="letter" -->
<!-- TMPL_ELSE -->
<label class="label100">Borrowers can't subscribe to issue alerts</label>
<!-- /TMPL_IF -->
</p>
</div>
<div id="bloc25">
<h2 class="bull">Planning</h2>
......
......@@ -263,6 +263,25 @@
None
<!-- /TMPL_IF -->
</div>
<div class="bloc25">
<h2 class="members">Alert subscriptions</h2>
<table>
<tr>
<th>Type</th>
<th>on</th>
</tr>
<!-- TMPL_LOOP NAME="alertloop" -->
<tr>
<td><!-- TMPL_IF name="issue" -->Serial issue<!-- /TMPL_IF --></td>
<td><!-- TMPL_VAR name="relatedto" --></td>
</tr>
<!-- /TMPL_LOOP -->
</table>
</div>
</div>
<script language="JavaScript" type="text/javascript">
function confirm_deletion() {
......
......@@ -22,7 +22,7 @@
<td><!-- TMPL_VAR NAME="code" --></td>
<td><!-- TMPL_VAR NAME="name" --></td>
<td>
<a href="/cgi-bin/koha/admin/letter.pl?op=add_form&amp;code=<!-- TMPL_VAR NAME="code" -->">
<a href="/cgi-bin/koha/admin/letter.pl?op=add_form&amp;module=<!-- TMPL_VAR name="module" -->&amp;code=<!-- TMPL_VAR NAME="code" -->">
<img src="<!-- TMPL_VAR NAME="interface" -->/<!-- TMPL_VAR NAME="theme" -->/images/fileopen.png" width="32" hspace="0" vspace="0" border="0">
</a>
</td>
......
......@@ -75,6 +75,19 @@
<!-- TMPL_IF name="enddate" --><p><b>This subscription is now ended. The last issue was recieved on <!-- TMPL_VAR name="enddate" --></b></p><!-- /TMPL_IF name="enddate" -->
<!--TMPL_UNLESS Name=fullinfo -->
<p><!-- TMPL_VAR name="notes" --></p>
<p>
<!-- TMPL_IF name="letter" -->
<!-- TMPL_IF name="hasalert" -->
<a href="opac-alert-subscribe.pl?op=cancel&amp;externalid=<!-- TMPL_VAR name="subscriptionid" -->&amp;alerttype=issue&amp;biblionumber=<!-- TMPL_VAR name="biblionumber" -->" class="button" title="Cancel mail alert when a new issue arrives for this subscription">
Cancel alert
</a>
<!-- TMPL_ELSE -->
<a href="opac-alert-subscribe.pl?externalid=<!-- TMPL_VAR name="subscriptionid" -->&amp;alerttype=issue&amp;biblionumber=<!-- TMPL_VAR name="biblionumber" -->" class="button" title="be warned by mail when a new issue arrives for this subscription">
Stay in touch
</a>
<!-- /TMPL_IF -->
<!-- /TMPL_IF -->
</p>
<!-- TMPL_IF name="opacnote" -->
<h2 class="catalogue">Issues summary</h2>
<p>
......
......@@ -113,6 +113,25 @@
<br />
</div>
<!-- /TMPL_IF -->
<!-- TMPL_IF name="alertloop" -->
<div class="bloc60">
<h2 class="members">Alert subscriptions</h2>
<table>
<tr>
<th>Type</th>
<th>on</th>
</tr>
<!-- TMPL_LOOP NAME="alertloop" -->
<tr>
<td><!-- TMPL_IF name="issue" -->Serial issue<!-- /TMPL_IF --></td>
<td><!-- TMPL_VAR name="relatedto" --></td>
</tr>
<!-- /TMPL_LOOP -->
</table>
</div>
<!-- /TMPL_IF -->
</div>
<!-- TMPL_INCLUDE NAME="opac-bottom.inc" -->
......@@ -43,6 +43,7 @@ use C4::Date;
use C4::Reserves2;
use C4::Circulation::Circ2;
use C4::Koha;
use C4::Letters;
use HTML::Template;
my $dbh = C4::Context->dbh;
......@@ -147,7 +148,11 @@ $data->{'categorycode'} = &getborrowercategory($data->{'categorycode'});
my ($numaccts,$accts,$total)=getboracctrecord('',\%bor);
#
# current issues
#
my ($count,$issue)=borrissues($bornum);
my $today=ParseDate('today');
my @issuedata;
my $totalprice = 0;
......@@ -185,8 +190,10 @@ for (my $i=0;$i<$count;$i++){
push (@issuedata, \%row);
}
#
# find reserves
#
my ($rescount,$reserves)=FindReserves('',$bornum); #From C4::Reserves2
my @reservedata;
foreach my $reserveline (@$reserves) {
$reserveline->{'reservedate2'} = format_date($reserveline->{'reservedate'});
......@@ -199,16 +206,23 @@ foreach my $reserveline (@$reserves) {
push (@reservedata, \%row);
}
# current alert subscriptions
my $alerts = getalert($bornum);
foreach (@$alerts) {
$_->{$_->{type}}=1;
$_->{relatedto} = findrelatedto($_->{type},$_->{externalid});
}
$template->param($data);
$template->param(
bornum => $bornum,
totalprice =>$totalprice,
totaldue =>$total,
issueloop => \@issuedata,
reserveloop => \@reservedata
);
$template->param(
reserveloop => \@reservedata,
alertloop => $alerts);
independantbranches => C4::Context->preference("IndependantBranches"),
samebranch => $samebranch) if (C4::Context->preference("IndependantBranches"));
samebranch => $samebranch) if (C4::Context->preference("IndependantBranches")
);
output_html_with_http_headers $input, $cookie, $template->output;
......@@ -6,6 +6,7 @@ use C4::Auth;
use C4::Koha;
use C4::Date;
use C4::Bull;
use C4::Letters;
use C4::Output;
use C4::Interface::CGI::Output;
use C4::Context;
......@@ -24,12 +25,15 @@ my $biblionumber = $query->param('biblionumber');
if ($selectview eq "full"){
my $subscriptions = get_full_subscription_list_from_biblionumber($biblionumber);
# now, check is there is an alert subscription for one of the subscriptions
foreach (@$subscriptions) {
if (getalert($loggedinuser,'issue',$_->{subscriptionid})) {
warn "SUBSCRIPTION FOR : $loggedinuser,'issue',$_->{subscriptionid}";
}
}
my $title = $subscriptions->[0]{bibliotitle};
# warn "title ".$title;
my $yearmin=$subscriptions->[0]{year};
# warn "yearmin ".$yearmin;
my $yearmax=$subscriptions->[scalar(@$subscriptions)-1]{year};
# warn "yearmax ".$yearmax;
($template, $loggedinuser, $cookie)
......@@ -56,6 +60,13 @@ if ($selectview eq "full"){
} else {
my $subscriptions = get_subscription_list_from_biblionumber($biblionumber);
# now, check is there is an alert subscription for one of the subscriptions
foreach (@$subscriptions) {
if (getalert($loggedinuser,'issue',$_->{subscriptionid})) {
$_->{hasalert} = 1;
}
}
($template, $loggedinuser, $cookie)
= get_template_and_user({template_name => "opac-serial-issues.tmpl",
query => $query,
......
......@@ -11,6 +11,7 @@ use C4::Search;
use C4::Interface::CGI::Output;
use HTML::Template;
use C4::Date;
use C4::Letters;
my $query = new CGI;
my ($template, $borrowernumber, $cookie)
......@@ -133,13 +134,22 @@ foreach my $res (@$reserves) {
$wcount++;
}
}
$template->param(WAITING => \@waiting);
# current alert subscriptions
warn " B : $borrowernumber";
my $alerts = getalert($borrowernumber);
foreach (@$alerts) {
$_->{$_->{type}}=1;
$_->{relatedto} = findrelatedto($_->{type},$_->{externalid});
}
$template->param(waiting_count => $wcount,
LibraryName => C4::Context->preference("LibraryName"),
suggestion => C4::Context->preference("suggestion"),
virtualshelves => C4::Context->preference("virtualshelves"),
textmessaging => $borr->{textmessaging},
alertloop => $alerts,
);
output_html_with_http_headers $query, $cookie, $template->output;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment