From 53543a46c51a85d53ecc1bcededed25d7541a677 Mon Sep 17 00:00:00 2001 From: Srdjan Jankovic Date: Wed, 22 Feb 2012 18:47:35 +1300 Subject: [PATCH] bug_7001: Issue and Reserve slips are notices. Branches can have their own version of notices - added branchcode to letter table. Support html notices - added is_html to letter table. Support for borrower attributes in templates. GetPreparedletter() is the interface for compiling letters (notices). Sysprefs for notice and slips stylesheets. --- C4/Circulation.pm | 20 +- C4/Letters.pm | 549 +++++++++++++------- C4/Members.pm | 81 +++- C4/Members/Attributes.pm | 18 + C4/Message.pm | 12 +- C4/Print.pm | 146 ++---- C4/Reserves.pm | 103 +++-- C4/Suggestions.pm | 22 +- acqui/booksellers.pl | 7 +- circ/circulation.pl | 3 +- circ/hold-transfer-slip.pl | 32 +- .../data/mysql/de-DE/mandatory/sample_notices.sql | 2 +- .../data/mysql/en/mandatory/sample_notices.sql | 84 +++- .../data/mysql/es-ES/mandatory/sample_notices.sql | 2 +- .../mysql/fr-FR/1-Obligatoire/sample_notices.sql | 2 +- installer/data/mysql/it-IT/necessari/notices.sql | 2 +- installer/data/mysql/kohastructure.sql | 7 +- .../mysql/nb-NO/1-Obligatorisk/sample_notices.sql | 2 +- .../data/mysql/pl-PL/mandatory/sample_notices.sql | 2 +- .../data/mysql/ru-RU/mandatory/sample_notices.sql | 2 +- installer/data/mysql/sysprefs.sql | 2 + .../data/mysql/uk-UA/mandatory/sample_notices.sql | 2 +- installer/data/mysql/updatedatabase.pl | 100 ++++- .../prog/en/includes/circ-toolbar.inc | 4 +- .../en/modules/admin/preferences/circulation.pref | 5 + .../en/modules/admin/preferences/staff_client.pref | 5 + .../prog/en/modules/batch/print-notices.tt | 6 +- .../prog/en/modules/circ/hold-transfer-slip.tt | 54 -- .../prog/en/modules/circ/printslip.tt | 28 + .../intranet-tmpl/prog/en/modules/tools/letter.tt | 162 +++++-- .../prog/en/modules/tools/tools-home.tt | 2 +- members/memberentry.pl | 5 +- members/moremember.pl | 10 - members/printslip.pl | 92 ++++ misc/cronjobs/advance_notices.pl | 78 ++-- misc/cronjobs/gather_print_notices.pl | 14 +- misc/cronjobs/overdue_notices.pl | 86 ++-- t/db_dependent/lib/KohaTest/Letters.pm | 5 +- t/db_dependent/lib/KohaTest/Letters/GetLetter.pm | 3 +- t/db_dependent/lib/KohaTest/Members.pm | 1 + t/db_dependent/lib/KohaTest/Print.pm | 5 +- t/db_dependent/lib/KohaTest/Reserves.pm | 1 + tools/letter.pl | 230 ++++++--- 43 files changed, 1308 insertions(+), 690 deletions(-) delete mode 100644 koha-tmpl/intranet-tmpl/prog/en/modules/circ/hold-transfer-slip.tt create mode 100644 koha-tmpl/intranet-tmpl/prog/en/modules/circ/printslip.tt create mode 100755 members/printslip.pl diff --git a/C4/Circulation.pm b/C4/Circulation.pm index 93c6fac..a62f26e 100644 --- a/C4/Circulation.pm +++ b/C4/Circulation.pm @@ -2667,11 +2667,18 @@ sub SendCirculationAlert { borrowernumber => $borrower->{borrowernumber}, message_name => $message_name{$type}, }); - my $letter = C4::Letters::getletter('circulation', $type); - C4::Letters::parseletter($letter, 'biblio', $item->{biblionumber}); - C4::Letters::parseletter($letter, 'biblioitems', $item->{biblionumber}); - C4::Letters::parseletter($letter, 'borrowers', $borrower->{borrowernumber}); - C4::Letters::parseletter($letter, 'branches', $branch); + my $letter = C4::Letters::GetPreparedLetter ( + module => 'circulation', + letter_code => $type, + branchcode => $branch, + tables => { + 'biblio' => $item->{biblionumber}, + 'biblioitems' => $item->{biblionumber}, + 'borrowers' => $borrower, + 'branches' => $branch, + } + ) or return; + my @transports = @{ $borrower_preferences->{transports} }; # warn "no transports" unless @transports; for (@transports) { @@ -2686,7 +2693,8 @@ sub SendCirculationAlert { $message->update; } } - $letter; + + return $letter; } =head2 updateWrongTransfer diff --git a/C4/Letters.pm b/C4/Letters.pm index 28c6984..5080a0c 100644 --- a/C4/Letters.pm +++ b/C4/Letters.pm @@ -24,6 +24,7 @@ use MIME::Lite; use Mail::Sendmail; use C4::Members; +use C4::Members::Attributes qw(GetBorrowerAttributes); use C4::Branch; use C4::Log; use C4::SMS; @@ -40,7 +41,7 @@ BEGIN { $VERSION = 3.01; @ISA = qw(Exporter); @EXPORT = qw( - &GetLetters &getletter &addalert &getalert &delalert &findrelatedto &SendAlerts GetPrintMessages + &GetLetters &GetPreparedLetter &GetWrappedLetter &addalert &getalert &delalert &findrelatedto &SendAlerts &GetPrintMessages ); } @@ -115,13 +116,26 @@ sub GetLetters (;$) { return \%letters; } -sub getletter ($$) { - my ( $module, $code ) = @_; +my %letter; +sub getletter ($$$) { + my ( $module, $code, $branchcode ) = @_; + + if (C4::Context->preference('IndependantBranches') && $branchcode){ + $branchcode = C4::Context->userenv->{'branch'}; + } + + if ( my $l = $letter{$module}{$code}{$branchcode} ) { + return { %$l }; # deep copy + } + my $dbh = C4::Context->dbh; - my $sth = $dbh->prepare("select * from letter where module=? and code=?"); - $sth->execute( $module, $code ); - my $line = $sth->fetchrow_hashref; - return $line; + my $sth = $dbh->prepare("select * from letter where module=? and code=? and (branchcode = ? or branchcode = '') order by branchcode desc limit 1"); + $sth->execute( $module, $code, $branchcode ); + my $line = $sth->fetchrow_hashref + or return; + $line->{'content-type'} = 'text/html; charset="UTF-8"' if $line->{is_html}; + $letter{$module}{$code}{$branchcode} = $line; + return { %$line }; } =head2 addalert ($borrowernumber, $type, $externalid) @@ -176,7 +190,7 @@ sub delalert ($) { sub getalert (;$$$) { my ( $borrowernumber, $type, $externalid ) = @_; my $dbh = C4::Context->dbh; - my $query = "SELECT * FROM alert WHERE"; + my $query = "SELECT a.*, b.branchcode FROM alert a JOIN borrowers b USING(borrowernumber) WHERE"; my @bind; if ($borrowernumber and $borrowernumber =~ /^\d+$/) { $query .= " borrowernumber=? AND "; @@ -232,73 +246,68 @@ sub findrelatedto ($$) { parameters : - $type : the type of alert - $externalid : the id of the "object" to query - - $letter : the letter to send. + - $letter_code : the letter to send. send an alert to all borrowers having put an alert on a given subject. =cut sub SendAlerts { - my ( $type, $externalid, $letter ) = @_; + my ( $type, $externalid, $letter_code ) = @_; my $dbh = C4::Context->dbh; my $strsth; if ( $type eq 'issue' ) { - # warn "sending issues..."; - my $letter = getletter( 'serial', $letter ); - # prepare the letter... # search the biblionumber my $sth = $dbh->prepare( "SELECT biblionumber FROM subscription WHERE subscriptionid=?"); $sth->execute($externalid); - my ($biblionumber) = $sth->fetchrow; - - # parsing branch info - my $userenv = C4::Context->userenv; - parseletter( $letter, 'branches', $userenv->{branch} ); - - # parsing librarian name - $letter->{content} =~ s/<>/$userenv->{firstname}/g; - $letter->{content} =~ s/<>/$userenv->{surname}/g; - $letter->{content} =~ - s/<>/$userenv->{emailaddress}/g; - - # parsing biblio information - parseletter( $letter, 'biblio', $biblionumber ); - parseletter( $letter, 'biblioitems', $biblionumber ); + my ($biblionumber) = $sth->fetchrow + or warn( "No subscription for '$externalid'" ), + return; + my %letter; # find the list of borrowers to alert my $alerts = getalert( '', 'issue', $externalid ); foreach (@$alerts) { - # and parse borrower ... - my $innerletter = $letter; my $borinfo = C4::Members::GetMember('borrowernumber' => $_->{'borrowernumber'}); - parseletter( $innerletter, 'borrowers', $_->{'borrowernumber'} ); + my $email = $borinfo->{email} or next; + + # warn "sending issues..."; + my $userenv = C4::Context->userenv; + my $letter = GetPreparedLetter ( + module => 'serial', + letter_code => $letter_code, + branchcode => $userenv->{branch}, + tables => { + 'branches' => $_->{branchcode}, + 'biblio' => $biblionumber, + 'biblioitems' => $biblionumber, + 'borrowers' => $borinfo, + }, + want_librarian => 1, + ) or return; # ... then send mail - if ( $borinfo->{email} ) { - my %mail = ( - To => $borinfo->{email}, - From => $borinfo->{email}, - Subject => "" . $innerletter->{title}, - Message => "" . $innerletter->{content}, - 'Content-Type' => 'text/plain; charset="utf8"', - ); - sendmail(%mail) or carp $Mail::Sendmail::error; - - } + my %mail = ( + To => $email, + From => $email, + Subject => "" . $letter->{title}, + Message => "" . $letter->{content}, + 'Content-Type' => 'text/plain; charset="utf8"', + ); + sendmail(%mail) or carp $Mail::Sendmail::error; } } - elsif ( $type eq 'claimacquisition' ) { - - $letter = getletter( 'claimacquisition', $letter ); + elsif ( $type eq 'claimacquisition' or $type eq 'claimissues' ) { # prepare the letter... # search the biblionumber - $strsth = qq{ + $strsth = $type eq 'claimacquisition' + ? qq{ SELECT aqorders.*,aqbasket.*,biblio.*,biblioitems.*,aqbooksellers.* FROM aqorders LEFT JOIN aqbasket ON aqbasket.basketno=aqorders.basketno @@ -306,114 +315,83 @@ sub SendAlerts { LEFT JOIN biblioitems ON aqorders.biblioitemnumber=biblioitems.biblioitemnumber LEFT JOIN aqbooksellers ON aqbasket.booksellerid=aqbooksellers.id WHERE aqorders.ordernumber IN ( - } - . join( ",", @$externalid ) . ")"; - } - elsif ( $type eq 'claimissues' ) { - - $letter = getletter( 'claimissues', $letter ); - - # prepare the letter... - # search the biblionumber - $strsth = qq{ + } + : qq{ SELECT serial.*,subscription.*, biblio.*, aqbooksellers.* FROM serial LEFT JOIN subscription ON serial.subscriptionid=subscription.subscriptionid LEFT JOIN biblio ON serial.biblionumber=biblio.biblionumber LEFT JOIN aqbooksellers ON subscription.aqbooksellerid=aqbooksellers.id WHERE serial.serialid IN ( - } + } . join( ",", @$externalid ) . ")"; - } - - if ( $type eq 'claimacquisition' or $type eq 'claimissues' ) { my $sthorders = $dbh->prepare($strsth); $sthorders->execute; - my @fields = map { - $sthorders->{mysql_table}[$_] . "." . $sthorders->{NAME}[$_] } - (0 .. $#{$sthorders->{NAME}} ) ; - - my @orders_infos; - while ( my $row = $sthorders->fetchrow_arrayref() ) { - my %rec = (); - @rec{@fields} = @$row; - push @orders_infos, \%rec; + my $dataorders = $sthorders->fetchall_arrayref( {} ); + + my $sthbookseller = + $dbh->prepare("select * from aqbooksellers where id=?"); + $sthbookseller->execute( $dataorders->[0]->{booksellerid} ); + my $databookseller = $sthbookseller->fetchrow_hashref; + + my @email; + push @email, $databookseller->{bookselleremail} if $databookseller->{bookselleremail}; + push @email, $databookseller->{contemail} if $databookseller->{contemail}; + unless (@email) { + warn "Bookseller $dataorders->[0]->{booksellerid} without emails"; + return; } - # parsing branch info my $userenv = C4::Context->userenv; - parseletter( $letter, 'branches', $userenv->{branch} ); - - # parsing librarian name - $letter->{content} =~ s/<>/$userenv->{firstname}/g; - $letter->{content} =~ s/<>/$userenv->{surname}/g; - $letter->{content} =~ s/<>/$userenv->{emailaddress}/g; - - # Get Fields remplacement - my $order_format = $1 if ( $letter->{content} =~ m/(.*<\/order>)/xms ); - - # Foreach field to remplace - while ( $letter->{content} =~ m/<<([^>]*)>>/g ) { - my $field = $1; - my $value = $orders_infos[0]->{$field} || ""; - $value = sprintf("%.2f", $value) if $field =~ /price/; - $letter->{content} =~ s/<<$field>>/$value/g; - } - - if ( $order_format ) { - # For each order - foreach my $infos ( @orders_infos ) { - my $order_content = $order_format; - # We replace by value - while ( $order_content =~ m/<<([^>]*)>>/g ) { - my $field = $1; - my $value = $infos->{$field} || ""; - $value = sprintf("%.2f", $value) if $field =~ /price/; - $order_content =~ s/(<<$field>>)/$value/g; - } - $order_content =~ s/<\/{0,1}?order>//g; - $letter->{content} =~ s/.*<\/order>/$order_content\n$order_format/xms; - } - $letter->{content} =~ s/.*<\/order>//xms; - } - - my $innerletter = $letter; + my $letter = GetPreparedLetter ( + module => $type, + letter_code => $letter_code, + branchcode => $userenv->{branch}, + tables => { + 'branches' => $userenv->{branch}, + 'aqbooksellers' => $databookseller, + }, + repeat => $dataorders, + want_librarian => 1, + ) or return; # ... then send mail - if ( $orders_infos[0]->{'aqbooksellers.bookselleremail'} - || $orders_infos[0]->{'aqbooksellers.contemail'} ) { - my $to = $orders_infos[0]->{'aqbooksellers.bookselleremail'}; - $to .= ", " if $to; - $to .= $orders_infos[0]->{'aqbooksellers.contemail'} || ""; - my %mail = ( - To => $to, - From => $userenv->{emailaddress}, - Subject => Encode::encode( "utf8", "" . $innerletter->{title} ), - Message => Encode::encode( "utf8", "" . $innerletter->{content} ), - 'Content-Type' => 'text/plain; charset="utf8"', - ); - sendmail(%mail) or carp $Mail::Sendmail::error; - warn "sending to $mail{To} From $mail{From} subj $mail{Subject} Mess $mail{Message}" if $debug; - if ( C4::Context->preference("LetterLog") ) { - logaction( "ACQUISITION", "Send Acquisition claim letter", "", "order list : " . join( ",", @$externalid ) . "\n$innerletter->{title}\n$innerletter->{content}" ) if $type eq 'claimacquisition'; - logaction( "ACQUISITION", "CLAIM ISSUE", undef, "To=" . $mail{To} . " Title=" . $innerletter->{title} . " Content=" . $innerletter->{content} ) if $type eq 'claimissues'; - } - } else { - return {error => "no_email" }; - } - - warn "sending to From $userenv->{emailaddress} subj $innerletter->{title} Mess $innerletter->{content}" if $debug; - } + my %mail = ( + To => join( ','. @email), + From => $userenv->{emailaddress}, + Subject => "" . $letter->{title}, + Message => "" . $letter->{content}, + 'Content-Type' => 'text/plain; charset="utf8"', + ); + sendmail(%mail) or carp $Mail::Sendmail::error; - # send an "account details" notice to a newly created user + logaction( + "ACQUISITION", + $type eq 'claimissues' ? "CLAIM ISSUE" : "ACQUISITION CLAIM", + undef, + "To=" + . $databookseller->{contemail} + . " Title=" + . $letter->{title} + . " Content=" + . $letter->{content} + ) if C4::Context->preference("LetterLog"); + } + # send an "account details" notice to a newly created user elsif ( $type eq 'members' ) { - # must parse the password special, before it's hashed. - $letter->{content} =~ s/<>/$externalid->{'password'}/g; - - parseletter( $letter, 'borrowers', $externalid->{'borrowernumber'}); - parseletter( $letter, 'branches', $externalid->{'branchcode'} ); - my $branchdetails = GetBranchDetail($externalid->{'branchcode'}); + my $letter = GetPreparedLetter ( + module => 'members', + letter_code => $letter_code, + branchcode => $externalid->{'branchcode'}, + tables => { + 'branches' => $branchdetails, + 'borrowers' => $externalid->{'borrowernumber'}, + }, + substitute => { 'borrowers.password' => $externalid->{'password'} }, + want_librarian => 1, + ) or return; + my %mail = ( To => $externalid->{'emailaddr'}, From => $branchdetails->{'branchemail'} || C4::Context->preference("KohaAdminEmailAddress"), @@ -425,24 +403,148 @@ sub SendAlerts { } } -=head2 parseletter($letter, $table, $pk) - - parameters : - - $letter : a hash to letter fields (title & content useful) - - $table : the Koha table to parse. - - $pk : the primary key to query on the $table table - parse all fields from a table, and replace values in title & content with the appropriate value - (not exported sub, used only internally) +=head2 GetPreparedLetter( %params ) + + %params hash: + module => letter module, mandatory + letter_code => letter code, mandatory + branchcode => for letter selection, if missing default system letter taken + tables => a hashref with table names as keys. Values are either: + - a scalar - primary key value + - an arrayref - primary key values + - a hashref - full record + substitute => custom substitution key/value pairs + repeat => records to be substituted on consecutive lines: + - an arrayref - tries to guess what needs substituting by + taking remaining << >> tokensr; not recommended + - a hashref token => @tables - replaces << >> << >> + subtemplate for each @tables row; table is a hashref as above + want_librarian => boolean, if set to true triggers librarian details + substitution from the userenv + Return value: + letter fields hashref (title & content useful) =cut -our %handles = (); -our %columns = (); +sub GetPreparedLetter { + my %params = @_; + + my $module = $params{module} or croak "No module"; + my $letter_code = $params{letter_code} or croak "No letter_code"; + my $branchcode = $params{branchcode} || ''; + + my $letter = getletter( $module, $letter_code, $branchcode ) + or warn( "No $module $letter_code letter"), + return; -sub parseletter_sth { + my $tables = $params{tables}; + my $substitute = $params{substitute}; + my $repeat = $params{repeat}; + $tables || $substitute || $repeat + or carp( "ERROR: nothing to substitute - both 'tables' and 'substitute' are empty" ), + return; + my $want_librarian = $params{want_librarian}; + + if ($substitute) { + while ( my ($token, $val) = each %$substitute ) { + $letter->{title} =~ s/<<$token>>/$val/g; + $letter->{content} =~ s/<<$token>>/$val/g; + } + } + + if ($want_librarian) { + # parsing librarian name + my $userenv = C4::Context->userenv; + $letter->{content} =~ s/<>/$userenv->{firstname}/go; + $letter->{content} =~ s/<>/$userenv->{surname}/go; + $letter->{content} =~ s/<>/$userenv->{emailaddress}/go; + } + + my ($repeat_no_enclosing_tags, $repeat_enclosing_tags); + + if ($repeat) { + if (ref ($repeat) eq 'ARRAY' ) { + $repeat_no_enclosing_tags = $repeat; + } else { + $repeat_enclosing_tags = $repeat; + } + } + + if ($repeat_enclosing_tags) { + while ( my ($tag, $tag_tables) = each %$repeat_enclosing_tags ) { + if ( $letter->{content} =~ m!<$tag>(.*)!s ) { + my $subcontent = $1; + my @lines = map { + my %subletter = ( title => '', content => $subcontent ); + _substitute_tables( \%subletter, $_ ); + $subletter{content}; + } @$tag_tables; + $letter->{content} =~ s!<$tag>.*!join( "\n", @lines )!se; + } + } + } + + if ($tables) { + _substitute_tables( $letter, $tables ); + } + + if ($repeat_no_enclosing_tags) { + if ( $letter->{content} =~ m/[^\n]*<<.*>>[^\n]*/so ) { + my $line = $&; + my $i = 1; + my @lines = map { + my $c = $line; + $c =~ s/<>/$i/go; + foreach my $field ( keys %{$_} ) { + $c =~ s/(<<[^\.]+.$field>>)/$_->{$field}/; + } + $i++; + $c; + } @$repeat_no_enclosing_tags; + + my $replaceby = join( "\n", @lines ); + $letter->{content} =~ s/\Q$line\E/$replaceby/s; + } + } + + $letter->{content} =~ s/<<\S*>>//go; #remove any stragglers +# $letter->{content} =~ s/<<[^>]*>>//go; + + return $letter; +} + +sub _substitute_tables { + my ( $letter, $tables ) = @_; + while ( my ($table, $param) = each %$tables ) { + next unless $param; + + my $ref = ref $param; + + my $values; + if ($ref && $ref eq 'HASH') { + $values = $param; + } + else { + my @pk; + my $sth = _parseletter_sth($table); + unless ($sth) { + warn "_parseletter_sth('$table') failed to return a valid sth. No substitution will be done for that table."; + return; + } + $sth->execute( $ref ? @$param : $param ); + + $values = $sth->fetchrow_hashref; + } + + _parseletter ( $letter, $table, $values ); + } +} + +my %handles = (); +sub _parseletter_sth { my $table = shift; unless ($table) { - carp "ERROR: parseletter_sth() called without argument (table)"; + carp "ERROR: _parseletter_sth() called without argument (table)"; return; } # check cache first @@ -456,9 +558,12 @@ sub parseletter_sth { ($table eq 'borrowers' ) ? "SELECT * FROM $table WHERE borrowernumber = ?" : ($table eq 'branches' ) ? "SELECT * FROM $table WHERE branchcode = ?" : ($table eq 'suggestions' ) ? "SELECT * FROM $table WHERE suggestionid = ?" : - ($table eq 'aqbooksellers') ? "SELECT * FROM $table WHERE id = ?" : undef ; + ($table eq 'aqbooksellers') ? "SELECT * FROM $table WHERE id = ?" : + ($table eq 'aqorders' ) ? "SELECT * FROM $table WHERE ordernumber = ?" : + ($table eq 'opac_news' ) ? "SELECT * FROM $table WHERE idnew = ?" : + undef ; unless ($query) { - warn "ERROR: No parseletter_sth query for table '$table'"; + warn "ERROR: No _parseletter_sth query for table '$table'"; return; # nothing to get } unless ($handles{$table} = C4::Context->dbh->prepare($query)) { @@ -468,25 +573,21 @@ sub parseletter_sth { return $handles{$table}; # now cache is populated for that $table } -sub parseletter { - my ( $letter, $table, $pk, $pk2 ) = @_; - unless ($letter) { - carp "ERROR: parseletter() 1st argument 'letter' empty"; - return; - } - my $sth = parseletter_sth($table); - unless ($sth) { - warn "parseletter_sth('$table') failed to return a valid sth. No substitution will be done for that table."; - return; - } - if ( $pk2 ) { - $sth->execute($pk, $pk2); - } else { - $sth->execute($pk); - } +=head2 _parseletter($letter, $table, $values) - my $values = $sth->fetchrow_hashref; - + parameters : + - $letter : a hash to letter fields (title & content useful) + - $table : the Koha table to parse. + - $values : table record hashref + parse all fields from a table, and replace values in title & content with the appropriate value + (not exported sub, used only internally) + +=cut + +my %columns = (); +sub _parseletter { + my ( $letter, $table, $values ) = @_; + # TEMPORARY hack until the expirationdate column is added to reserves if ( $table eq 'reserves' && $values->{'waitingdate'} ) { my @waitingdate = split /-/, $values->{'waitingdate'}; @@ -500,16 +601,51 @@ sub parseletter { )->output(); } + if ($letter->{content} && $letter->{content} =~ /<>/) { + my @da = localtime(); + my $todaysdate = "$da[2]:$da[1] " . C4::Dates->today(); + $letter->{content} =~ s/<>/$todaysdate/go; + } # and get all fields from the table - my $columns = C4::Context->dbh->prepare("SHOW COLUMNS FROM $table"); - $columns->execute; - while ( ( my $field ) = $columns->fetchrow_array ) { - my $replacefield = "<<$table.$field>>"; - $values->{$field} =~ s/\p{P}(?=$)//g if $values->{$field}; - my $replacedby = $values->{$field} || ''; - ($letter->{title} ) and $letter->{title} =~ s/$replacefield/$replacedby/g; - ($letter->{content}) and $letter->{content} =~ s/$replacefield/$replacedby/g; +# my $columns = $columns{$table}; +# unless ($columns) { +# $columns = $columns{$table} = C4::Context->dbh->selectcol_arrayref("SHOW COLUMNS FROM $table"); +# } +# foreach my $field (@$columns) { + + while ( my ($field, $val) = each %$values ) { + my $replacetablefield = "<<$table.$field>>"; + my $replacefield = "<<$field>>"; + $val =~ s/\p{P}(?=$)//g if $val; + my $replacedby = defined ($val) ? $val : ''; + ($letter->{title} ) and do { + $letter->{title} =~ s/$replacetablefield/$replacedby/g; + $letter->{title} =~ s/$replacefield/$replacedby/g; + }; + ($letter->{content}) and do { + $letter->{content} =~ s/$replacetablefield/$replacedby/g; + $letter->{content} =~ s/$replacefield/$replacedby/g; + }; + } + + if ($table eq 'borrowers' && $letter->{content}) { + if ( my $attributes = GetBorrowerAttributes($values->{borrowernumber}) ) { + my %attr; + foreach (@$attributes) { + my $code = $_->{code}; + my $val = $_->{value_description} || $_->{value}; + $val =~ s/\p{P}(?=$)//g if $val; + next unless $val gt ''; + $attr{$code} ||= []; + push @{ $attr{$code} }, $val; + } + while ( my ($code, $val_ar) = each %attr ) { + my $replacefield = "<>"; + my $replacedby = join ',', @$val_ar; + $letter->{content} =~ s/$replacefield/$replacedby/g; + } + } } return $letter; } @@ -694,31 +830,32 @@ returns your letter object, with the content updated. sub _add_attachments { my $params = shift; - return unless 'HASH' eq ref $params; - foreach my $required_parameter (qw( letter attachments message )) { - return unless exists $params->{$required_parameter}; - } - return $params->{'letter'} unless @{ $params->{'attachments'} }; + my $letter = $params->{'letter'}; + my $attachments = $params->{'attachments'}; + return $letter unless @$attachments; + my $message = $params->{'message'}; # First, we have to put the body in as the first attachment - $params->{'message'}->attach( - Type => 'TEXT', - Data => $params->{'letter'}->{'content'}, + $message->attach( + Type => $letter->{'content-type'} || 'TEXT', + Data => $letter->{'is_html'} + ? _wrap_html($letter->{'content'}, $letter->{'title'}) + : $letter->{'content'}, ); - foreach my $attachment ( @{ $params->{'attachments'} } ) { - $params->{'message'}->attach( + foreach my $attachment ( @$attachments ) { + $message->attach( Type => $attachment->{'type'}, Data => $attachment->{'content'}, Filename => $attachment->{'filename'}, ); } # we're forcing list context here to get the header, not the count back from grep. - ( $params->{'letter'}->{'content-type'} ) = grep( /^Content-Type:/, split( /\n/, $params->{'message'}->header_as_string ) ); - $params->{'letter'}->{'content-type'} =~ s/^Content-Type:\s+//; - $params->{'letter'}->{'content'} = $params->{'message'}->body_as_string; + ( $letter->{'content-type'} ) = grep( /^Content-Type:/, split( /\n/, $params->{'message'}->header_as_string ) ); + $letter->{'content-type'} =~ s/^Content-Type:\s+//; + $letter->{'content'} = $message->body_as_string; - return $params->{'letter'}; + return $letter; } @@ -785,14 +922,17 @@ sub _send_message_by_email ($;$$$) { my $utf8 = decode('MIME-Header', $message->{'subject'} ); $message->{subject}= encode('MIME-Header', $utf8); + my $subject = encode('utf8', $message->{'subject'}); my $content = encode('utf8', $message->{'content'}); + my $content_type = $message->{'content_type'} || 'text/plain; charset="UTF-8"'; + my $is_html = $content_type =~ m/html/io; my %sendmail_params = ( To => $to_address, From => $message->{'from_address'} || C4::Context->preference('KohaAdminEmailAddress'), - Subject => encode('utf8', $message->{'subject'}), + Subject => $subject, charset => 'utf8', - Message => $content, - 'content-type' => $message->{'content_type'} || 'text/plain; charset="UTF-8"', + Message => $is_html ? _wrap_html($content, $subject) : $content, + 'content-type' => $content_type, ); $sendmail_params{'Auth'} = {user => $username, pass => $password, method => $method} if $username; if ( my $bcc = C4::Context->preference('OverdueNoticeBcc') ) { @@ -812,6 +952,27 @@ sub _send_message_by_email ($;$$$) { } } +sub _wrap_html { + my ($content, $title) = @_; + + my $css = C4::Context->preference("NoticeCSS") || ''; + $css = qq{} if $css; + return < + + +$title + +$css + + +$content + + +EOS +} + sub _send_message_by_sms ($) { my $message = shift or return undef; my $member = C4::Members::GetMember( 'borrowernumber' => $message->{'borrowernumber'} ); diff --git a/C4/Members.pm b/C4/Members.pm index b81872c..7def77e 100644 --- a/C4/Members.pm +++ b/C4/Members.pm @@ -23,7 +23,7 @@ package C4::Members; use strict; #use warnings; FIXME - Bug 2505 use C4::Context; -use C4::Dates qw(format_date_in_iso); +use C4::Dates qw(format_date_in_iso format_date); use Digest::MD5 qw(md5_base64); use Date::Calc qw/Today Add_Delta_YM check_date Date_to_Days/; use C4::Log; # logaction @@ -31,8 +31,10 @@ use C4::Overdues; use C4::Reserves; use C4::Accounts; use C4::Biblio; +use C4::Letters; use C4::SQLHelper qw(InsertInTable UpdateInTable SearchInTable); use C4::Members::Attributes qw(SearchIdMatchingAttribute); +use C4::NewsChannels; #get slip news our ($VERSION,@ISA,@EXPORT,@EXPORT_OK,$debug); @@ -91,6 +93,8 @@ BEGIN { &DeleteMessage &GetMessages &GetMessagesCount + + &IssueSlip ); #Modify data @@ -2229,7 +2233,80 @@ sub DeleteMessage { logaction("MEMBERS", "DELCIRCMESSAGE", $message->{'borrowernumber'}, $message->{'message'}) if C4::Context->preference("BorrowersLog"); } -END { } # module clean-up code here (global destructor) +=head2 IssueSlip + + IssueSlip($branchcode, $borrowernumber, $quickslip) + + Returns letter hash ( see C4::Letters::GetPreparedLetter ) + + $quickslip is boolean, to indicate whether we want a quick slip + +=cut + +sub IssueSlip { + my ($branch, $borrowernumber, $quickslip) = @_; + +# return unless ( C4::Context->boolean_preference('printcirculationslips') ); + + my $today = POSIX::strftime("%Y-%m-%d", localtime); + + my $issueslist = GetPendingIssues($borrowernumber); + foreach my $it (@$issueslist){ + if ($it->{'issuedate'} eq $today) { + $it->{'today'} = 1; + } + elsif ($it->{'date_due'} le $today) { + $it->{'overdue'} = 1; + } + + $it->{'date_due'}=format_date($it->{'date_due'}); + } + my @issues = sort { $b->{'timestamp'} <=> $a->{'timestamp'} } @$issueslist; + + my ($letter_code, %repeat); + if ( $quickslip ) { + $letter_code = 'ISSUEQSLIP'; + %repeat = ( + 'checkedout' => [ map { + 'biblio' => $_, + 'items' => $_, + 'issues' => $_, + }, grep { $_->{'today'} } @issues ], + ); + } + else { + $letter_code = 'ISSUESLIP'; + %repeat = ( + 'checkedout' => [ map { + 'biblio' => $_, + 'items' => $_, + 'issues' => $_, + }, grep { !$_->{'overdue'} } @issues ], + + 'overdue' => [ map { + 'biblio' => $_, + 'items' => $_, + 'issues' => $_, + }, grep { $_->{'overdue'} } @issues ], + + 'news' => [ map { + $_->{'timestamp'} = $_->{'newdate'}; + { opac_news => $_ } + } @{ GetNewsToDisplay("slip") } ], + ); + } + + return C4::Letters::GetPreparedLetter ( + module => 'circulation', + letter_code => $letter_code, + branchcode => $branch, + tables => { + 'branches' => $branch, + 'borrowers' => $borrowernumber, + }, + repeat => \%repeat, + ); +} 1; diff --git a/C4/Members/Attributes.pm b/C4/Members/Attributes.pm index 4ae5600..33affa8 100644 --- a/C4/Members/Attributes.pm +++ b/C4/Members/Attributes.pm @@ -95,6 +95,24 @@ sub GetBorrowerAttributes { return \@results; } +=head2 GetAttributes + + my $attributes = C4::Members::Attributes::GetAttributes([$opac_only]); + +Retrieve an arrayref of extended attribute codes + +=cut + +sub GetAttributes { + my ($opac_only) = @_; + + my $dbh = C4::Context->dbh(); + my $query = "SELECT code FROM borrower_attribute_types"; + $query .= "\nWHERE opac_display = 1" if $opac_only; + $query .= "\nORDER BY code"; + return $dbh->selectcol_arrayref($query); +} + =head2 GetBorrowerAttributeValue my $value = C4::Members::Attributes::GetBorrowerAttributeValue($borrowernumber, $attribute_code); diff --git a/C4/Message.pm b/C4/Message.pm index 16272ff..4b88970 100644 --- a/C4/Message.pm +++ b/C4/Message.pm @@ -18,9 +18,15 @@ How to add a new message to the queue: use C4::Items; my $borrower = { borrowernumber => 1 }; my $item = C4::Items::GetItem(1); - my $letter = C4::Letters::getletter('circulation', 'CHECKOUT'); - C4::Letters::parseletter($letter, 'biblio', $item->{biblionumber}); - C4::Letters::parseletter($letter, 'biblioitems', $item->{biblionumber}); + my $letter = C4::Letters::GetPreparedLetter ( + module => 'circulation', + letter_code => 'CHECKOUT', + branchcode => $branch, + tables => { + 'biblio', $item->{biblionumber}, + 'biblioitems', $item->{biblionumber}, + }, + ); C4::Message->enqueue($letter, $borrower->{borrowernumber}, 'email'); How to update a borrower's last checkout message: diff --git a/C4/Print.pm b/C4/Print.pm index f810816..7fb55cf 100644 --- a/C4/Print.pm +++ b/C4/Print.pm @@ -20,8 +20,6 @@ package C4::Print; use strict; #use warnings; FIXME - Bug 2505 use C4::Context; -use C4::Members; -use C4::Dates qw(format_date); use vars qw($VERSION @ISA @EXPORT); @@ -30,7 +28,7 @@ BEGIN { $VERSION = 3.01; require Exporter; @ISA = qw(Exporter); - @EXPORT = qw(&remoteprint &printreserve &printslip); + @EXPORT = qw(&printslip); } =head1 NAME @@ -47,28 +45,48 @@ The functions in this module handle sending text to a printer. =head1 FUNCTIONS -=head2 remoteprint +=cut - &remoteprint($items, $borrower); +=comment + my $slip = <<"EOF"; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Date: $todaysdate; -Prints the list of items in C<$items> to a printer. +ITEM RESERVED: +$itemdata->{'title'} ($itemdata->{'author'}) +barcode: $itemdata->{'barcode'} -C<$borrower> is a reference-to-hash giving information about a patron. -This may be gotten from C<&GetMemberDetails>. The patron's name -will be printed in the output. +COLLECT AT: $branchname + +BORROWER: +$bordata->{'surname'}, $bordata->{'firstname'} +card number: $bordata->{'cardnumber'} +Phone: $bordata->{'phone'} +$bordata->{'streetaddress'} +$bordata->{'suburb'} +$bordata->{'town'} +$bordata->{'emailaddress'} -C<$items> is a reference-to-list, where each element is a -reference-to-hash describing a borrowed item. C<$items> may be gotten -from C<&GetBorrowerIssues>. +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +EOF =cut +=head2 printslip + + &printslip($slip) + +print a slip for the given $borrowernumber and $branchcode + +=cut + +sub printslip ($) { + my ($slip) = @_; + + return unless ( C4::Context->boolean_preference('printcirculationslips') ); + # FIXME - It'd be nifty if this could generate pretty PostScript. -sub remoteprint ($$) { - my ($items, $borrower) = @_; - (return) - unless ( C4::Context->boolean_preference('printcirculationslips') ); my $queue = ''; # FIXME - If 'queue' is undefined or empty, then presumably it should @@ -94,107 +112,13 @@ sub remoteprint ($$) { # print $queue; #open (FILE,">/tmp/$file"); - my $i = 0; - # FIXME - This is HLT-specific. Put this stuff in a customizable - # site-specific file somewhere. - print PRINTER "Horowhenua Library Trust\r\n"; - print PRINTER "Phone: 368-1953\r\n"; - print PRINTER "Fax: 367-9218\r\n"; - print PRINTER "Email: renewals\@library.org.nz\r\n\r\n\r\n"; - print PRINTER "$borrower->{'cardnumber'}\r\n"; - print PRINTER - "$borrower->{'title'} $borrower->{'initials'} $borrower->{'surname'}\r\n"; - - # FIXME - Use for ($i = 0; $items->[$i]; $i++) - # Or better yet, foreach $item (@{$items}) - while ( $items->[$i] ) { - - # print $i; - my $itemdata = $items->[$i]; - - # FIXME - This is just begging for a Perl format. - print PRINTER "$i $itemdata->{'title'}\r\n"; - print PRINTER "$itemdata->{'barcode'}"; - print PRINTER " " x 15; - print PRINTER "$itemdata->{'date_due'}\r\n"; - $i++; - } + print PRINTER $slip; print PRINTER "\r\n" x 7 ; close PRINTER; #system("lpr /tmp/$file"); } -sub printreserve { - - # FIXME - make useful - return; - - my ( $branchname, $bordata, $itemdata ) = @_; - my $printer = ''; - (return) unless ( C4::Context->boolean_preference('printreserveslips') ); - if ( $printer eq "" || $printer eq 'nulllp' ) { - open( PRINTER, ">>/tmp/kohares" ) - or die "Could not write to /tmp/kohares"; - } - else { - open( PRINTER, "| lpr -P $printer >/dev/null" ) - or die "Couldn't write to queue:$!\n"; - } - my @da = localtime(); - my $todaysdate = "$da[2]:$da[1] " . C4::Dates->today(); - my $slip = <<"EOF"; -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Date: $todaysdate; - -ITEM RESERVED: -$itemdata->{'title'} ($itemdata->{'author'}) -barcode: $itemdata->{'barcode'} - -COLLECT AT: $branchname - -BORROWER: -$bordata->{'surname'}, $bordata->{'firstname'} -card number: $bordata->{'cardnumber'} -Phone: $bordata->{'phone'} -$bordata->{'streetaddress'} -$bordata->{'suburb'} -$bordata->{'town'} -$bordata->{'emailaddress'} - - -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -EOF - print PRINTER $slip; - close PRINTER; - return $slip; -} - -=head2 printslip - - &printslip($borrowernumber) - -print a slip for the given $borrowernumber - -=cut - -#' -sub printslip ($) { - - #FIXME - make useful - - my $borrowernumber = shift; - my $borrower = GetMemberDetails($borrowernumber); - my $issueslist = GetPendingIssues($borrowernumber); - foreach my $it (@$issueslist){ - $it->{'date_due'}=format_date($it->{'date_due'}); - } - my @issues = sort { $b->{'timestamp'} <=> $a->{'timestamp'} } @$issueslist; - remoteprint(\@issues, $borrower ); -} - -END { } # module clean-up code here (global destructor) - 1; __END__ diff --git a/C4/Reserves.pm b/C4/Reserves.pm index 359bbad..d2af1c5 100644 --- a/C4/Reserves.pm +++ b/C4/Reserves.pm @@ -121,6 +121,8 @@ BEGIN { &AlterPriority &ToggleLowestPriority + + &ReserveSlip ); @EXPORT_OK = qw( MergeHolds ); } @@ -194,32 +196,31 @@ sub AddReserve { # Send e-mail to librarian if syspref is active if(C4::Context->preference("emailLibrarianWhenHoldIsPlaced")){ my $borrower = C4::Members::GetMember(borrowernumber => $borrowernumber); - my $biblio = GetBiblioData($biblionumber); - my $letter = C4::Letters::getletter( 'reserves', 'HOLDPLACED'); - my $branchcode = $borrower->{branchcode}; - my $branch_details = C4::Branch::GetBranchDetail($branchcode); - my $admin_email_address =$branch_details->{'branchemail'} || C4::Context->preference('KohaAdminEmailAddress'); - - my %keys = (%$borrower, %$biblio); - foreach my $key (keys %keys) { - my $replacefield = "<<$key>>"; - $letter->{content} =~ s/$replacefield/$keys{$key}/g; - $letter->{title} =~ s/$replacefield/$keys{$key}/g; + my $branch_details = C4::Branch::GetBranchDetail($borrower->{branchcode}); + if ( my $letter = C4::Letters::GetPreparedLetter ( + module => 'reserves', + letter_code => 'HOLDPLACED', + branchcode => $branch, + tables => { + 'branches' => $branch_details, + 'borrowers' => $borrower, + 'biblio' => $biblionumber, + }, + ) ) { + + my $admin_email_address =$branch_details->{'branchemail'} || C4::Context->preference('KohaAdminEmailAddress'); + + C4::Letters::EnqueueLetter( + { letter => $letter, + borrowernumber => $borrowernumber, + message_transport_type => 'email', + from_address => $admin_email_address, + to_address => $admin_email_address, + } + ); } - - C4::Letters::EnqueueLetter( - { letter => $letter, - borrowernumber => $borrowernumber, - message_transport_type => 'email', - from_address => $admin_email_address, - to_address => $admin_email_address, - } - ); - - } - #} ($const eq "o" || $const eq "e") or return; # FIXME: why not have a useful return value? $query = qq/ @@ -1720,21 +1721,21 @@ sub _koha_notify_reserve { my $admin_email_address = $branch_details->{'branchemail'} || C4::Context->preference('KohaAdminEmailAddress'); - my $letter = getletter( 'reserves', $letter_code ); - die "Could not find a letter called '$letter_code' in the 'reserves' module" unless( $letter ); + my $letter = C4::Letters::GetPreparedLetter ( + module => 'reserves', + letter_code => $letter_code, + branchcode => $reserve->{branchcode}, + tables => { + 'branches' => $branch_details, + 'borrowers' => $borrower, + 'biblio' => $biblionumber, + 'reserves' => $reserve, + 'items', $reserve->{'itemnumber'}, + }, + substitute => { today => C4::Dates->new()->output() }, + ) or die "Could not find a letter called '$letter_code' in the 'reserves' module"; - C4::Letters::parseletter( $letter, 'branches', $reserve->{'branchcode'} ); - C4::Letters::parseletter( $letter, 'borrowers', $borrowernumber ); - C4::Letters::parseletter( $letter, 'biblio', $biblionumber ); - C4::Letters::parseletter( $letter, 'reserves', $borrowernumber, $biblionumber ); - if ( $reserve->{'itemnumber'} ) { - C4::Letters::parseletter( $letter, 'items', $reserve->{'itemnumber'} ); - } - my $today = C4::Dates->new()->output(); - $letter->{'title'} =~ s/<>/$today/g; - $letter->{'content'} =~ s/<>/$today/g; - $letter->{'content'} =~ s/<<[a-z0-9_]+\.[a-z0-9]+>>//g; #remove any stragglers if ( $print_mode ) { C4::Letters::EnqueueLetter( { @@ -1908,6 +1909,36 @@ sub MergeHolds { } +=head2 ReserveSlip + + ReserveSlip($branchcode, $borrowernumber, $biblionumber) + + Returns letter hash ( see C4::Letters::GetPreparedLetter ) or undef + +=cut + +sub ReserveSlip { + my ($branch, $borrowernumber, $biblionumber) = @_; + +# return unless ( C4::Context->boolean_preference('printreserveslips') ); + + my $reserve = GetReserveInfo($borrowernumber,$biblionumber ) + or return; + + return C4::Letters::GetPreparedLetter ( + module => 'circulation', + letter_code => 'RESERVESLIP', + branchcode => $branch, + tables => { + 'reserves' => $reserve, + 'branches' => $reserve->{branchcode}, + 'borrowers' => $reserve, + 'biblio' => $reserve, + 'items' => $reserve, + }, + ); +} + =head1 AUTHOR Koha Development Team diff --git a/C4/Suggestions.pm b/C4/Suggestions.pm index c9461f5..60d0e99 100644 --- a/C4/Suggestions.pm +++ b/C4/Suggestions.pm @@ -425,20 +425,24 @@ sub ModSuggestion { if ($suggestion->{STATUS}) { # fetch the entire updated suggestion so that we can populate the letter my $full_suggestion = GetSuggestion($suggestion->{suggestionid}); - my $letter = C4::Letters::getletter('suggestions', $full_suggestion->{STATUS}); - if ($letter) { - C4::Letters::parseletter($letter, 'branches', $full_suggestion->{branchcode}); - C4::Letters::parseletter($letter, 'borrowers', $full_suggestion->{suggestedby}); - C4::Letters::parseletter($letter, 'suggestions', $full_suggestion->{suggestionid}); - C4::Letters::parseletter($letter, 'biblio', $full_suggestion->{biblionumber}); - my $enqueued = C4::Letters::EnqueueLetter({ + if ( my $letter = C4::Letters::GetPreparedLetter ( + module => 'suggestions', + letter_code => $full_suggestion->{STATUS}, + branchcode => $full_suggestion->{branchcode}, + tables => { + 'branches' => $full_suggestion->{branchcode}, + 'borrowers' => $full_suggestion->{suggestedby}, + 'suggestions' => $full_suggestion, + 'biblio' => $full_suggestion->{biblionumber}, + }, + ) ) { + C4::Letters::EnqueueLetter({ letter => $letter, borrowernumber => $full_suggestion->{suggestedby}, suggestionid => $full_suggestion->{suggestionid}, LibraryName => C4::Context->preference("LibraryName"), message_transport_type => 'email', - }); - if (!$enqueued){warn "can't enqueue letter $letter";} + }) or warn "can't enqueue letter $letter"; } } return $status_update_table; diff --git a/acqui/booksellers.pl b/acqui/booksellers.pl index d7c64db..ac3c557 100755 --- a/acqui/booksellers.pl +++ b/acqui/booksellers.pl @@ -111,16 +111,11 @@ for my $vendor (@suppliers) { for my $basket ( @{$baskets} ) { my $authorisedby = $basket->{authorisedby}; - my $basketbranch = ''; # set a blank branch to start with - if ( GetMember( borrowernumber => $authorisedby ) ) { - # authorisedby may not be a valid borrowernumber; it's not foreign-key constrained! - $basketbranch = GetMember( borrowernumber => $authorisedby )->{branchcode}; - } if ($userenv->{'flags'} & 1 || #user is superlibrarian (haspermission( $uid, { acquisition => q{*} } ) && #user has acq permissions and ($viewbaskets eq 'all' || #user is allowed to see all baskets - ($viewbaskets eq 'branch' && $authorisedby && $userbranch eq $basketbranch) || #basket belongs to user's branch + ($viewbaskets eq 'branch' && $authorisedby && $userbranch eq GetMember( borrowernumber => $authorisedby )->{branchcode}) || #basket belongs to user's branch ($basket->{authorisedby} && $viewbaskets == 'user' && $authorisedby == $loggedinuser) #user created this basket ) ) diff --git a/circ/circulation.pl b/circ/circulation.pl index e8d22cb..6928966 100755 --- a/circ/circulation.pl +++ b/circ/circulation.pl @@ -24,7 +24,6 @@ use strict; #use warnings; FIXME - Bug 2505 use CGI; use C4::Output; -use C4::Print; use C4::Auth qw/:DEFAULT get_session/; use C4::Dates qw/format_date/; use C4::Branch; # GetBranches @@ -176,7 +175,7 @@ if ( $barcode eq '' && $query->param('charges') eq 'yes' ) { } if ( $print eq 'yes' && $borrowernumber ne '' ) { - printslip( $borrowernumber ); + PrintIssueSlip($session->param('branch') || $branch, $borrowernumber); $query->param( 'borrowernumber', '' ); $borrowernumber = ''; } diff --git a/circ/hold-transfer-slip.pl b/circ/hold-transfer-slip.pl index f581464..8ae5d2a 100755 --- a/circ/hold-transfer-slip.pl +++ b/circ/hold-transfer-slip.pl @@ -23,10 +23,8 @@ use strict; use C4::Context; use C4::Output; use CGI; -use C4::Auth; +use C4::Auth qw/:DEFAULT get_session/; use C4::Reserves; -use C4::Branch; -use C4::Dates qw/format_date format_date_in_iso/; use vars qw($debug); @@ -35,13 +33,16 @@ BEGIN { } my $input = new CGI; +my $sessionID = $input->cookie("CGISESSID"); +my $session = get_session($sessionID); + my $biblionumber = $input->param('biblionumber'); my $borrowernumber = $input->param('borrowernumber'); my $transfer = $input->param('transfer'); my ( $template, $loggedinuser, $cookie ) = get_template_and_user( { - template_name => "circ/hold-transfer-slip.tmpl", + template_name => "circ/printslip.tmpl", query => $input, type => "intranet", authnotrequired => 0, @@ -50,14 +51,21 @@ my ( $template, $loggedinuser, $cookie ) = get_template_and_user( } ); -my $reserveinfo = GetReserveInfo($borrowernumber,$biblionumber ); -my $pulldate = C4::Dates->new(); -$reserveinfo->{'pulldate'} = $pulldate->output(); -$reserveinfo->{'branchname'} = GetBranchName($reserveinfo->{'branchcode'}); -$reserveinfo->{'transferrequired'} = $transfer; - -$template->param( reservedata => [ $reserveinfo ] , - ); +my $userenv = C4::Context->userenv; +my ($slip, $is_html); +if ( my $letter = ReserveSlip ($session->param('branch') || $userenv->{branch}, $borrowernumber, $biblionumber) ) { + $slip = $letter->{content}; + $is_html = $letter->{is_html}; +} +else { + $slip = "Reserve not found"; +} +$template->param( + slip => $slip, + plain => !$is_html, + title => "Koha -- Circulation: Transfers", + stylesheet => C4::Context->preference("SlipCSS"), +); output_html_with_http_headers $input, $cookie, $template->output; diff --git a/installer/data/mysql/de-DE/mandatory/sample_notices.sql b/installer/data/mysql/de-DE/mandatory/sample_notices.sql index 0d172db..f668d99 100644 --- a/installer/data/mysql/de-DE/mandatory/sample_notices.sql +++ b/installer/data/mysql/de-DE/mandatory/sample_notices.sql @@ -11,7 +11,7 @@ VALUES ('circulation','ODUE','Mahnung','Mahnung','Liebe/r < ('reserves', 'HOLD_PRINT', 'Vormerkbenachrichtigung (Print)', 'Vormerkbenachrichtigung (Print)', '<>\r\n<>\r\n<>\r\n<>\r\n<> <>\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n<> <>\r\n<>\r\n<>\r\n<> <>\r\n<>\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\nLiebe(r) <> <>,\r\n\r\nFür Sie liegt seit dem <> eine Vormerkung zur Abholung bereit:\r\n\r\nTitel: <>\r\nVerfasser: <>\r\nSignatur: <>\r\n'), ('circulation','CHECKIN','Rückgabequittung (Zusammenfassung)','Rückgabequittung','Die folgenden Medien wurden zurückgegeben:\r\n----\r\n<>\r\n----\r\nVielen Dank.'), ('circulation','CHECKOUT','Ausleihquittung (Zusammenfassung)','Ausleihquittung','Die folgenden Medien wurden entliehen:\r\n----\r\n<>\r\n----\r\nVielen Dank für Ihren Besuch in <>.'), -('reserves', 'HOLDPLACED', 'Neue Vormerkung', 'Neue Vormerkung','Folgender Titel wurde vorgemerkt: <> (<<biblionumber>>) durch den Benutzer <<firstname>> <<surname>> (<<cardnumber>>).'), +('reserves', 'HOLDPLACED', 'Neue Vormerkung', 'Neue Vormerkung','Folgender Titel wurde vorgemerkt: <<biblio.title>> (<<biblio.biblionumber>>) durch den Benutzer <<borrowers.firstname>> <<borrowers.surname>> (<<borrowers.cardnumber>>).'), ('suggestions','ACCEPTED','Anschaffungsvorschlag wurde angenommen', 'Ihr Anschaffungsvorschlag wurde angenommen','Liebe(r) <<borrowers.firstname>> <<borrowers.surname>>,\n\nSie haben der Bibliothek folgendes Medium zur Anschaffung vorgeschlagen: <<suggestions.title>> by <<suggestions.author>>.\n\nDie Bibliothek hat diesen Titel heute recherchiert und wird Ihn sobald wie möglich im Buchhandel bestellen. Sie erhalten Nachricht, sobald die Bestellung abgeschlossen ist und sobald der Titel in der Bibliotek verfügbar ist.\n\nWenn Sie Fragen haben, richten Sie Ihre Mail bitte an: <<branches.branchemail>>.\n\nVielen Dank,\n\n<<branches.branchname>>'), ('suggestions','AVAILABLE','Vorgeschlagenes Medium verfügbar', 'Das vorgeschlagene Medium ist jetzt verfügbar','Liebe(r) <<borrowers.firstname>> <<borrowers.surname>>,\n\nSie haben der Bibliothek folgendes Medium zur Anschaffung vorgeschlagen: <<suggestions.title>> von <<suggestions.author>>.\n\nWir freuen uns Ihnen mitteilen zu können, dass dieser Titel jetzt im Bestand der Bibliothek verfügbar ist.\n\nWenn Sie Fragen haben, richten Sie Ihre Mail bitte an: <<branches.branchemail>>.\n\nVielen Dank,\n\n<<branches.branchname>>'), ('suggestions','ORDERED','Vorgeschlagenes Medium bestellt', 'Das vorgeschlagene Medium wurde im Buchhandel bestellt','Liebe(r) <<borrowers.firstname>> <<borrowers.surname>>,\n\nSie haben der Bibliothek folgendes Medium zur Anschaffung vorgeschlaten: <<suggestions.title>> von <<suggestions.author>>.\n\nWir freuen uns Ihnen mitteilen zu können, dass dieser Titel jetzt im Buchhandel bestellt wurde. Nach Eintreffen wird er in unseren Bestand eingearbeitet.\n\nSie erhalten Nachricht, sobald das Medium verfügbar ist.\n\nBei Nachfragen erreichen Sie uns unter der Emailadresse <<branches.branchemail>>.\n\nVielen Dank,\n\n<<branches.branchname>>'), diff --git a/installer/data/mysql/en/mandatory/sample_notices.sql b/installer/data/mysql/en/mandatory/sample_notices.sql index 5ca7eaf..a600373 100644 --- a/installer/data/mysql/en/mandatory/sample_notices.sql +++ b/installer/data/mysql/en/mandatory/sample_notices.sql @@ -11,8 +11,90 @@ VALUES ('circulation','ODUE','Overdue Notice','Item Overdue','Dear <<borrowers.f ('reserves', 'HOLD_PRINT', 'Hold Available for Pickup (print notice)', 'Hold Available for Pickup (print notice)', '<<branches.branchname>>\r\n<<branches.branchaddress1>>\r\n<<branches.branchaddress2>>\r\n\r\n\r\nChange Service Requested\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n<<borrowers.firstname>> <<borrowers.surname>>\r\n<<borrowers.address>>\r\n<<borrowers.city>> <<borrowers.zipcode>>\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n<<borrowers.firstname>> <<borrowers.surname>> <<borrowers.cardnumber>>\r\n\r\nYou have a hold available for pickup as of <<reserves.waitingdate>>:\r\n\r\nTitle: <<biblio.title>>\r\nAuthor: <<biblio.author>>\r\nCopy: <<items.copynumber>>\r\n'), ('circulation','CHECKIN','Item Check-in (Digest)','Check-ins','The following items have been checked in:\r\n----\r\n<<biblio.title>>\r\n----\r\nThank you.'), ('circulation','CHECKOUT','Item Check-out (Digest)','Checkouts','The following items have been checked out:\r\n----\r\n<<biblio.title>>\r\n----\r\nThank you for visiting <<branches.branchname>>.'), -('reserves', 'HOLDPLACED', 'Hold Placed on Item', 'Hold Placed on Item','A hold has been placed on the following item : <<title>> (<<biblionumber>>) by the user <<firstname>> <<surname>> (<<cardnumber>>).'), +('reserves', 'HOLDPLACED', 'Hold Placed on Item', 'Hold Placed on Item','A hold has been placed on the following item : <<biblio.title>> (<<biblio.biblionumber>>) by the user <<borrowers.firstname>> <<borrowers.surname>> (<<borrowers.cardnumber>>).'), ('suggestions','ACCEPTED','Suggestion accepted', 'Purchase suggestion accepted','Dear <<borrowers.firstname>> <<borrowers.surname>>,\n\nYou have suggested that the library acquire <<suggestions.title>> by <<suggestions.author>>.\n\nThe library has reviewed your suggestion today. The item will be ordered as soon as possible. You will be notified by mail when the order is completed, and again when the item arrives at the library.\n\nIf you have any questions, please email us at <<branches.branchemail>>.\n\nThank you,\n\n<<branches.branchname>>'), ('suggestions','AVAILABLE','Suggestion available', 'Suggested purchase available','Dear <<borrowers.firstname>> <<borrowers.surname>>,\n\nYou have suggested that the library acquire <<suggestions.title>> by <<suggestions.author>>.\n\nWe are pleased to inform you that the item you requested is now part of the collection.\n\nIf you have any questions, please email us at <<branches.branchemail>>.\n\nThank you,\n\n<<branches.branchname>>'), ('suggestions','ORDERED','Suggestion ordered', 'Suggested item ordered','Dear <<borrowers.firstname>> <<borrowers.surname>>,\n\nYou have suggested that the library acquire <<suggestions.title>> by <<suggestions.author>>.\n\nWe are pleased to inform you that the item you requested has now been ordered. It should arrive soon, at which time it will be processed for addition into the collection.\n\nYou will be notified again when the book is available.\n\nIf you have any questions, please email us at <<branches.branchemail>>\n\nThank you,\n\n<<branches.branchname>>'), ('suggestions','REJECTED','Suggestion rejected', 'Purchase suggestion declined','Dear <<borrowers.firstname>> <<borrowers.surname>>,\n\nYou have suggested that the library acquire <<suggestions.title>> by <<suggestions.author>>.\n\nThe library has reviewed your request today, and has decided not to accept the suggestion at this time.\n\nThe reason given is: <<suggestions.reason>>\n\nIf you have any questions, please email us at <<branches.branchemail>>.\n\nThank you,\n\n<<branches.branchname>>'); +INSERT INTO `letter` (module, code, name, title, content, is_html) +VALUES ('circulation','ISSUESLIP','Issue Slip','Issue Slip', '<h3><<branches.branchname>></h3> +Checked out to <<borrowers.title>> <<borrowers.firstname>> <<borrowers.initials>> <<borrowers.surname>> <br /> +(<<borrowers.cardnumber>>) <br /> + +<<today>><br /> + +<h4>Checked Out</h4> +<checkedout> +<p> +<<biblio.title>> <br /> +Barcode: <<items.barcode>><br /> +Date due: <<issues.date_due>><br /> +</p> +</checkedout> + +<h4>Overdues</h4> +<overdue> +<p> +<<biblio.title>> <br /> +Barcode: <<items.barcode>><br /> +Date due: <<issues.date_due>><br /> +</p> +</overdue> + +<hr> + +<h4 style="text-align: center; font-style:italic;">News</h4> +<news> +<div class="newsitem"> +<h5 style="margin-bottom: 1px; margin-top: 1px"><b><<opac_news.title>></b></h5> +<p style="margin-bottom: 1px; margin-top: 1px"><<opac_news.new>></p> +<p class="newsfooter" style="font-size: 8pt; font-style:italic; margin-bottom: 1px; margin-top: 1px">Posted on <<opac_news.timestamp>></p> +<hr /> +</div> +</news>', 1), +('circulation','ISSUEQSLIP','Issue Quick Slip','Issue Quick Slip', '<h3><<branches.branchname>></h3> +Checked out to <<borrowers.title>> <<borrowers.firstname>> <<borrowers.initials>> <<borrowers.surname>> <br /> +(<<borrowers.cardnumber>>) <br /> + +<<today>><br /> + +<h4>Checked Out Today</h4> +<checkedout> +<p> +<<biblio.title>> <br /> +Barcode: <<items.barcode>><br /> +Date due: <<issues.date_due>><br /> +</p> +</checkedout>', 1), +('circulation','RESERVESLIP','Reserve Slip','Reserve Slip', '<h5>Date: <<today>></h5> + +<h3> Transfer to/Hold in <<branches.branchname>></h3> + +<reserves> +<div> +<h3><<borrowers.surname>>, <<borrowers.firstname>></h3> + +<ul> + <li><<borrowers.cardnumber>></li> + <li><<borrowers.phone>></li> + <li> <<borrowers.address>><br /> + <<borrowers.address2>><br /> + <<borrowers.city >> <<borrowers.zipcode>> + </li> + <li><<borrowers.email>></li> +</ul> +<br /> +<h3>ITEM ON HOLD</h3> + <h4><<biblio.title>></h4> + <h5><<biblio.author>></h5> + <ul> + <li><<items.barcode>></li> + <li><<items.itemcallnumber>></li> + <li><<reserves.waitingdate>></li> + </ul> + <p>Notes: + <pre><<reserves.reservenotes>></pre> + </p> +</div> +</reserves>', 1); + diff --git a/installer/data/mysql/es-ES/mandatory/sample_notices.sql b/installer/data/mysql/es-ES/mandatory/sample_notices.sql index 78b80fa..0450bd0 100644 --- a/installer/data/mysql/es-ES/mandatory/sample_notices.sql +++ b/installer/data/mysql/es-ES/mandatory/sample_notices.sql @@ -11,7 +11,7 @@ VALUES ('circulation','ODUE','Overdue Notice','Item Overdue','Dear <<borrowers.f ('reserves', 'HOLD_PRINT', 'Hold Available for Pickup (print notice)', 'Hold Available for Pickup (print notice)', '<<branches.branchname>>\r\n<<branches.branchaddress1>>\r\n<<branches.branchaddress2>>\r\n\r\n\r\nChange Service Requested\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n<<borrowers.firstname>> <<borrowers.surname>>\r\n<<borrowers.address>>\r\n<<borrowers.city>> <<borrowers.zipcode>>\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n<<borrowers.firstname>> <<borrowers.surname>> <<borrowers.cardnumber>>\r\n\r\nYou have a hold available for pickup as of <<reserves.waitingdate>>:\r\n\r\nTitle: <<biblio.title>>\r\nAuthor: <<biblio.author>>\r\nCopy: <<items.copynumber>>\r\n'), ('circulation','CHECKIN','Item Check-in (Digest)','Check-ins','The following items have been checked in:\r\n----\r\n<<biblio.title>>\r\n----\r\nThank you.'), ('circulation','CHECKOUT','Item Check-out (Digest)','Checkouts','The following items have been checked out:\r\n----\r\n<<biblio.title>>\r\n----\r\nThank you for visiting <<branches.branchname>>.'), -('reserves', 'HOLDPLACED', 'Hold Placed on Item', 'Hold Placed on Item','A hold has been placed on the following item : <<title>> (<<biblionumber>>) by the user <<firstname>> <<surname>> (<<cardnumber>>).'), +('reserves', 'HOLDPLACED', 'Hold Placed on Item', 'Hold Placed on Item','A hold has been placed on the following item : <<biblio.title>> (<<biblio.biblionumber>>) by the user <<borrowers.firstname>> <<borrowers.surname>> (<<borrowers.cardnumber>>).'), ('suggestions','ACCEPTED','Suggestion accepted', 'Purchase suggestion accepted','Dear <<borrowers.firstname>> <<borrowers.surname>>,\n\nYou have suggested that the library acquire <<suggestions.title>> by <<suggestions.author>>.\n\nThe library has reviewed your suggestion today. The item will be ordered as soon as possible. You will be notified by mail when the order is completed, and again when the item arrives at the library.\n\nIf you have any questions, please email us at <<branches.branchemail>>.\n\nThank you,\n\n<<branches.branchname>>'), ('suggestions','AVAILABLE','Suggestion available', 'Suggested purchase available','Dear <<borrowers.firstname>> <<borrowers.surname>>,\n\nYou have suggested that the library acquire <<suggestions.title>> by <<suggestions.author>>.\n\nWe are pleased to inform you that the item you requested is now part of the collection.\n\nIf you have any questions, please email us at <<branches.branchemail>>.\n\nThank you,\n\n<<branches.branchname>>'), ('suggestions','ORDERED','Suggestion ordered', 'Suggested item ordered','Dear <<borrowers.firstname>> <<borrowers.surname>>,\n\nYou have suggested that the library acquire <<suggestions.title>> by <<suggestions.author>>.\n\nWe are pleased to inform you that the item you requested has now been ordered. It should arrive soon, at which time it will be processed for addition into the collection.\n\nYou will be notified again when the book is available.\n\nIf you have any questions, please email us at <<branches.branchemail>>\n\nThank you,\n\n<<branches.branchname>>'), diff --git a/installer/data/mysql/fr-FR/1-Obligatoire/sample_notices.sql b/installer/data/mysql/fr-FR/1-Obligatoire/sample_notices.sql index 9e9f66d..4eb1210 100644 --- a/installer/data/mysql/fr-FR/1-Obligatoire/sample_notices.sql +++ b/installer/data/mysql/fr-FR/1-Obligatoire/sample_notices.sql @@ -13,7 +13,7 @@ VALUES ('reserves', 'HOLD_PRINT', 'Hold Available for Pickup (print notice)', 'Hold Available for Pickup at <<branches.branchname>>', '<<branches.branchname>>\n<<branches.branchaddress1>>\n<<branches.branchaddress2>>\n\n\nChange Service Requested\n\n\n\n\n\n\n\n<<borrowers.firstname>> <<borrowers.surname>>\n<<borrowers.address>>\n<<borrowers.city>> <<borrowers.zipcode>>\n\n\n\n\n\n\n\n\n\n\n<<borrowers.firstname>> <<borrowers.surname>> <<borrowers.cardnumber>>\n\nYou have a hold available for pickup as of <<reserves.waitingdate>>:\r\n\r\nTitle: <<biblio.title>>\r\nAuthor: <<biblio.author>>\r\nCopy: <<items.copynumber>>\r\n'), ('circulation','CHECKIN','Item Check-in (Digest)','Check-ins','The following items have been checked in:\r\n----\r\n<<biblio.title>>\r\n----\r\nThank you.'), ('circulation','CHECKOUT','Item Check-out (Digest)','Checkouts','The following items have been checked out:\r\n----\r\n<<biblio.title>>\r\n----\r\nThank you for visiting <<branches.branchname>>.'), -('reserves', 'HOLDPLACED', 'Hold Placed on Item', 'Hold Placed on Item','A hold has been placed on the following item : <<title>> (<<biblionumber>>) by the user <<firstname>> <<surname>> (<<cardnumber>>).'), +('reserves', 'HOLDPLACED', 'Hold Placed on Item', 'Hold Placed on Item','A hold has been placed on the following item : <<biblio.title>> (<<biblio.biblionumber>>) by the user <<borrowers.firstname>> <<borrowers.surname>> (<<borrowers.cardnumber>>).'), ('suggestions','ACCEPTED','Suggestion accepted', 'Purchase suggestion accepted','Dear <<borrowers.firstname>> <<borrowers.surname>>,\n\nYou have suggested that the library acquire <<suggestions.title>> by <<suggestions.author>>.\n\nThe library has reviewed your suggestion today. The item will be ordered as soon as possible. You will be notified by mail when the order is completed, and again when the item arrives at the library.\n\nIf you have any questions, please email us at <<branches.branchemail>>.\n\nThank you,\n\n<<branches.branchname>>'), ('suggestions','AVAILABLE','Suggestion available', 'Suggested purchase available','Dear <<borrowers.firstname>> <<borrowers.surname>>,\n\nYou have suggested that the library acquire <<suggestions.title>> by <<suggestions.author>>.\n\nWe are pleased to inform you that the item you requested is now part of the collection.\n\nIf you have any questions, please email us at <<branches.branchemail>>.\n\nThank you,\n\n<<branches.branchname>>'), ('suggestions','ORDERED','Suggestion ordered', 'Suggested item ordered','Dear <<borrowers.firstname>> <<borrowers.surname>>,\n\nYou have suggested that the library acquire <<suggestions.title>> by <<suggestions.author>>.\n\nWe are pleased to inform you that the item you requested has now been ordered. It should arrive soon, at which time it will be processed for addition into the collection.\n\nYou will be notified again when the book is available.\n\nIf you have any questions, please email us at <<branches.branchemail>>\n\nThank you,\n\n<<branches.branchname>>'), diff --git a/installer/data/mysql/it-IT/necessari/notices.sql b/installer/data/mysql/it-IT/necessari/notices.sql index 78b80fa..0450bd0 100644 --- a/installer/data/mysql/it-IT/necessari/notices.sql +++ b/installer/data/mysql/it-IT/necessari/notices.sql @@ -11,7 +11,7 @@ VALUES ('circulation','ODUE','Overdue Notice','Item Overdue','Dear <<borrowers.f ('reserves', 'HOLD_PRINT', 'Hold Available for Pickup (print notice)', 'Hold Available for Pickup (print notice)', '<<branches.branchname>>\r\n<<branches.branchaddress1>>\r\n<<branches.branchaddress2>>\r\n\r\n\r\nChange Service Requested\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n<<borrowers.firstname>> <<borrowers.surname>>\r\n<<borrowers.address>>\r\n<<borrowers.city>> <<borrowers.zipcode>>\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n<<borrowers.firstname>> <<borrowers.surname>> <<borrowers.cardnumber>>\r\n\r\nYou have a hold available for pickup as of <<reserves.waitingdate>>:\r\n\r\nTitle: <<biblio.title>>\r\nAuthor: <<biblio.author>>\r\nCopy: <<items.copynumber>>\r\n'), ('circulation','CHECKIN','Item Check-in (Digest)','Check-ins','The following items have been checked in:\r\n----\r\n<<biblio.title>>\r\n----\r\nThank you.'), ('circulation','CHECKOUT','Item Check-out (Digest)','Checkouts','The following items have been checked out:\r\n----\r\n<<biblio.title>>\r\n----\r\nThank you for visiting <<branches.branchname>>.'), -('reserves', 'HOLDPLACED', 'Hold Placed on Item', 'Hold Placed on Item','A hold has been placed on the following item : <<title>> (<<biblionumber>>) by the user <<firstname>> <<surname>> (<<cardnumber>>).'), +('reserves', 'HOLDPLACED', 'Hold Placed on Item', 'Hold Placed on Item','A hold has been placed on the following item : <<biblio.title>> (<<biblio.biblionumber>>) by the user <<borrowers.firstname>> <<borrowers.surname>> (<<borrowers.cardnumber>>).'), ('suggestions','ACCEPTED','Suggestion accepted', 'Purchase suggestion accepted','Dear <<borrowers.firstname>> <<borrowers.surname>>,\n\nYou have suggested that the library acquire <<suggestions.title>> by <<suggestions.author>>.\n\nThe library has reviewed your suggestion today. The item will be ordered as soon as possible. You will be notified by mail when the order is completed, and again when the item arrives at the library.\n\nIf you have any questions, please email us at <<branches.branchemail>>.\n\nThank you,\n\n<<branches.branchname>>'), ('suggestions','AVAILABLE','Suggestion available', 'Suggested purchase available','Dear <<borrowers.firstname>> <<borrowers.surname>>,\n\nYou have suggested that the library acquire <<suggestions.title>> by <<suggestions.author>>.\n\nWe are pleased to inform you that the item you requested is now part of the collection.\n\nIf you have any questions, please email us at <<branches.branchemail>>.\n\nThank you,\n\n<<branches.branchname>>'), ('suggestions','ORDERED','Suggestion ordered', 'Suggested item ordered','Dear <<borrowers.firstname>> <<borrowers.surname>>,\n\nYou have suggested that the library acquire <<suggestions.title>> by <<suggestions.author>>.\n\nWe are pleased to inform you that the item you requested has now been ordered. It should arrive soon, at which time it will be processed for addition into the collection.\n\nYou will be notified again when the book is available.\n\nIf you have any questions, please email us at <<branches.branchemail>>\n\nThank you,\n\n<<branches.branchname>>'), diff --git a/installer/data/mysql/kohastructure.sql b/installer/data/mysql/kohastructure.sql index 67149c9..0cff8c5 100644 --- a/installer/data/mysql/kohastructure.sql +++ b/installer/data/mysql/kohastructure.sql @@ -1169,10 +1169,12 @@ DROP TABLE IF EXISTS `letter`; CREATE TABLE `letter` ( -- table for all notice templates in Koha `module` varchar(20) NOT NULL default '', -- Koha module that triggers this notice `code` varchar(20) NOT NULL default '', -- unique identifier for this notice + `branchcode` varchar(10) default NULL, -- foreign key, linking to the branches table for the location the item was checked out `name` varchar(100) NOT NULL default '', -- plain text name for this notice + `is_html` tinyint(1) default 0, `title` varchar(200) NOT NULL default '', -- subject line of the notice `content` text, -- body text for the notice - PRIMARY KEY (`module`,`code`) + PRIMARY KEY (`module`,`code`, `branchcode`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- @@ -2253,12 +2255,13 @@ CREATE TABLE `message_transports` ( `is_digest` tinyint(1) NOT NULL default '0', `letter_module` varchar(20) NOT NULL default '', `letter_code` varchar(20) NOT NULL default '', + `branchcode` varchar(10) NOT NULL default '', PRIMARY KEY (`message_attribute_id`,`message_transport_type`,`is_digest`), KEY `message_transport_type` (`message_transport_type`), KEY `letter_module` (`letter_module`,`letter_code`), CONSTRAINT `message_transports_ibfk_1` FOREIGN KEY (`message_attribute_id`) REFERENCES `message_attributes` (`message_attribute_id`) ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT `message_transports_ibfk_2` FOREIGN KEY (`message_transport_type`) REFERENCES `message_transport_types` (`message_transport_type`) ON DELETE CASCADE ON UPDATE CASCADE, - CONSTRAINT `message_transports_ibfk_3` FOREIGN KEY (`letter_module`, `letter_code`) REFERENCES `letter` (`module`, `code`) ON DELETE CASCADE ON UPDATE CASCADE + CONSTRAINT `message_transports_ibfk_3` FOREIGN KEY (`letter_module`, `letter_code`, `branchcode`) REFERENCES `letter` (`module`, `code`, `branchcode`) ON DELETE CASCADE ON UPDATE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- diff --git a/installer/data/mysql/nb-NO/1-Obligatorisk/sample_notices.sql b/installer/data/mysql/nb-NO/1-Obligatorisk/sample_notices.sql index 762da91..f40da36 100644 --- a/installer/data/mysql/nb-NO/1-Obligatorisk/sample_notices.sql +++ b/installer/data/mysql/nb-NO/1-Obligatorisk/sample_notices.sql @@ -32,7 +32,7 @@ VALUES ('circulation','ODUE','Purring','Purring på dokument','<<borrowers.first ('reserves', 'HOLD_PRINT', 'Hentemelding (på papir)', 'Hentemelding', '<<branches.branchname>>\r\n<<branches.branchaddress1>>\r\n<<branches.branchaddress2>>\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n<<borrowers.firstname>> <<borrowers.surname>>\r\n<<borrowers.address>>\r\n<<borrowers.city>> <<borrowers.zipcode>>\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n<<borrowers.firstname>> <<borrowers.surname>> <<borrowers.cardnumber>>\r\n\r\nDu har et reservert dokument som kan hentes fra <<reserves.waitingdate>>:\r\n\r\nTittel: <<biblio.title>>\r\nForfatter: <<biblio.author>>\r\nEksemplar: <<items.copynumber>>\r\n'), ('circulation','CHECKIN','Innlevering','Melding om innlevering','Følgende dokument har blitt innlevert:\r\n----\r\n<<biblio.title>>\r\n----\r\nVennlig hilsen\r\nBiblioteket'), ('circulation','CHECKOUT','Utlån','Melding om utlån','Følgende dokument har blitt lånt ut:\r\n----\r\n<<biblio.title>>\r\n----\r\nVennlig hilsen\r\nBiblioteket'), -('reserves', 'HOLDPLACED', 'Melding om reservasjon', 'Melding om reservasjon','Følgende dokument har blitt reservert : <<title>> (<<biblionumber>>) av <<firstname>> <<surname>> (<<cardnumber>>).'), +('reserves', 'HOLDPLACED', 'Melding om reservasjon', 'Melding om reservasjon','Følgende dokument har blitt reservert : <<biblio.title>> (<<biblio.biblionumber>>) av <<borrowers.firstname>> <<borrowers.surname>> (<<borrowers.cardnumber>>).'), ('suggestions','ACCEPTED','Forslag godtatt', 'Innkjøpsforslag godtatt','<<borrowers.firstname>> <<borrowers.surname>>,\n\nDu har foreslått at biblioteket kjøper inn <<suggestions.title>> av <<suggestions.author>>.\n\nBiblioteket har vurdert forslaget i dag. Dokumentet vil bli bestilt så fort det lar seg gjøre. Du vil få en ny melding når bestillingen er gjort, og når dokumentet ankommer biblioteket.\n\nEr det noe du lurer på, vennligst kontakt oss på <<branches.branchemail>>.\n\nVennlig hilsen,\n\n<<branches.branchname>>'), ('suggestions','AVAILABLE','Foreslått dokument tilgjengelig', 'Foreslått dokument tilgjengelig','<<borrowers.firstname>> <<borrowers.surname>>,\n\nDu har foreslått at biblioteket kjøper inn <<suggestions.title>> av <<suggestions.author>>.\n\nVi har gleden av å informere deg om at dokumentet nå er innlemmet i samlingen.\n\nEr det noe du lurer på, vennligst kontakt oss på <<branches.branchemail>>.\n\nVennlig hilsen,\n\n<<branches.branchname>>'), ('suggestions','ORDERED','Innkjøpsforslag i bestilling', 'Innkjøpsforslag i bestilling','Dear <<borrowers.firstname>> <<borrowers.surname>>,\n\nDu har foreslått at biblioteket kjøper inn <<suggestions.title>> av <<suggestions.author>>.\n\nVi har gleden av å informere deg om at dokumentet du foreslo nå er i bestilling.\n\nDu vil få en ny melding når dokumentet er tilgjengelig.\n\nEr det noe du lurer på, vennligst kontakt oss på <<branches.branchemail>>.\n\nVennlig hilsen,\n\n<<branches.branchname>>'), diff --git a/installer/data/mysql/pl-PL/mandatory/sample_notices.sql b/installer/data/mysql/pl-PL/mandatory/sample_notices.sql index c101b0b..73102af 100644 --- a/installer/data/mysql/pl-PL/mandatory/sample_notices.sql +++ b/installer/data/mysql/pl-PL/mandatory/sample_notices.sql @@ -13,7 +13,7 @@ VALUES ('reserves', 'HOLD_PRINT', 'Hold Available for Pickup (print notice)', 'Hold Available for Pickup (print notice)', '<<branches.branchname>>\r\n<<branches.branchaddress1>>\r\n<<branches.branchaddress2>>\r\n\r\n\r\nChange Service Requested\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n<<borrowers.firstname>> <<borrowers.surname>>\r\n<<borrowers.address>>\r\n<<borrowers.city>> <<borrowers.zipcode>>\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n<<borrowers.firstname>> <<borrowers.surname>> <<borrowers.cardnumber>>\r\n\r\nYou have a hold available for pickup as of <<reserves.waitingdate>>:\r\n\r\nTitle: <<biblio.title>>\r\nAuthor: <<biblio.author>>\r\nCopy: <<items.copynumber>>\r\n'), ('circulation','CHECKIN','Item Check-in (Digest)','Check-ins','The following items have been checked in:\r\n----\r\n<<biblio.title>>\r\n----\r\nThank you.'), ('circulation','CHECKOUT','Item Check-out (Digest)','Checkouts','The following items have been checked out:\r\n----\r\n<<biblio.title>>\r\n----\r\nThank you for visiting <<branches.branchname>>.'), -('reserves', 'HOLDPLACED', 'Hold Placed on Item', 'Hold Placed on Item','A hold has been placed on the following item : <<title>> (<<biblionumber>>) by the user <<firstname>> <<surname>> (<<cardnumber>>).'), +('reserves', 'HOLDPLACED', 'Hold Placed on Item', 'Hold Placed on Item','A hold has been placed on the following item : <<biblio.title>> (<<biblio.biblionumber>>) by the user <<borrowers.firstname>> <<borrowers.surname>> (<<borrowers.cardnumber>>).'), ('suggestions','ACCEPTED','Suggestion accepted', 'Purchase suggestion accepted','Dear <<borrowers.firstname>> <<borrowers.surname>>,\n\nYou have suggested that the library acquire <<suggestions.title>> by <<suggestions.author>>.\n\nThe library has reviewed your suggestion today. The item will be ordered as soon as possible. You will be notified by mail when the order is completed, and again when the item arrives at the library.\n\nIf you have any questions, please email us at <<branches.branchemail>>.\n\nThank you,\n\n<<branches.branchname>>'), ('suggestions','AVAILABLE','Suggestion available', 'Suggested purchase available','Dear <<borrowers.firstname>> <<borrowers.surname>>,\n\nYou have suggested that the library acquire <<suggestions.title>> by <<suggestions.author>>.\n\nWe are pleased to inform you that the item you requested is now part of the collection.\n\nIf you have any questions, please email us at <<branches.branchemail>>.\n\nThank you,\n\n<<branches.branchname>>'), ('suggestions','ORDERED','Suggestion ordered', 'Suggested item ordered','Dear <<borrowers.firstname>> <<borrowers.surname>>,\n\nYou have suggested that the library acquire <<suggestions.title>> by <<suggestions.author>>.\n\nWe are pleased to inform you that the item you requested has now been ordered. It should arrive soon, at which time it will be processed for addition into the collection.\n\nYou will be notified again when the book is available.\n\nIf you have any questions, please email us at <<branches.branchemail>>\n\nThank you,\n\n<<branches.branchname>>'), diff --git a/installer/data/mysql/ru-RU/mandatory/sample_notices.sql b/installer/data/mysql/ru-RU/mandatory/sample_notices.sql index 5ca7eaf..e13782a 100644 --- a/installer/data/mysql/ru-RU/mandatory/sample_notices.sql +++ b/installer/data/mysql/ru-RU/mandatory/sample_notices.sql @@ -11,7 +11,7 @@ VALUES ('circulation','ODUE','Overdue Notice','Item Overdue','Dear <<borrowers.f ('reserves', 'HOLD_PRINT', 'Hold Available for Pickup (print notice)', 'Hold Available for Pickup (print notice)', '<<branches.branchname>>\r\n<<branches.branchaddress1>>\r\n<<branches.branchaddress2>>\r\n\r\n\r\nChange Service Requested\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n<<borrowers.firstname>> <<borrowers.surname>>\r\n<<borrowers.address>>\r\n<<borrowers.city>> <<borrowers.zipcode>>\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n<<borrowers.firstname>> <<borrowers.surname>> <<borrowers.cardnumber>>\r\n\r\nYou have a hold available for pickup as of <<reserves.waitingdate>>:\r\n\r\nTitle: <<biblio.title>>\r\nAuthor: <<biblio.author>>\r\nCopy: <<items.copynumber>>\r\n'), ('circulation','CHECKIN','Item Check-in (Digest)','Check-ins','The following items have been checked in:\r\n----\r\n<<biblio.title>>\r\n----\r\nThank you.'), ('circulation','CHECKOUT','Item Check-out (Digest)','Checkouts','The following items have been checked out:\r\n----\r\n<<biblio.title>>\r\n----\r\nThank you for visiting <<branches.branchname>>.'), -('reserves', 'HOLDPLACED', 'Hold Placed on Item', 'Hold Placed on Item','A hold has been placed on the following item : <<title>> (<<biblionumber>>) by the user <<firstname>> <<surname>> (<<cardnumber>>).'), +('reserves', 'HOLDPLACED', 'Hold Placed on Item', 'Hold Placed on Item','A hold has been placed on the following item : <<biblio.title>> (<<biblio.biblionumber>>) by the user <<borrowers.firstname>> <<borrowers.surname>> (<<borrowers.cardnumber>>).'), ('suggestions','ACCEPTED','Suggestion accepted', 'Purchase suggestion accepted','Dear <<borrowers.firstname>> <<borrowers.surname>>,\n\nYou have suggested that the library acquire <<suggestions.title>> by <<suggestions.author>>.\n\nThe library has reviewed your suggestion today. The item will be ordered as soon as possible. You will be notified by mail when the order is completed, and again when the item arrives at the library.\n\nIf you have any questions, please email us at <<branches.branchemail>>.\n\nThank you,\n\n<<branches.branchname>>'), ('suggestions','AVAILABLE','Suggestion available', 'Suggested purchase available','Dear <<borrowers.firstname>> <<borrowers.surname>>,\n\nYou have suggested that the library acquire <<suggestions.title>> by <<suggestions.author>>.\n\nWe are pleased to inform you that the item you requested is now part of the collection.\n\nIf you have any questions, please email us at <<branches.branchemail>>.\n\nThank you,\n\n<<branches.branchname>>'), ('suggestions','ORDERED','Suggestion ordered', 'Suggested item ordered','Dear <<borrowers.firstname>> <<borrowers.surname>>,\n\nYou have suggested that the library acquire <<suggestions.title>> by <<suggestions.author>>.\n\nWe are pleased to inform you that the item you requested has now been ordered. It should arrive soon, at which time it will be processed for addition into the collection.\n\nYou will be notified again when the book is available.\n\nIf you have any questions, please email us at <<branches.branchemail>>\n\nThank you,\n\n<<branches.branchname>>'), diff --git a/installer/data/mysql/sysprefs.sql b/installer/data/mysql/sysprefs.sql index 0cc79b2..1d0513b 100644 --- a/installer/data/mysql/sysprefs.sql +++ b/installer/data/mysql/sysprefs.sql @@ -330,6 +330,8 @@ INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('EasyAnalyticalRecords','0','If on, display in the catalogue screens tools to easily setup analytical record relationships','','YesNo'); INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('OpacShowRecentComments',0,'If ON a link to recent comments will appear in the OPAC masthead',NULL,'YesNo'); INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES ('CircAutoPrintQuickSlip', '1', 'Choose what should happen when an empty barcode field is submitted in circulation: Display a print quick slip window or Clear the screen.',NULL,'YesNo'); +INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('NoticeCSS','','Notices CSS url.',NULL,'free'); +INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('SlipCSS','','Slips CSS url.',NULL,'free'); INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES ('OPACLocalCoverImages','0','Display local cover images on OPAC search and details pages.','1','YesNo'); INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES ('LocalCoverImages','0','Display local cover images on intranet details pages.','1','YesNo'); INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES ('AllowMultipleCovers','0','Allow multiple cover images to be attached to each bibliographic record.','1','YesNo'); diff --git a/installer/data/mysql/uk-UA/mandatory/sample_notices.sql b/installer/data/mysql/uk-UA/mandatory/sample_notices.sql index 6ab0e18..a908f6c 100644 --- a/installer/data/mysql/uk-UA/mandatory/sample_notices.sql +++ b/installer/data/mysql/uk-UA/mandatory/sample_notices.sql @@ -10,7 +10,7 @@ VALUES ('circulation','ODUE','Overdue Notice','Item Overdue','Dear <<borrowers.f ('reserves', 'HOLD', 'Hold Available for Pickup', 'Hold Available for Pickup at <<branches.branchname>>', 'Dear <<borrowers.firstname>> <<borrowers.surname>>,\r\n\r\nYou have a hold available for pickup as of <<reserves.waitingdate>>:\r\n\r\nTitle: <<biblio.title>>\r\nAuthor: <<biblio.author>>\r\nCopy: <<items.copynumber>>\r\nLocation: <<branches.branchname>>\r\n<<branches.branchaddress1>>\r\n<<branches.branchaddress2>>\r\n<<branches.branchaddress3>>\r\n<<branches.branchcity>> <<branches.branchzip>>'), ('circulation','CHECKIN','Item Check-in (Digest)','Check-ins','The following items have been checked in:\r\n----\r\n<<biblio.title>>\r\n----\r\nThank you.'), ('circulation','CHECKOUT','Item Check-out (Digest)','Checkouts','The following items have been checked out:\r\n----\r\n<<biblio.title>>\r\n----\r\nThank you for visiting <<branches.branchname>>.'), -('reserves', 'HOLDPLACED', 'Hold Placed on Item', 'Hold Placed on Item','A hold has been placed on the following item : <<title>> (<<biblionumber>>) by the user <<firstname>> <<surname>> (<<cardnumber>>).'), +('reserves', 'HOLDPLACED', 'Hold Placed on Item', 'Hold Placed on Item','A hold has been placed on the following item : <<biblio.title>> (<<biblio.biblionumber>>) by the user <<borrowers.firstname>> <<borrowers.surname>> (<<borrowers.cardnumber>>).'), ('suggestions','ACCEPTED','Suggestion accepted', 'Purchase suggestion accepted','Dear <<borrowers.firstname>> <<borrowers.surname>>,\n\nYou have suggested that the library acquire <<suggestions.title>> by <<suggestions.author>>.\n\nThe library has reviewed your suggestion today. The item will be ordered as soon as possible. You will be notified by mail when the order is completed, and again when the item arrives at the library.\n\nIf you have any questions, please email us at <<branches.branchemail>>.\n\nThank you,\n\n<<branches.branchname>>'), ('suggestions','AVAILABLE','Suggestion available', 'Suggested purchase available','Dear <<borrowers.firstname>> <<borrowers.surname>>,\n\nYou have suggested that the library acquire <<suggestions.title>> by <<suggestions.author>>.\n\nWe are pleased to inform you that the item you requested is now part of the collection.\n\nIf you have any questions, please email us at <<branches.branchemail>>.\n\nThank you,\n\n<<branches.branchname>>'), ('suggestions','ORDERED','Suggestion ordered', 'Suggested item ordered','Dear <<borrowers.firstname>> <<borrowers.surname>>,\n\nYou have suggested that the library acquire <<suggestions.title>> by <<suggestions.author>>.\n\nWe are pleased to inform you that the item you requested has now been ordered. It should arrive soon, at which time it will be processed for addition into the collection.\n\nYou will be notified again when the book is available.\n\nIf you have any questions, please email us at <<branches.branchemail>>\n\nThank you,\n\n<<branches.branchname>>'), diff --git a/installer/data/mysql/updatedatabase.pl b/installer/data/mysql/updatedatabase.pl index d2d9d97..cc6c06a 100755 --- a/installer/data/mysql/updatedatabase.pl +++ b/installer/data/mysql/updatedatabase.pl @@ -4497,7 +4497,6 @@ if (C4::Context->preference("Version") < TransformToNum($DBversion)) { print "Upgrade to $DBversion done (Add 461 subfield 9 to default framework)\n"; SetVersion ($DBversion); } - } $DBversion = "3.05.00.018"; @@ -4712,6 +4711,105 @@ if ( C4::Context->preference("Version") < TransformToNum($DBversion) ) { SetVersion($DBversion); } +$DBversion = "3.07.00.XXX"; +if (C4::Context->preference("Version") < TransformToNum($DBversion)) { + $dbh->do("ALTER TABLE `message_transports` DROP FOREIGN KEY `message_transports_ibfk_3`"); + $dbh->do("ALTER TABLE `letter` DROP PRIMARY KEY"); + $dbh->do("ALTER TABLE `letter` ADD `branchcode` varchar(10) default NULL AFTER `code`"); + $dbh->do("ALTER TABLE `letter` ADD PRIMARY KEY (`module`,`code`, `branchcode`)"); + $dbh->do("ALTER TABLE `message_transports` ADD `branchcode` varchar(10) NOT NULL default ''"); + $dbh->do("ALTER TABLE `message_transports` ADD CONSTRAINT `message_transports_ibfk_3` FOREIGN KEY (`letter_module`, `letter_code`, `branchcode`) REFERENCES `letter` (`module`, `code`, `branchcode`) ON DELETE CASCADE ON UPDATE CASCADE"); + $dbh->do("ALTER TABLE `letter` ADD `is_html` tinyint(1) default 0 AFTER `name`"); + + $dbh->do("INSERT INTO `letter` (module, code, name, title, content, is_html) + VALUES ('circulation','ISSUESLIP','Issue Slip','Issue Slip', '<h3><<branches.branchname>></h3> +Checked out to <<borrowers.title>> <<borrowers.firstname>> <<borrowers.initials>> <<borrowers.surname>> <br /> +(<<borrowers.cardnumber>>) <br /> + +<<today>><br /> + +<h4>Checked Out</h4> +<checkedout> +<p> +<<biblio.title>> <br /> +Barcode: <<items.barcode>><br /> +Date due: <<issues.date_due>><br /> +</p> +</checkedout> + +<h4>Overdues</h4> +<overdue> +<p> +<<biblio.title>> <br /> +Barcode: <<items.barcode>><br /> +Date due: <<issues.date_due>><br /> +</p> +</overdue> + +<hr> + +<h4 style=\"text-align: center; font-style:italic;\">News</h4> +<news> +<div class=\"newsitem\"> +<h5 style=\"margin-bottom: 1px; margin-top: 1px\"><b><<opac_news.title>></b></h5> +<p style=\"margin-bottom: 1px; margin-top: 1px\"><<opac_news.new>></p> +<p class=\"newsfooter\" style=\"font-size: 8pt; font-style:italic; margin-bottom: 1px; margin-top: 1px\">Posted on <<opac_news.timestamp>></p> +<hr /> +</div> +</news>', 1)"); + $dbh->do("INSERT INTO `letter` (module, code, name, title, content, is_html) + VALUES ('circulation','ISSUEQSLIP','Issue Quick Slip','Issue Quick Slip', '<h3><<branches.branchname>></h3> +Checked out to <<borrowers.title>> <<borrowers.firstname>> <<borrowers.initials>> <<borrowers.surname>> <br /> +(<<borrowers.cardnumber>>) <br /> + +<<today>><br /> + +<h4>Checked Out Today</h4> +<checkedout> +<p> +<<biblio.title>> <br /> +Barcode: <<items.barcode>><br /> +Date due: <<issues.date_due>><br /> +</p> +</checkedout>', 1)"); + $dbh->do("INSERT INTO `letter` (module, code, name, title, content, is_html) + VALUES ('circulation','RESERVESLIP','Reserve Slip','Reserve Slip', '<h5>Date: <<today>></h5> + +<h3> Transfer to/Hold in <<branches.branchname>></h3> + +<h3><<borrowers.surname>>, <<borrowers.firstname>></h3> + +<ul> + <li><<borrowers.cardnumber>></li> + <li><<borrowers.phone>></li> + <li> <<borrowers.address>><br /> + <<borrowers.address2>><br /> + <<borrowers.city >> <<borrowers.zipcode>> + </li> + <li><<borrowers.email>></li> +</ul> +<br /> +<h3>ITEM ON HOLD</h3> +<h4><<biblio.title>></h4> +<h5><<biblio.author>></h5> +<ul> + <li><<items.barcode>></li> + <li><<items.itemcallnumber>></li> + <li><<reserves.waitingdate>></li> +</ul> +<p>Notes: +<pre><<reserves.reservenotes>></pre> +</p>', 1)"); + + $dbh->do("INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('NoticeCSS','','Notices CSS url.',NULL,'free')"); + $dbh->do("INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('SlipCSS','','Slips CSS url.',NULL,'free')"); + + $dbh->do("UPDATE `letter` SET content = replace(content, '<<title>>', '<<biblio.title>>') WHERE code = 'HOLDPLACED'"); + + print "Upgrade to $DBversion done (Add branchcode and is_html to letter table; Default ISSUESLIP and RESERVESLIP letters; Add NoticeCSS and SlipCSS sysprefs)\n"; + SetVersion($DBversion); +} + =head1 FUNCTIONS =head2 DropAllForeignKeys($table) diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/circ-toolbar.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/circ-toolbar.inc index a4acfdf..4e583f1 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/includes/circ-toolbar.inc +++ b/koha-tmpl/intranet-tmpl/prog/en/includes/circ-toolbar.inc @@ -42,8 +42,10 @@ function update_child() { }); // YUI Toolbar Functions + var slip_re = /slip/; function printx_window(print_type) { - window.open("/cgi-bin/koha/members/moremember.pl?borrowernumber=[% borrowernumber %]&print=" + print_type, "printwindow"); + var handler = print_type.match(slip_re) ? "printslip" : "moremember"; + window.open("/cgi-bin/koha/members/" + handler + ".pl?borrowernumber=[% borrowernumber %]&print=" + print_type, "printwindow"); return false; } function searchToHold(){ diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref index b3716c0..1556385 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref @@ -98,6 +98,11 @@ Circulation: yes: "open a print quick slip window" no: "clear the screen" - . + - + - Include the stylesheet at + - pref: NoticeCSS + class: url + - on Notices. (This should be a complete URL, starting with <code>http://</code>) Checkout Policy: - - pref: AllowNotForLoanOverride diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/staff_client.pref b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/staff_client.pref index df0a434..efa33a8 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/staff_client.pref +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/staff_client.pref @@ -83,6 +83,11 @@ Staff Client: Results: "Results page (for future use, Results XSLT not functional at this time)." Both: "Both Results and Details pages (for future use, Results XSLT not functional at this time)." - 'Note: The corresponding XSLT option must be turned on.' + - + - Include the stylesheet at + - pref: SlipCSS + class: url + - on Issue and Reserve Slips. (This should be a complete URL, starting with <code>http://</code>.) Options: - - pref: viewMARC diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/batch/print-notices.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/batch/print-notices.tt index 1904381..73f9e61 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/batch/print-notices.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/batch/print-notices.tt @@ -8,11 +8,7 @@ --> </style> [% IF ( stylesheet ) %] - <style type="text/css"> - <!-- - [% stylesheet %] - --> - </style> + <link rel="stylesheet" type="text/css" href="[% stylesheet %]"> [% END %] </head> <body> diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/hold-transfer-slip.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/hold-transfer-slip.tt deleted file mode 100644 index 18d45aa..0000000 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/hold-transfer-slip.tt +++ /dev/null @@ -1,54 +0,0 @@ -[% INCLUDE 'doc-head-open.inc' %] -<title>Koha -- Circulation: Transfers -[% INCLUDE 'doc-head-close-receipt.inc' %] - - -
- -[% FOREACH reservedat IN reservedata %] - -
Date: [% reservedat.pulldate %]
-

[% IF ( reservedat.transferrequired ) %]Transfer to [% reservedat.branchname %] [% ELSE %]Hold in [% reservedat.branchname %][% END %]

- -
- -

[% reservedat.surname %], [% reservedat.firstname %]

- -
    -
  • [% reservedat.cardnumber %]
  • - [% IF ( reservedat.phone ) %] -
  • [% reservedat.phone %]
  • - [% END %] -
  • - [% reservedat.address %]
    - [% IF ( reservedat.address2 ) %][% reservedat.address2 %]
    [% END %] - [% reservedat.city %] [% reservedat.zip %] -
  • - [% IF ( reservedat.email ) %] -
  • [% reservedat.email %]
  • - [% END %] -
-
-

ITEM ON HOLD

-

[% reservedat.title |html %]

-
[% reservedat.author %]
-
    - [% IF ( reservedat.barcode ) %]
  • [% reservedat.barcode %]
  • [% END %] - [% IF ( reservedat.itemcallnumber ) %]
  • [% reservedat.itemcallnumber %]
  • [% END %] - [% IF ( reservedat.waitingdate ) %]
  • [% reservedat.waitingdate %]
  • [% END %] -
- [% IF ( reservedat.reservenotes ) %] -

Notes: [% reservedat.reservenotes %]

- [% END %] - - - -[% END %] -
-[% INCLUDE 'intranet-bottom.inc' %] diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/printslip.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/printslip.tt new file mode 100644 index 0000000..a790069 --- /dev/null +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/printslip.tt @@ -0,0 +1,28 @@ +[% INCLUDE 'doc-head-open.inc' %] +[% title %] + + + +[% IF stylesheet %] + +[% END %] + + + + +
+ +[% IF plain %] +
+[% slip %]
+
+[% ELSE %] +[% slip %] +[% END %] + +[% INCLUDE 'intranet-bottom.inc' %] diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/letter.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/letter.tt index 063236e..eec2384 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/letter.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/letter.tt @@ -5,14 +5,29 @@ -
- +[% IF ( no_op_set ) %] +
+ + [% UNLESS independant_branch %] +

+ Select a library : + +

+ [% END %] +

+ + +

+
+ [% IF ( search ) %]

You Searched for [% searchfield %]

[% END %] - [% IF ( letter ) %] + [% IF ( letter && !independant_branch) %] + [% select_for_copy = BLOCK %] + + [% END %] + [% END %] +
+ + - [% FOREACH lette IN letter %] - [% UNLESS ( loop.odd ) %] + + [% FOREACH lette IN letter %] + [% can_edit = lette.branchcode || !independant_branch %] + [% UNLESS ( loop.odd ) %] - [% ELSE %] + [% ELSE %] - [% END %] + [% END %] + + - [% END %] + [% END %] +
Branch Module Code Name     
[% lette.branchname || "(All libraries)" %] [% lette.module %] [% lette.code %] [% lette.name %] - Edit + [% IF can_edit %] + Edit + [% END %] + + [% IF !independant_branch || !lette.branchcode %] +
+ + + + + [% IF independant_branch %] + + [% ELSE %] + [% select_for_copy %] + [% END %] + +
+ [% END %]
- [% IF ( lette.protected ) %] - - - [% ELSE %] - Delete - [% END %] + [% IF !lette.protected && can_edit %] + Delete + [% END %]
- [% END %] +[% END %] - [% END %] - [% IF ( add_form ) %] +[% IF ( add_form ) %] -
- + + [% IF ( modify ) %] @@ -182,6 +229,20 @@ $(document).ready(function() {
[% IF ( modify ) %]Modify notice[% ELSE %]Add notice[% END %]
    + + [% IF independant_branch %] + + [% ELSE %] +
  1. + + +
  2. + [% END %]
  3. @@ -235,6 +296,14 @@ $(document).ready(function() {
  4. + + [% IF is_html %] + + [% ELSE %] + + [% END %] +
  5. +
  6. @@ -252,27 +321,31 @@ $(document).ready(function() {
+
+
- [% END %] +[% END %] - [% IF ( add_validate ) %] +[% IF ( add_validate ) %] Data recorded
- [% END %] +[% END %] - [% IF ( delete_confirm ) %] +[% IF ( delete_confirm ) %]

Delete Notice?

+ + @@ -280,6 +353,7 @@ $(document).ready(function() {
Branch Module Code Name
[% branchname %] [% module %] [% code %] [% name %]
+ @@ -290,14 +364,14 @@ $(document).ready(function() {
- [% END %] +[% END %] - [% IF ( delete_confirmed ) %] +[% IF ( delete_confirmed ) %] Data deleted
- [% END %] +[% END %]
diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/tools-home.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/tools-home.tt index b71a1ee..5cc3bbf 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/tools-home.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/tools-home.tt @@ -26,7 +26,7 @@ [% END %] [% IF ( CAN_user_tools_edit_notices ) %] -
Notices
+
Notices & Slips
Define notices (print and email notification messages for overdues, etc.)
[% END %] diff --git a/members/memberentry.pl b/members/memberentry.pl index 86dd6ed..c474a66 100755 --- a/members/memberentry.pl +++ b/members/memberentry.pl @@ -347,10 +347,7 @@ if ((!$nok) and $nodouble and ($op eq 'insert' or $op eq 'save')){ # if we manage to find a valid email address, send notice if ($emailaddr) { $newdata{emailaddr} = $emailaddr; - my $letter = getletter ('members', "ACCTDETAILS:$newdata{'branchcode'}") ; - # if $branch notice fails, then email a default notice instead. - $letter = getletter ('members', "ACCTDETAILS") if !$letter; - SendAlerts ( 'members' , \%newdata , $letter ) if $letter + SendAlerts ( 'members', \%newdata, "ACCTDETAILS" ); } } diff --git a/members/moremember.pl b/members/moremember.pl index c477100..5a988f9 100755 --- a/members/moremember.pl +++ b/members/moremember.pl @@ -51,7 +51,6 @@ use C4::Reserves; use C4::Branch; # GetBranchName use C4::Overdues qw/CheckBorrowerDebarred/; use C4::Form::MessagingPreferences; -use C4::NewsChannels; #get slip news use List::MoreUtils qw/uniq/; use C4::Members::Attributes qw(GetBorrowerAttributes); @@ -484,13 +483,4 @@ $template->param( activeBorrowerRelationship => (C4::Context->preference('borrowerRelationship') ne ''), ); -#Get the slip news items -my $all_koha_news = &GetNewsToDisplay("slip"); -my $koha_news_count = scalar @$all_koha_news; - -$template->param( - koha_news => $all_koha_news, - koha_news_count => $koha_news_count -); - output_html_with_http_headers $input, $cookie, $template->output; diff --git a/members/printslip.pl b/members/printslip.pl new file mode 100755 index 0000000..3a499cd --- /dev/null +++ b/members/printslip.pl @@ -0,0 +1,92 @@ +#!/usr/bin/perl + +# Copyright 2000-2002 Katipo Communications +# Copyright 2010 BibLibre +# +# 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., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + +=head1 moremember.pl + + script to do a borrower enquiry/bring up borrower details etc + Displays all the details about a borrower + written 20/12/99 by chris@katipo.co.nz + last modified 21/1/2000 by chris@katipo.co.nz + modified 31/1/2001 by chris@katipo.co.nz + to not allow items on request to be renewed + + needs html removed and to use the C4::Output more, but its tricky + +=cut + +use strict; +#use warnings; FIXME - Bug 2505 +use CGI; +use C4::Context; +use C4::Auth qw/:DEFAULT get_session/; +use C4::Output; +use C4::Members; +use C4::Koha; + +#use Smart::Comments; +#use Data::Dumper; + +use vars qw($debug); + +BEGIN { + $debug = $ENV{DEBUG} || 0; +} + +my $input = new CGI; +my $sessionID = $input->cookie("CGISESSID"); +my $session = get_session($sessionID); + +$debug or $debug = $input->param('debug') || 0; +my $print = $input->param('print'); +my $error = $input->param('error'); + +# circ staff who process checkouts but can't edit +# patrons still need to be able to print receipts +my $flagsrequired = { circulate => "circulate_remaining_permissions" }; + +my ( $template, $loggedinuser, $cookie ) = get_template_and_user( + { + template_name => "circ/printslip.tmpl", + query => $input, + type => "intranet", + authnotrequired => 0, + flagsrequired => $flagsrequired, + debug => 1, + } +); + +my $borrowernumber = $input->param('borrowernumber'); +my $branch=C4::Context->userenv->{'branch'}; +my ($slip, $is_html); +if (my $letter = IssueSlip ($session->param('branch') || $branch, $borrowernumber, $print eq "qslip")) { + $slip = $letter->{content}; + $is_html = $letter->{is_html}; +} + +$template->param( + slip => $slip, + plain => !$is_html, + title => "Print Receipt for $borrowernumber", + stylesheet => C4::Context->preference("SlipCSS"), + error => $error, +); + +output_html_with_http_headers $input, $cookie, $template->output; diff --git a/misc/cronjobs/advance_notices.pl b/misc/cronjobs/advance_notices.pl index 1fa358f..09c4017 100755 --- a/misc/cronjobs/advance_notices.pl +++ b/misc/cronjobs/advance_notices.pl @@ -79,13 +79,10 @@ patrons. It queues them in the message queue, which is processed by the process_message_queue.pl cronjob. See the comments in the script for directions on changing the script. This script has the following parameters : - -c Confirm and remove this help & warning - -m maximum number of days in advance to send advance notices. - -n send No mail. Instead, all mail messages are printed on screen. Usefull for testing purposes. - -v verbose - -i csv list of fields that get substituted into templates in places - of the EEitems.contentEE placeholder. Defaults to - issuedate,title,barcode,author + -c Confirm and remove this help & warning + -m maximum number of days in advance to send advance notices. + -n send No mail. Instead, all mail messages are printed on screen. Usefull for testing purposes. + -v verbose ENDUSAGE # Since advance notice options are not visible in the web-interface @@ -157,8 +154,6 @@ UPCOMINGITEM: foreach my $upcoming ( @$upcoming_dues ) { } else { my $biblio = C4::Biblio::GetBiblioFromItemNumber( $upcoming->{'itemnumber'} ); my $letter_type = 'DUE'; - $letter = C4::Letters::getletter( 'circulation', $letter_type ); - die "no letter of type '$letter_type' found. Please see sample_notices.sql" unless $letter; $sth->execute($upcoming->{'borrowernumber'},$upcoming->{'itemnumber'},'0'); my $titles = ""; while ( my $item_info = $sth->fetchrow_hashref()) { @@ -166,13 +161,14 @@ UPCOMINGITEM: foreach my $upcoming ( @$upcoming_dues ) { $titles .= join("\t",@item_info) . "\n"; } - $letter = parse_letter( { letter => $letter, + $letter = parse_letter( { letter_code => $letter_type, borrowernumber => $upcoming->{'borrowernumber'}, branchcode => $upcoming->{'branchcode'}, biblionumber => $biblio->{'biblionumber'}, itemnumber => $upcoming->{'itemnumber'}, substitute => { 'items.content' => $titles } - } ); + } ) + or die "no letter of type '$letter_type' found. Please see sample_notices.sql"; } } else { $borrower_preferences = C4::Members::Messaging::GetMessagingPreferences( { borrowernumber => $upcoming->{'borrowernumber'}, @@ -189,8 +185,6 @@ UPCOMINGITEM: foreach my $upcoming ( @$upcoming_dues ) { } else { my $biblio = C4::Biblio::GetBiblioFromItemNumber( $upcoming->{'itemnumber'} ); my $letter_type = 'PREDUE'; - $letter = C4::Letters::getletter( 'circulation', $letter_type ); - die "no letter of type '$letter_type' found. Please see sample_notices.sql" unless $letter; $sth->execute($upcoming->{'borrowernumber'},$upcoming->{'itemnumber'},$borrower_preferences->{'days_in_advance'}); my $titles = ""; while ( my $item_info = $sth->fetchrow_hashref()) { @@ -198,13 +192,14 @@ UPCOMINGITEM: foreach my $upcoming ( @$upcoming_dues ) { $titles .= join("\t",@item_info) . "\n"; } - $letter = parse_letter( { letter => $letter, + $letter = parse_letter( { letter_code => $letter_type, borrowernumber => $upcoming->{'borrowernumber'}, branchcode => $upcoming->{'branchcode'}, biblionumber => $biblio->{'biblionumber'}, itemnumber => $upcoming->{'itemnumber'}, substitute => { 'items.content' => $titles } - } ); + } ) + or die "no letter of type '$letter_type' found. Please see sample_notices.sql"; } } @@ -250,8 +245,6 @@ PATRON: while ( my ( $borrowernumber, $digest ) = each %$upcoming_digest ) { my $letter_type = 'PREDUEDGST'; - my $letter = C4::Letters::getletter( 'circulation', $letter_type ); - die "no letter of type '$letter_type' found. Please see sample_notices.sql" unless $letter; $sth->execute($borrowernumber,$borrower_preferences->{'days_in_advance'}); my $titles = ""; @@ -259,12 +252,13 @@ PATRON: while ( my ( $borrowernumber, $digest ) = each %$upcoming_digest ) { my @item_info = map { $_ =~ /^date|date$/ ? format_date($item_info->{$_}) : $item_info->{$_} || '' } @item_content_fields; $titles .= join("\t",@item_info) . "\n"; } - $letter = parse_letter( { letter => $letter, + my $letter = parse_letter( { letter_code => $letter_type, borrowernumber => $borrowernumber, substitute => { count => $count, 'items.content' => $titles } - } ); + } ) + or die "no letter of type '$letter_type' found. Please see sample_notices.sql"; if ($nomail) { local $, = "\f"; print $letter->{'content'}; @@ -290,20 +284,19 @@ PATRON: while ( my ( $borrowernumber, $digest ) = each %$due_digest ) { next PATRON unless $borrower_preferences; # how could this happen? my $letter_type = 'DUEDGST'; - my $letter = C4::Letters::getletter( 'circulation', $letter_type ); - die "no letter of type '$letter_type' found. Please see sample_notices.sql" unless $letter; $sth->execute($borrowernumber,'0'); my $titles = ""; while ( my $item_info = $sth->fetchrow_hashref()) { my @item_info = map { $_ =~ /^date|date$/ ? format_date($item_info->{$_}) : $item_info->{$_} || '' } @item_content_fields; $titles .= join("\t",@item_info) . "\n"; } - $letter = parse_letter( { letter => $letter, + my $letter = parse_letter( { letter_code => $letter_type, borrowernumber => $borrowernumber, substitute => { count => $count, 'items.content' => $titles } - } ); + } ) + or die "no letter of type '$letter_type' found. Please see sample_notices.sql"; if ($nomail) { local $, = "\f"; @@ -323,40 +316,35 @@ PATRON: while ( my ( $borrowernumber, $digest ) = each %$due_digest ) { =head2 parse_letter - - =cut sub parse_letter { my $params = shift; - foreach my $required ( qw( letter borrowernumber ) ) { + foreach my $required ( qw( letter_code borrowernumber ) ) { return unless exists $params->{$required}; } - if ( $params->{'substitute'} ) { - while ( my ($key, $replacedby) = each %{$params->{'substitute'}} ) { - my $replacefield = "<<$key>>"; - - $params->{'letter'}->{title} =~ s/$replacefield/$replacedby/g; - $params->{'letter'}->{content} =~ s/$replacefield/$replacedby/g; - } - } - - C4::Letters::parseletter( $params->{'letter'}, 'borrowers', $params->{'borrowernumber'} ); + my %table_params = ( 'borrowers' => $params->{'borrowernumber'} ); - if ( $params->{'branchcode'} ) { - C4::Letters::parseletter( $params->{'letter'}, 'branches', $params->{'branchcode'} ); + if ( my $p = $params->{'branchcode'} ) { + $table_params{'branches'} = $p; } - if ( $params->{'itemnumber'} ) { - C4::Letters::parseletter( $params->{'letter'}, 'issues', $params->{'itemnumber'} ); - C4::Letters::parseletter( $params->{'letter'}, 'items', $params->{'itemnumber'} ); + if ( my $p = $params->{'itemnumber'} ) { + $table_params{'issues'} = $p; + $table_params{'items'} = $p; } - if ( $params->{'biblionumber'} ) { - C4::Letters::parseletter( $params->{'letter'}, 'biblio', $params->{'biblionumber'} ); - C4::Letters::parseletter( $params->{'letter'}, 'biblioitems', $params->{'biblionumber'} ); + if ( my $p = $params->{'biblionumber'} ) { + $table_params{'biblio'} = $p; + $table_params{'biblioitems'} = $p; } - return $params->{'letter'}; + return C4::Letters::GetPreparedLetter ( + module => 'circulation', + letter_code => $params->{'letter_code'}, + branchcode => $table_params{'branches'}, + substitute => $params->{'substitute'}, + tables => \%table_params, + ); } 1; diff --git a/misc/cronjobs/gather_print_notices.pl b/misc/cronjobs/gather_print_notices.pl index a72d6a6..165b16e 100755 --- a/misc/cronjobs/gather_print_notices.pl +++ b/misc/cronjobs/gather_print_notices.pl @@ -39,11 +39,9 @@ use Getopt::Long; sub usage { print STDERR < \$stylesheet, 'h|help' => \$help, ) || usage( 1 ); @@ -71,16 +68,9 @@ exit unless( @messages ); open OUTPUT, '>', File::Spec->catdir( $output_directory, "holdnotices-" . $today->output( 'iso' ) . ".html" ); my $template = C4::Templates::gettemplate( 'batch/print-notices.tmpl', 'intranet', new CGI ); -my $stylesheet_contents = ''; - -if ($stylesheet) { - open STYLESHEET, '<', $stylesheet; - while ( ) { $stylesheet_contents .= $_ } - close STYLESHEET; -} $template->param( - stylesheet => $stylesheet_contents, + stylesheet => C4::Context->preference("NoticeCSS"), today => $today->output(), messages => \@messages, ); diff --git a/misc/cronjobs/overdue_notices.pl b/misc/cronjobs/overdue_notices.pl index 5896abd..d303f4f 100755 --- a/misc/cronjobs/overdue_notices.pl +++ b/misc/cronjobs/overdue_notices.pl @@ -460,16 +460,6 @@ END_SQL { $verbose and warn "borrower $firstname, $lastname ($borrowernumber) has items triggering level $i."; - my $letter = C4::Letters::getletter( 'circulation', $overdue_rules->{"letter$i"} ); - - unless ($letter) { - $verbose and warn "Message '$overdue_rules->{letter$i}' content not found"; - - # might as well skip while PERIOD, no other borrowers are going to work. - # FIXME : Does this mean a letter must be defined in order to trigger a debar ? - next PERIOD; - } - if ( $overdue_rules->{"debarred$i"} ) { #action taken is debarring @@ -494,11 +484,12 @@ END_SQL my @item_info = map { $_ =~ /^date|date$/ ? format_date( $item_info->{$_} ) : $item_info->{$_} || '' } @item_content_fields; $titles .= join("\t", @item_info) . "\n"; $itemcount++; - push @items, { itemnumber => $item_info->{'itemnumber'}, biblionumber => $item_info->{'biblionumber'} }; + push @items, $item_info; } $sth2->finish; - $letter = parse_letter( - { letter => $letter, + + my $letter = parse_letter( + { letter_code => $overdue_rules->{"letter$i"}, borrowernumber => $borrowernumber, branchcode => $branchcode, items => \@items, @@ -509,6 +500,13 @@ END_SQL } } ); + unless ($letter) { + $verbose and warn "Message '$overdue_rules->{letter$i}' content not found"; + + # might as well skip while PERIOD, no other borrowers are going to work. + # FIXME : Does this mean a letter must be defined in order to trigger a debar ? + next PERIOD; + } if ( $exceededPrintNoticesMaxLines ) { $letter->{'content'} .= "List too long for form; please check your account online for a complete list of your overdue items."; @@ -643,54 +641,56 @@ substituted keys and values. =cut -sub parse_letter { # FIXME: this code should probably be moved to C4::Letters:parseletter +sub parse_letter { my $params = shift; - foreach my $required (qw( letter borrowernumber )) { + foreach my $required (qw( letter_code borrowernumber )) { return unless exists $params->{$required}; } - my $todaysdate = C4::Dates->new()->output("syspref"); - $params->{'letter'}->{title} =~ s/<>/$todaysdate/g; - $params->{'letter'}->{content} =~ s/<>/$todaysdate/g; + my $substitute = $params->{'substitute'} || {}; + $substitute->{today} ||= C4::Dates->new()->output("syspref"); - if ( $params->{'substitute'} ) { - while ( my ( $key, $replacedby ) = each %{ $params->{'substitute'} } ) { - my $replacefield = "<<$key>>"; - $params->{'letter'}->{title} =~ s/$replacefield/$replacedby/g; - $params->{'letter'}->{content} =~ s/$replacefield/$replacedby/g; - } + my %tables = ( 'borrowers' => $params->{'borrowernumber'} ); + if ( my $p = $params->{'branchcode'} ) { + $tables{'branches'} = $p; } - $params->{'letter'} = C4::Letters::parseletter( $params->{'letter'}, 'borrowers', $params->{'borrowernumber'} ); - - if ( $params->{'branchcode'} ) { - $params->{'letter'} = C4::Letters::parseletter( $params->{'letter'}, 'branches', $params->{'branchcode'} ); + my $currency_format; + if ($params->{'letter'}->{'content'} =~ m/(.*)<\/fine>/o) { # process any fine tags... + $currency_format = $1; + $params->{'letter'}->{'content'} =~ s/.*<\/fine>/<>/o; } - if ( $params->{'items'} ) { + my @item_tables; + if ( my $i = $params->{'items'} ) { my $item_format = ''; - PROCESS_ITEMS: - while (scalar(@{$params->{'items'}}) > 0) { - my $item = shift @{$params->{'items'}}; + foreach my $item (@$i) { my $fine = GetFine($item->{'itemnumber'}, $params->{'borrowernumber'}); if (!$item_format) { $params->{'letter'}->{'content'} =~ m/(.*<\/item>)/; $item_format = $1; } - if ($params->{'letter'}->{'content'} =~ m/(.*)<\/fine>/) { # process any fine tags... - my $formatted_fine = currency_format("$1", "$fine", FMT_SYMBOL); - $params->{'letter'}->{'content'} =~ s/.*<\/fine>/$formatted_fine/; - } - $params->{'letter'} = C4::Letters::parseletter( $params->{'letter'}, 'biblio', $item->{'biblionumber'} ); - $params->{'letter'} = C4::Letters::parseletter( $params->{'letter'}, 'biblioitems', $item->{'biblionumber'} ); - $params->{'letter'} = C4::Letters::parseletter( $params->{'letter'}, 'items', $item->{'itemnumber'} ); - $params->{'letter'} = C4::Letters::parseletter( $params->{'letter'}, 'issues', $item->{'itemnumber'} ); - $params->{'letter'}->{'content'} =~ s/(.*<\/item>)/$1\n$item_format/ if scalar(@{$params->{'items'}} > 0); + $item->{'fine'} = currency_format($currency_format, "$fine", FMT_SYMBOL) + if $currency_format; + + push @item_tables, { + 'biblio' => $item->{'biblionumber'}, + 'biblioitems' => $item->{'biblionumber'}, + 'items' => $item, + 'issues' => $item->{'itemnumber'}, + }; } } - $params->{'letter'}->{'content'} =~ s/<\/{0,1}?item>//g; # strip all remaining item tags... - return $params->{'letter'}; + + return C4::Letters::GetPreparedLetter ( + module => 'circulation', + letter_code => $params->{'letter_code'}, + branchcode => $params->{'branchcode'}, + tables => \%tables, + substitute => $substitute, + repeat => { item => \@item_tables }, + ); } =head2 prepare_letter_for_printing diff --git a/t/db_dependent/lib/KohaTest/Letters.pm b/t/db_dependent/lib/KohaTest/Letters.pm index 97d58fb..f2d7b0d 100644 --- a/t/db_dependent/lib/KohaTest/Letters.pm +++ b/t/db_dependent/lib/KohaTest/Letters.pm @@ -12,13 +12,12 @@ sub testing_class { 'C4::Letters' }; sub methods : Test( 1 ) { my $self = shift; - my @methods = qw( getletter - addalert + my @methods = qw( addalert delalert getalert findrelatedto SendAlerts - parseletter + GetPreparedLetter ); can_ok( $self->testing_class, @methods ); diff --git a/t/db_dependent/lib/KohaTest/Letters/GetLetter.pm b/t/db_dependent/lib/KohaTest/Letters/GetLetter.pm index 76b6ab4..53e5439 100644 --- a/t/db_dependent/lib/KohaTest/Letters/GetLetter.pm +++ b/t/db_dependent/lib/KohaTest/Letters/GetLetter.pm @@ -10,7 +10,7 @@ use Test::More; sub GetLetter : Test( 6 ) { my $self = shift; - my $letter = getletter( 'circulation', 'ODUE' ); + my $letter = getletter( 'circulation', 'ODUE', '' ); isa_ok( $letter, 'HASH' ) or diag( Data::Dumper->Dump( [ $letter ], [ 'letter' ] ) ); @@ -21,7 +21,6 @@ sub GetLetter : Test( 6 ) { ok( exists $letter->{'name'}, 'name' ); ok( exists $letter->{'title'}, 'title' ); - } 1; diff --git a/t/db_dependent/lib/KohaTest/Members.pm b/t/db_dependent/lib/KohaTest/Members.pm index 5646be1..dfde7da 100644 --- a/t/db_dependent/lib/KohaTest/Members.pm +++ b/t/db_dependent/lib/KohaTest/Members.pm @@ -52,6 +52,7 @@ sub methods : Test( 1 ) { GetBorrowersWhoHaveNeverBorrowed GetBorrowersWithIssuesHistoryOlderThan GetBorrowersNamesAndLatestIssue + IssueSlip ); can_ok( $self->testing_class, @methods ); diff --git a/t/db_dependent/lib/KohaTest/Print.pm b/t/db_dependent/lib/KohaTest/Print.pm index 02fd5fb..d35ab34 100644 --- a/t/db_dependent/lib/KohaTest/Print.pm +++ b/t/db_dependent/lib/KohaTest/Print.pm @@ -12,10 +12,7 @@ sub testing_class { 'C4::Print' }; sub methods : Test( 1 ) { my $self = shift; - my @methods = qw( remoteprint - printreserve - printslip - ); + my @methods = qw( printslip ); can_ok( $self->testing_class, @methods ); } diff --git a/t/db_dependent/lib/KohaTest/Reserves.pm b/t/db_dependent/lib/KohaTest/Reserves.pm index 8b05dd0..6416ac3 100644 --- a/t/db_dependent/lib/KohaTest/Reserves.pm +++ b/t/db_dependent/lib/KohaTest/Reserves.pm @@ -33,6 +33,7 @@ sub methods : Test( 1 ) { GetReserveInfo _FixPriority _Findgroupreserve + ReserveSlip ); can_ok( $self->testing_class, @methods ); diff --git a/tools/letter.pl b/tools/letter.pl index 04cd7d2..ae47810 100755 --- a/tools/letter.pl +++ b/tools/letter.pl @@ -46,14 +46,35 @@ use CGI; use C4::Auth; use C4::Context; use C4::Output; +use C4::Branch; # GetBranches +use C4::Members::Attributes; -# letter_exists($module, $code) -# - return true if a letter with the given $module and $code exists +# _letter_from_where($branchcode,$module, $code) +# - return FROM WHERE clause and bind args for a letter +sub _letter_from_where { + my ($branchcode, $module, $code) = @_; + my $sql = q{FROM letter WHERE branchcode = ? AND module = ? AND code = ?}; + my @args = ($branchcode || '', $module, $code); +# Mysql is retarded. cause branchcode is part of the primary key it cannot be null. How does that +# work with foreign key constraint I wonder... + +# if ($branchcode) { +# $sql .= " AND branchcode = ?"; +# push @args, $branchcode; +# } else { +# $sql .= " AND branchcode IS NULL"; +# } + + return ($sql, \@args); +} + +# letter_exists($branchcode,$module, $code) +# - return true if a letter with the given $branchcode, $module and $code exists sub letter_exists { - my ($module, $code) = @_; + my ($sql, $args) = _letter_from_where(@_); my $dbh = C4::Context->dbh; - my $letters = $dbh->selectall_arrayref(q{SELECT name FROM letter WHERE module = ? AND code = ?}, undef, $module, $code); - return @{$letters}; + my $letter = $dbh->selectrow_hashref("SELECT * $sql", undef, @$args); + return $letter; } # $protected_letters = protected_letters() @@ -67,16 +88,14 @@ sub protected_letters { my $input = new CGI; my $searchfield = $input->param('searchfield'); my $script_name = '/cgi-bin/koha/tools/letter.pl'; +my $branchcode = $input->param('branchcode'); my $code = $input->param('code'); my $module = $input->param('module'); my $content = $input->param('content'); -my $op = $input->param('op'); +my $op = $input->param('op') || ''; my $dbh = C4::Context->dbh; -if (!defined $module ) { - $module = q{}; -} -my ( $template, $borrowernumber, $cookie ) = get_template_and_user( +my ( $template, $borrowernumber, $cookie, $staffflags ) = get_template_and_user( { template_name => 'tools/letter.tmpl', query => $input, @@ -87,32 +106,39 @@ my ( $template, $borrowernumber, $cookie ) = get_template_and_user( } ); -if (!defined $op) { - $op = q{}; # silence errors from eq -} +my $my_branch = C4::Context->preference("IndependantBranches") && !$staffflags->{'superlibrarian'} + ? C4::Context->userenv()->{'branch'} + : undef; # we show only the TMPL_VAR names $op $template->param( + independant_branch => $my_branch, script_name => $script_name, + searchfield => $searchfield, action => $script_name ); +if ($op eq 'copy') { + add_copy(); + $op = 'add_form'; +} + if ($op eq 'add_form') { - add_form($module, $code); + add_form($branchcode, $module, $code); } elsif ( $op eq 'add_validate' ) { add_validate(); $op = q{}; # next operation is to return to default screen } elsif ( $op eq 'delete_confirm' ) { - delete_confirm($module, $code); + delete_confirm($branchcode, $module, $code); } elsif ( $op eq 'delete_confirmed' ) { - delete_confirmed($module, $code); + delete_confirmed($branchcode, $module, $code); $op = q{}; # next operation is to return to default screen } else { - default_display($searchfield); + default_display($branchcode,$searchfield); } # Do this last as delete_confirmed resets @@ -125,23 +151,21 @@ if ($op) { output_html_with_http_headers $input, $cookie, $template->output; sub add_form { - my ($module, $code ) = @_; + my ($branchcode,$module, $code ) = @_; my $letter; # if code has been passed we can identify letter and its an update action if ($code) { - $letter = $dbh->selectrow_hashref(q{SELECT module, code, name, title, content FROM letter WHERE module=? AND code=?}, - undef, $module, $code); + $letter = letter_exists($branchcode,$module, $code); + } + if ($letter) { $template->param( modify => 1 ); $template->param( code => $letter->{code} ); } else { # initialize the new fields $letter = { - module => $module, - code => q{}, - name => q{}, - title => q{}, - content => q{}, + branchcode => $branchcode, + module => $module, }; $template->param( adding => 1 ); } @@ -173,14 +197,20 @@ sub add_form { {value => q{}, text => '---ITEMS---' }, {value => 'items.content', text => 'items.content'}, add_fields('issues','borrowers'); + if ($module eq 'circulation') { + push @{$field_selection}, add_fields('opac_news'); + } } $template->param( - name => $letter->{name}, - title => $letter->{title}, - content => $letter->{content}, - module => $module, - $module => 1, + branchcode => $letter->{branchcode}, + name => $letter->{name}, + is_html => $letter->{is_html}, + title => $letter->{title}, + content => $letter->{content}, + module => $module, + $module => 1, + branchloop => _branchloop($branchcode), SQLfieldname => $field_selection, ); return; @@ -188,37 +218,56 @@ sub add_form { sub add_validate { my $dbh = C4::Context->dbh; - my $module = $input->param('module'); - my $oldmodule = $input->param('oldmodule'); - my $code = $input->param('code'); - my $name = $input->param('name'); - my $title = $input->param('title'); - my $content = $input->param('content'); - if (letter_exists($oldmodule, $code)) { + my $oldbranchcode = $input->param('oldbranchcode'); + my $branchcode = $input->param('branchcode') || ''; + my $module = $input->param('module'); + my $oldmodule = $input->param('oldmodule'); + my $code = $input->param('code'); + my $name = $input->param('name'); + my $is_html = $input->param('is_html'); + my $title = $input->param('title'); + my $content = $input->param('content'); + if (letter_exists($oldbranchcode,$oldmodule, $code)) { $dbh->do( - q{UPDATE letter SET module = ?, code = ?, name = ?, title = ?, content = ? WHERE module = ? AND code = ?}, + q{UPDATE letter SET branchcode = ?, module = ?, name = ?, is_html = ?, title = ?, content = ? WHERE branchcode = ? AND module = ? AND code = ?}, undef, - $module, $code, $name, $title, $content, - $oldmodule, $code + $branchcode, $module, $name, $is_html || 0, $title, $content, + $oldbranchcode, $oldmodule, $code ); } else { $dbh->do( - q{INSERT INTO letter (module,code,name,title,content) VALUES (?,?,?,?,?)}, + q{INSERT INTO letter (branchcode,module,code,name,is_html,title,content) VALUES (?,?,?,?,?,?,?)}, undef, - $module, $code, $name, $title, $content + $branchcode, $module, $code, $name, $is_html || 0, $title, $content ); } # set up default display - default_display(); - return; + default_display($branchcode); +} + +sub add_copy { + my $dbh = C4::Context->dbh; + my $oldbranchcode = $input->param('oldbranchcode'); + my $branchcode = $input->param('branchcode'); + my $module = $input->param('module'); + my $code = $input->param('code'); + + return if letter_exists($branchcode,$module, $code); + + my $old_letter = letter_exists($oldbranchcode,$module, $code); + + $dbh->do( + q{INSERT INTO letter (branchcode,module,code,name,is_html,title,content) VALUES (?,?,?,?,?,?,?)}, + undef, + $branchcode, $module, $code, $old_letter->{name}, $old_letter->{is_html}, $old_letter->{title}, $old_letter->{content} + ); } sub delete_confirm { - my ($module, $code) = @_; + my ($branchcode, $module, $code) = @_; my $dbh = C4::Context->dbh; - my $letter = $dbh->selectrow_hashref(q|SELECT name FROM letter WHERE module = ? AND code = ?|, - { Slice => {} }, - $module, $code); + my $letter = letter_exists($branchcode, $module, $code); + $template->param( branchcode => $branchcode, branchname => GetBranchName($branchcode) ); $template->param( code => $code ); $template->param( module => $module); $template->param( name => $letter->{name}); @@ -226,40 +275,53 @@ sub delete_confirm { } sub delete_confirmed { - my ($module, $code) = @_; + my ($branchcode, $module, $code) = @_; + my ($sql, $args) = _letter_from_where($branchcode, $module, $code); my $dbh = C4::Context->dbh; - $dbh->do('DELETE FROM letter WHERE module=? AND code=?',{},$module,$code); + $dbh->do("DELETE $sql", undef, @$args); # setup default display for screen - default_display(); + default_display($branchcode); return; } sub retrieve_letters { - my $searchstring = shift; + my ($branchcode, $searchstring) = @_; + + $branchcode = $my_branch if $branchcode && $my_branch; + my $dbh = C4::Context->dbh; - if ($searchstring) { - if ($searchstring=~m/(\S+)/) { - $searchstring = $1 . q{%}; - return $dbh->selectall_arrayref('SELECT module, code, name FROM letter WHERE code LIKE ? ORDER BY module, code', - { Slice => {} }, $searchstring); - } + my ($sql, @where, @args); + $sql = "SELECT branchcode, module, code, name, branchname + FROM letter + LEFT OUTER JOIN branches USING (branchcode)"; + if ($searchstring && $searchstring=~m/(\S+)/) { + $searchstring = $1 . q{%}; + push @where, 'code LIKE ?'; + push @args, $searchstring; } - else { - return $dbh->selectall_arrayref('SELECT module, code, name FROM letter ORDER BY module, code', { Slice => {} }); + elsif ($branchcode) { + push @where, 'branchcode = ?'; + push @args, $branchcode || ''; } - return; + elsif ($my_branch) { + push @where, "(branchcode = ? OR branchcode = '')"; + push @args, $my_branch; + } + + $sql .= " WHERE ".join(" AND ", @where) if @where; + $sql .= " ORDER BY module, code, branchcode"; +# use Data::Dumper; die Dumper($sql, \@args); + return $dbh->selectall_arrayref($sql, { Slice => {} }, @args); } sub default_display { - my $searchfield = shift; - my $results; + my ($branchcode, $searchfield) = @_; + if ( $searchfield ) { $template->param( search => 1 ); - $template->param( searchfield => $searchfield ); - $results = retrieve_letters($searchfield); - } else { - $results = retrieve_letters(); } + my $results = retrieve_letters($branchcode,$searchfield); + my $loop_data = []; my $protected_letters = protected_letters(); foreach my $row (@{$results}) { @@ -267,8 +329,27 @@ sub default_display { push @{$loop_data}, $row; } - $template->param( letter => $loop_data ); - return; + + $template->param( + letter => $loop_data, + branchloop => _branchloop($branchcode), + ); +} + +sub _branchloop { + my ($branchcode) = @_; + + my $branches = GetBranches(); + my @branchloop; + for my $thisbranch (sort { $branches->{$a}->{branchname} cmp $branches->{$b}->{branchname} } keys %$branches) { + push @branchloop, { + value => $thisbranch, + selected => $branchcode && $thisbranch eq $branchcode, + branchname => $branches->{$thisbranch}->{'branchname'}, + }; + } + + return \@branchloop; } sub add_fields { @@ -307,6 +388,7 @@ sub get_columns_for { text => $tlabel, }; } + my $sql = "SHOW COLUMNS FROM $table";# TODO not db agnostic my $table_prefix = $table . q|.|; my $rows = C4::Context->dbh->selectall_arrayref($sql, { Slice => {} }); @@ -317,5 +399,15 @@ sub get_columns_for { text => $table_prefix . $row->{Field}, } } + if ($table eq 'borrowers') { + if ( my $attributes = C4::Members::Attributes::GetAttributes() ) { + foreach (@$attributes) { + push @fields, { + value => "borrower-attribute:$_", + text => "attribute:$_", + } + } + } + } return @fields; } -- 1.6.5