diff --git a/C4/Branch.pm b/C4/Branch.pm index a6ab59cc80..18177ec651 100644 --- a/C4/Branch.pm +++ b/C4/Branch.pm @@ -45,7 +45,7 @@ BEGIN { &DelBranch &DelBranchCategory ); - @EXPORT_OK = qw( &onlymine &mybranch ); + @EXPORT_OK = qw( &onlymine &mybranch get_branch_code_from_name ); } =head1 NAME @@ -572,6 +572,15 @@ sub CheckBranchCategorycode { return $total; } +sub get_branch_code_from_name { + my @branch_name = @_; + my $query = "SELECT branchcode FROM branches WHERE branchname=?;"; + my $dbh = C4::Context->dbh(); + my $sth = $dbh->prepare($query); + $sth->execute(@branch_name); + return $sth->fetchrow_array; +} + 1; __END__ diff --git a/C4/Labels.pm b/C4/Labels.pm deleted file mode 100644 index b9b0dec6f9..0000000000 --- a/C4/Labels.pm +++ /dev/null @@ -1,1494 +0,0 @@ -package C4::Labels; - -# Copyright 2006 Katipo Communications. -# -# This file is part of Koha. -# -# Koha is free software; you can redistribute it and/or modify it under the -# terms of the GNU General Public License as published by the Free Software -# Foundation; either version 2 of the License, or (at your option) any later -# version. -# -# Koha is distributed in the hope that it will be useful, but WITHOUT ANY -# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR -# A PARTICULAR PURPOSE. See the GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along with -# Koha; if not, write to the Free Software Foundation, Inc., 59 Temple Place, -# Suite 330, Boston, MA 02111-1307 USA - -use strict; -# use warnings; # FIXME -use vars qw($VERSION @ISA @EXPORT); - -use PDF::Reuse; -use Text::Wrap; -use Algorithm::CheckDigits; -use C4::Members; -use C4::Branch; -use C4::Debug; -use C4::Biblio; -use Text::CSV_XS; -use Data::Dumper; - -BEGIN { - $VERSION = 0.03; - require Exporter; - @ISA = qw(Exporter); - @EXPORT = qw( - &get_label_options &GetLabelItems - &build_circ_barcode &draw_boundaries - &drawbox &GetActiveLabelTemplate - &GetAllLabelTemplates &DeleteTemplate - &GetSingleLabelTemplate &SaveTemplate - &CreateTemplate &SetActiveTemplate - &SaveConf &GetTextWrapCols - &GetUnitsValue - &DrawSpineText - &DrawBarcode - &DrawPatronCardText - &get_printingtypes &GetPatronCardItems - &get_layouts - &get_barcode_types - &get_batches &delete_batch - &add_batch &printText - &GetItemFields - &get_text_fields - get_layout &save_layout &add_layout - &set_active_layout - &build_text_dropbox - &delete_layout &get_active_layout - &get_highest_batch - &deduplicate_batch - &GetAllPrinterProfiles &GetSinglePrinterProfile - &SaveProfile &CreateProfile &DeleteProfile - &GetAssociatedProfile &SetAssociatedProfile - ); -} - - -=head1 NAME - -C4::Labels - Functions for printing spine labels and barcodes in Koha - -=head1 FUNCTIONS - -=head2 get_label_options; - - $options = get_label_options() - -Return a pointer on a hash list containing info from labels_conf table in Koha DB. - -=cut - -sub get_label_options { - my $query2 = " SELECT * FROM labels_conf where active = 1"; # FIXME: exact same as get_active_layout - my $sth = C4::Context->dbh->prepare($query2); - $sth->execute(); - return $sth->fetchrow_hashref; -} - -sub get_layouts { - my $dbh = C4::Context->dbh; - my $query = " Select * from labels_conf"; - my $sth = $dbh->prepare($query); - $sth->execute(); - my @resultsloop; - while ( my $data = $sth->fetchrow_hashref ) { - $data->{'fieldlist'} = get_text_fields( $data->{'id'} ); - push( @resultsloop, $data ); - } - return @resultsloop; -} - -sub get_layout { - my ($layout_id) = @_; - my $dbh = C4::Context->dbh; - # get the actual items to be printed. - my $query = " Select * from labels_conf where id = ?"; - my $sth = $dbh->prepare($query); - $sth->execute($layout_id); - my $data = $sth->fetchrow_hashref; - return $data; -} - -sub get_active_layout { - my $query = " Select * from labels_conf where active = 1"; # FIXME: exact same as get_label_options - my $sth = C4::Context->dbh->prepare($query); - $sth->execute(); - return $sth->fetchrow_hashref; -} - -sub delete_layout { - my ($layout_id) = @_; - my $dbh = C4::Context->dbh; - # get the actual items to be printed. - my $query = "delete from labels_conf where id = ?"; - my $sth = $dbh->prepare($query); - $sth->execute($layout_id); -} - -sub get_printingtypes { - my ($layout_id) = @_; - my @printtypes; -# FIXME hard coded print types - push( @printtypes, { code => 'BAR', desc => "barcode only" } ); - push( @printtypes, { code => 'BIB', desc => "biblio only" } ); - push( @printtypes, { code => 'BARBIB', desc => "barcode / biblio" } ); - push( @printtypes, { code => 'BIBBAR', desc => "biblio / barcode" } ); - push( @printtypes, { code => 'ALT', desc => "alternating labels" } ); - push( @printtypes, { code => 'CSV', desc => "csv output" } ); - push( @printtypes, { code => 'PATCRD', desc => "patron cards" } ); - - my $conf = get_layout($layout_id); - my $active_printtype = $conf->{'printingtype'}; - - # lop thru layout, insert selected to hash - - foreach my $printtype (@printtypes) { - if ( $printtype->{'code'} eq $active_printtype ) { - $printtype->{'active'} = 1; - } - } - return @printtypes; -} - -# this sub (build_text_dropbox) is deprecated and should be deleted. -# rch 2008.04.15 -# -sub build_text_dropbox { - my ($order) = @_; - my $field_count = 7; # <----------- FIXME hard coded - my @lines; - !$order - ? push( @lines, { num => '', selected => '1' } ) - : push( @lines, { num => '' } ); - for ( my $i = 1 ; $i <= $field_count ; $i++ ) { - my $line = { num => "$i" }; - $line->{'selected'} = 1 if $i eq $order; - push( @lines, $line ); - } - return @lines; -} - -sub get_text_fields { - my ( $layout_id, $sorttype ) = @_; - my @sorted_fields; - my $error; - my $sortorder = get_layout($layout_id); - if ( $sortorder->{formatstring} ) { - if ( !$sorttype ) { - return $sortorder->{formatstring}; - } - else { - my $csv = Text::CSV_XS->new( { allow_whitespace => 1 } ); - my $line = $sortorder->{formatstring}; - my $status = $csv->parse($line); - @sorted_fields = - map { { 'code' => $_, desc => $_ } } $csv->fields(); - $error = $csv->error_input(); - warn $error if $error; # TODO - do more with this. - } - } - else { - - # These fields are hardcoded based on the template for label-edit-layout.pl - my @text_fields = ( - { - code => 'itemtype', - desc => "Item Type", - order => $sortorder->{'itemtype'} - }, - { - code => 'issn', - desc => "ISSN", - order => $sortorder->{'issn'} - }, - { - code => 'isbn', - desc => "ISBN", - order => $sortorder->{'isbn'} - }, - { - code => 'barcode', - desc => "Barcode", - order => $sortorder->{'barcode'} - }, - { - code => 'author', - desc => "Author", - order => $sortorder->{'author'} - }, - { - code => 'title', - desc => "Title", - order => $sortorder->{'title'} - }, - { - code => 'itemcallnumber', - desc => "Call Number", - order => $sortorder->{'itemcallnumber'} - }, - ); - - my @new_fields = (); - foreach my $field (@text_fields) { - push( @new_fields, $field ) if $field->{'order'} > 0; - } - - @sorted_fields = sort { $$a{order} <=> $$b{order} } @new_fields; - } - - # if we have a 'formatstring', then we ignore these hardcoded fields. - my $active_fields; - - if ( $sorttype eq 'codes' ) - { # FIXME: This sub should really always return the array of hashrefs and let the caller take what he wants from that -fbcit - return @sorted_fields; - } - else { - foreach my $field (@sorted_fields) { - $active_fields .= "$field->{'desc'} "; - } - return $active_fields; - } -} - -=head2 sub add_batch - -=over 4 - - add_batch($batch_type,\@batch_list); - if $batch_list is supplied, - create a new batch with those items. - else, return the next available batch_id. - -=back - -=cut - -sub add_batch ($;$) { - my $table = (@_ and 'patroncards' eq shift) ? 'patroncards' : 'labels'; - my $batch_list = (@_) ? shift : undef; - my $dbh = C4::Context->dbh; - # FIXME : batch_id should be an auto_incr INT. Temporarily casting as int ( see koha bug 2555 ) - # until a label_batches table is added, and we can convert batch_id to int. - my $q ="SELECT MAX( CAST(batch_id AS SIGNED) ) FROM $table"; - my $sth = $dbh->prepare($q); - $sth->execute(); - my ($batch_id) = $sth->fetchrow_array || 0; - $batch_id++; - if ($batch_list) { - if ($table eq 'patroncards') { - $sth = $dbh->prepare("INSERT INTO $table (`batch_id`,`borrowernumber`) VALUES (?,?)"); - } else { - $sth = $dbh->prepare("INSERT INTO $table (`batch_id`,`itemnumber` ) VALUES (?,?)"); - } - for (@$batch_list) { - $sth->execute($batch_id,$_); - } - } - return $batch_id; -} - -#FIXME: Needs to be ported to receive $batch_type -# ... this looks eerily like add_batch() ... -sub get_highest_batch { - my $table = (@_ and 'patroncards' eq shift) ? 'patroncards' : 'labels'; - my $q = - "select distinct batch_id from $table order by batch_id desc limit 1"; - my $sth = C4::Context->dbh->prepare($q); - $sth->execute(); - my $data = $sth->fetchrow_hashref or return 1; - return ($data->{'batch_id'} || 1); -} - - -sub get_batches (;$) { - my $table = (@_ and 'patroncards' eq shift) ? 'patroncards' : 'labels'; - my $q = "SELECT batch_id, COUNT(*) AS num FROM $table GROUP BY batch_id"; - my $sth = C4::Context->dbh->prepare($q); - $sth->execute(); - my $batches = $sth->fetchall_arrayref({}); - return @$batches; -} - -sub delete_batch { - my ($batch_id, $batch_type) = @_; - warn "Deleteing batch (id:$batch_id) of type $batch_type"; - my $q = "DELETE FROM $batch_type WHERE batch_id = ?"; - my $sth = C4::Context->dbh->prepare($q); - $sth->execute($batch_id); -} - -sub get_barcode_types { - my ($layout_id) = @_; - my $layout = get_layout($layout_id); - my $barcode = $layout->{'barcodetype'}; - my @array; - - push( @array, { code => 'CODE39', desc => 'Code 39' } ); - push( @array, { code => 'CODE39MOD', desc => 'Code39 + Modulo43' } ); - push( @array, { code => 'CODE39MOD10', desc => 'Code39 + Modulo10' } ); - push( @array, { code => 'ITF', desc => 'Interleaved 2 of 5' } ); - - foreach my $line (@array) { - if ( $line->{'code'} eq $barcode ) { - $line->{'active'} = 1; - } - } - return @array; -} - -sub GetUnitsValue { - my ($units) = @_; - my $unitvalue; - $unitvalue = '1' if ( $units eq 'POINT' ); - $unitvalue = '2.83464567' if ( $units eq 'MM' ); - $unitvalue = '28.3464567' if ( $units eq 'CM' ); - $unitvalue = 72 if ( $units eq 'INCH' ); - return $unitvalue; -} - -sub GetTextWrapCols { - my ( $font, $fontsize, $label_width, $left_text_margin ) = @_; - my $string = '0'; - my $strwidth; - my $count = 0; -# my $textlimit = $label_width - ($left_text_margin); - my $textlimit = $label_width - ( 3 * $left_text_margin); - - while ( $strwidth < $textlimit ) { - $strwidth = prStrWidth( $string, $font, $fontsize ); - $string = $string . '0'; - #warn "strwidth:$strwidth, textlimit:$textlimit, count:$count string:$string"; - $count++; - } - return $count; -} - -sub GetActiveLabelTemplate { - my $dbh = C4::Context->dbh; - my $query = " SELECT * FROM labels_templates where active = 1 limit 1"; - my $sth = $dbh->prepare($query); - $sth->execute(); - my $active_tmpl = $sth->fetchrow_hashref; - return $active_tmpl; -} - -sub GetSingleLabelTemplate { - my ($tmpl_id) = @_; - my $dbh = C4::Context->dbh; - my $query = " SELECT * FROM labels_templates where tmpl_id = ?"; - my $sth = $dbh->prepare($query); - $sth->execute($tmpl_id); - my $template = $sth->fetchrow_hashref; - return $template; -} - -sub SetActiveTemplate { - my ($tmpl_id) = @_; - my $dbh = C4::Context->dbh; - my $query = " UPDATE labels_templates SET active = NULL"; - my $sth = $dbh->prepare($query); - $sth->execute(); - - $query = "UPDATE labels_templates SET active = 1 WHERE tmpl_id = ?"; - $sth = $dbh->prepare($query); - $sth->execute($tmpl_id); -} - -sub set_active_layout { - my ($layout_id) = @_; - my $dbh = C4::Context->dbh; - my $query = " UPDATE labels_conf SET active = NULL"; - my $sth = $dbh->prepare($query); - $sth->execute(); - - $query = "UPDATE labels_conf SET active = 1 WHERE id = ?"; - $sth = $dbh->prepare($query); - $sth->execute($layout_id); -} - -sub DeleteTemplate { - my ($tmpl_id) = @_; - my $dbh = C4::Context->dbh; - my $query = " DELETE FROM labels_templates where tmpl_id = ?"; - my $sth = $dbh->prepare($query); - $sth->execute($tmpl_id); -} - -sub SaveTemplate { - my ( - $tmpl_id, $tmpl_code, $tmpl_desc, $page_width, - $page_height, $label_width, $label_height, $topmargin, - $leftmargin, $cols, $rows, $colgap, - $rowgap, $font, $fontsize, $units - ) = @_; - $debug and warn "Passed \$font:$font"; - my $dbh = C4::Context->dbh; - my $query = - " UPDATE labels_templates SET tmpl_code=?, tmpl_desc=?, page_width=?, - page_height=?, label_width=?, label_height=?, topmargin=?, - leftmargin=?, cols=?, rows=?, colgap=?, rowgap=?, font=?, fontsize=?, - units=? - WHERE tmpl_id = ?"; - - my $sth = $dbh->prepare($query); - $sth->execute( - $tmpl_code, $tmpl_desc, $page_width, $page_height, - $label_width, $label_height, $topmargin, $leftmargin, - $cols, $rows, $colgap, $rowgap, - $font, $fontsize, $units, $tmpl_id - ); - my $dberror = $sth->errstr; - return $dberror; -} - -sub CreateTemplate { - my $tmpl_id; - my ( - $tmpl_code, $tmpl_desc, $page_width, $page_height, - $label_width, $label_height, $topmargin, $leftmargin, - $cols, $rows, $colgap, $rowgap, - $font, $fontsize, $units - ) = @_; - - my $dbh = C4::Context->dbh; - - my $query = "INSERT INTO labels_templates (tmpl_code, tmpl_desc, page_width, - page_height, label_width, label_height, topmargin, - leftmargin, cols, rows, colgap, rowgap, font, fontsize, units) - VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"; - - my $sth = $dbh->prepare($query); - $sth->execute( - $tmpl_code, $tmpl_desc, $page_width, $page_height, - $label_width, $label_height, $topmargin, $leftmargin, - $cols, $rows, $colgap, $rowgap, - $font, $fontsize, $units - ); - my $dberror = $sth->errstr; - return $dberror; -} - -sub GetAllLabelTemplates { - my $dbh = C4::Context->dbh; - # get the actual items to be printed. - my @data; - my $query = " Select * from labels_templates "; - my $sth = $dbh->prepare($query); - $sth->execute(); - my @resultsloop; - while ( my $data = $sth->fetchrow_hashref ) { - push( @resultsloop, $data ); - } - #warn Dumper @resultsloop; - return @resultsloop; -} - -#sub SaveConf { -sub add_layout { - - my ( - $barcodetype, $title, $subtitle, $isbn, $issn, - $itemtype, $bcn, $text_justify, $callnum_split, - $itemcallnumber, $author, $tmpl_id, - $printingtype, $guidebox, $startlabel, $layoutname, $formatstring - ) = @_; - - my $dbh = C4::Context->dbh; - my $query2 = "update labels_conf set active = NULL"; - my $sth2 = $dbh->prepare($query2); - $sth2->execute(); - $query2 = "INSERT INTO labels_conf - ( barcodetype, title, subtitle, isbn,issn, itemtype, barcode, - text_justify, callnum_split, itemcallnumber, author, printingtype, - guidebox, startlabel, layoutname, formatstring, active ) - values ( ?, ?,?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,?,?, 1 )"; - $sth2 = $dbh->prepare($query2); - $sth2->execute( - $barcodetype, $title, $subtitle, $isbn, $issn, - $itemtype, $bcn, $text_justify, $callnum_split, - $itemcallnumber, $author, $printingtype, - $guidebox, $startlabel, $layoutname, $formatstring - ); - SetActiveTemplate($tmpl_id); -} - -sub save_layout { - - my ( - $barcodetype, $title, $subtitle, $isbn, $issn, - $itemtype, $bcn, $text_justify, $callnum_split, - $itemcallnumber, $author, $tmpl_id, - $printingtype, $guidebox, $startlabel, $layoutname, $formatstring, - $layout_id - ) = @_; -### $layoutname -### $layout_id - - my $dbh = C4::Context->dbh; - my $query2 = "update labels_conf set - barcodetype=?, title=?, subtitle=?, isbn=?,issn=?, - itemtype=?, barcode=?, text_justify=?, callnum_split=?, - itemcallnumber=?, author=?, printingtype=?, - guidebox=?, startlabel=?, layoutname=?, formatstring=? where id = ?"; - my $sth2 = $dbh->prepare($query2); - $sth2->execute( - $barcodetype, $title, $subtitle, $isbn, $issn, - $itemtype, $bcn, $text_justify, $callnum_split, - $itemcallnumber, $author, $printingtype, - $guidebox, $startlabel, $layoutname, $formatstring, $layout_id - ); -} - -=head2 GetAllPrinterProfiles; - - @profiles = GetAllPrinterProfiles() - -Returns an array of references-to-hash, whos keys are ..... - -=cut - -sub GetAllPrinterProfiles { - my $dbh = C4::Context->dbh; - my @data; - my $query = "SELECT * FROM printers_profile AS pp INNER JOIN labels_templates AS lt ON pp.tmpl_id = lt.tmpl_id"; - my $sth = $dbh->prepare($query); - $sth->execute(); - my @resultsloop; - while ( my $data = $sth->fetchrow_hashref ) { - push( @resultsloop, $data ); - } - return @resultsloop; -} - -=head2 GetSinglePrinterProfile; - - $profile = GetSinglePrinterProfile() - -Returns a hashref whos keys are... - -=cut - -sub GetSinglePrinterProfile { - my ($prof_id) = @_; - my $query = "SELECT * FROM printers_profile WHERE prof_id = ?"; - my $sth = C4::Context->dbh->prepare($query); - $sth->execute($prof_id); - my $template = $sth->fetchrow_hashref; - return $template; -} - -=head2 SaveProfile; - - SaveProfile('parameters') - -When passed a set of parameters, this function updates the given profile with the new parameters. - -=cut - -sub SaveProfile { - my ( - $prof_id, $offset_horz, $offset_vert, $creep_horz, $creep_vert, $units - ) = @_; - my $dbh = C4::Context->dbh; - my $query = - " UPDATE printers_profile - SET offset_horz=?, offset_vert=?, creep_horz=?, creep_vert=?, unit=? - WHERE prof_id = ? "; - my $sth = $dbh->prepare($query); - $sth->execute( - $offset_horz, $offset_vert, $creep_horz, $creep_vert, $units, $prof_id - ); -} - -=head2 CreateProfile; - - CreateProfile('parameters') - -When passed a set of parameters, this function creates a new profile containing those parameters -and returns any errors. - -=cut - -sub CreateProfile { - my ( - $prof_id, $printername, $paper_bin, $tmpl_id, $offset_horz, - $offset_vert, $creep_horz, $creep_vert, $units - ) = @_; - my $dbh = C4::Context->dbh; - my $query = - " INSERT INTO printers_profile (prof_id, printername, paper_bin, tmpl_id, - offset_horz, offset_vert, creep_horz, creep_vert, unit) - VALUES(?,?,?,?,?,?,?,?,?) "; - my $sth = $dbh->prepare($query); - $sth->execute( - $prof_id, $printername, $paper_bin, $tmpl_id, $offset_horz, - $offset_vert, $creep_horz, $creep_vert, $units - ); - my $error = $sth->errstr; - return $error; -} - -=head2 DeleteProfile; - - DeleteProfile(prof_id) - -When passed a profile id, this function deletes that profile from the database and returns any errors. - -=cut - -sub DeleteProfile { - my ($prof_id) = @_; - my $dbh = C4::Context->dbh; - my $query = " DELETE FROM printers_profile WHERE prof_id = ?"; - my $sth = $dbh->prepare($query); - $sth->execute($prof_id); - my $error = $sth->errstr; - return $error; -} - -=head2 GetAssociatedProfile; - - $assoc_prof = GetAssociatedProfile(tmpl_id) - -When passed a template id, this function returns the parameters from the currently associated printer profile -in a hashref where key=fieldname and value=fieldvalue. - -=cut - -sub GetAssociatedProfile { - my ($tmpl_id) = @_; - my $dbh = C4::Context->dbh; - # First we find out the prof_id for the associated profile... - my $query = "SELECT * FROM labels_profile WHERE tmpl_id = ?"; - my $sth = $dbh->prepare($query); - $sth->execute($tmpl_id); - my $assoc_prof = $sth->fetchrow_hashref or return; - # Then we retrieve that profile and return it to the caller... - $assoc_prof = GetSinglePrinterProfile($assoc_prof->{'prof_id'}); - return $assoc_prof; -} - -=head2 SetAssociatedProfile; - - SetAssociatedProfile($prof_id, $tmpl_id) - -When passed both a profile id and template id, this function establishes an association between the two. No more -than one profile may be associated with any given template at the same time. - -=cut - -sub SetAssociatedProfile { - my ($prof_id, $tmpl_id) = @_; - my $dbh = C4::Context->dbh; - my $query = "INSERT INTO labels_profile (prof_id, tmpl_id) VALUES (?,?) ON DUPLICATE KEY UPDATE prof_id = ?"; - my $sth = $dbh->prepare($query); - $sth->execute($prof_id, $tmpl_id, $prof_id); -} - - -=head2 GetLabelItems; - - $options = GetLabelItems() - -Returns an array of references-to-hash, whos keys are the fields from the biblio, biblioitems, items and labels tables in the Koha database. - -=cut - -sub GetLabelItems { - my ($batch_id) = @_; - my $dbh = C4::Context->dbh; - - my @resultsloop = (); - my $count; - my @data; - my $sth; - - if ($batch_id) { - my $query3 = " - SELECT * - FROM labels - WHERE batch_id = ? - ORDER BY labelid"; - $sth = $dbh->prepare($query3); - $sth->execute($batch_id); - } - else { - my $query3 = " - SELECT * - FROM labels"; - $sth = $dbh->prepare($query3); - $sth->execute(); - } - my $cnt = $sth->rows; - my $i1 = 1; - while ( my $data = $sth->fetchrow_hashref ) { - - # lets get some summary info from each item - my $query1 = -# FIXME This makes for a very bulky data structure; data from tables w/duplicate col names also gets overwritten. -# Something like this, perhaps, but this also causes problems because we need more fields sometimes. -# SELECT i.barcode, i.itemcallnumber, i.itype, bi.isbn, bi.issn, b.title, b.author - "SELECT bi.*, i.*, b.* - FROM items AS i, biblioitems AS bi ,biblio AS b - WHERE itemnumber=? AND i.biblioitemnumber=bi.biblioitemnumber AND bi.biblionumber=b.biblionumber"; - my $sth1 = $dbh->prepare($query1); - $sth1->execute( $data->{'itemnumber'} ); - - my $data1 = $sth1->fetchrow_hashref(); - $data1->{'labelno'} = $i1; - $data1->{'labelid'} = $data->{'labelid'}; - $data1->{'batch_id'} = $batch_id; - $data1->{'summary'} = "$data1->{'barcode'}, $data1->{'title'}, $data1->{'isbn'}"; - - push( @resultsloop, $data1 ); - $sth1->finish; - - $i1++; - } - $sth->finish; - return @resultsloop; - -} - -sub GetItemFields { - my @fields = qw ( - barcode title - isbn issn - author itemtype - itemcallnumber - ); - return @fields; -} - -=head2 GetBarcodeData - -=over 4 - -Parse labels_conf.formatstring value -(one value of the csv, which has already been split) -and return string from koha tables or MARC record. - -=back - -=cut - -sub GetBarcodeData { - my ( $f, $item, $record ) = @_; - my $kohatables = &_descKohaTables(); - my $datastring = ''; - my $match_kohatable = join( - '|', - ( - @{ $kohatables->{biblio} }, - @{ $kohatables->{biblioitems} }, - @{ $kohatables->{items} } - ) - ); - while ($f) { - $f =~ s/^\s?//; - if ( $f =~ /^'(.*)'.*/ ) { - # single quotes indicate a static text string. - $datastring .= $1; - $f = $'; - } - elsif ( $f =~ /^($match_kohatable).*/ ) { - $datastring .= $item->{$f}; - $f = $'; - } - elsif ( $f =~ /^([0-9a-z]{3})(\w)(\W?).*?/ ) { - my ($field,$subf,$ws) = ($1,$2,$3); - my $subf_data; - my ($itemtag, $itemsubfieldcode) = &GetMarcFromKohaField("items.itemnumber",''); - my @marcfield = $record->field($field); - if(@marcfield) { - if($field eq $itemtag) { # item-level data, we need to get the right item. - foreach my $itemfield (@marcfield) { - if ( $itemfield->subfield($itemsubfieldcode) eq $item->{'itemnumber'} ) { - $datastring .= $itemfield->subfield($subf ) . $ws; - last; - } - } - } else { # bib-level data, we'll take the first matching tag/subfield. - $datastring .= $marcfield[0]->subfield($subf) . $ws ; - } - } - $f = $'; - } - else { - warn "failed to parse label formatstring: $f"; - last; # Failed to match - } - } - return $datastring; -} - -=head2 descKohaTables - -Return a hashref of an array of hashes, -with name,type keys. - -=cut - -sub _descKohaTables { - my $dbh = C4::Context->dbh(); - my $kohatables; - for my $table ( 'biblio','biblioitems','items' ) { - my $sth = $dbh->column_info(undef,undef,$table,'%'); - while (my $info = $sth->fetchrow_hashref()){ - push @{$kohatables->{$table}} , $info->{'COLUMN_NAME'} ; - } - } - return $kohatables; -} - -sub GetPatronCardItems { - my ( $batch_id ) = @_; - my @resultsloop; - - my $dbh = C4::Context->dbh; -# my $query = "SELECT * FROM patroncards WHERE batch_id = ? ORDER BY borrowernumber"; - my $query = "SELECT * FROM patroncards WHERE batch_id = ? ORDER BY cardid"; - my $sth = $dbh->prepare($query); - $sth->execute($batch_id); - my $cardno = 1; - while ( my $data = $sth->fetchrow_hashref ) { - my $patron_data = GetMember( $data->{'borrowernumber'} ); - $patron_data->{'branchname'} = GetBranchName( $patron_data->{'branchcode'} ); - $patron_data->{'cardno'} = $cardno; - $patron_data->{'cardid'} = $data->{'cardid'}; - $patron_data->{'batch_id'} = $batch_id; - push( @resultsloop, $patron_data ); - $cardno++; - } - return @resultsloop; -} - -sub deduplicate_batch { - my ( $batch_id, $batch_type ) = @_; - my $query = " - SELECT DISTINCT - batch_id," . (($batch_type eq 'labels') ? 'itemnumber' : 'borrowernumber') . ", - count(". (($batch_type eq 'labels') ? 'labelid' : 'cardid') . ") as count - FROM $batch_type - WHERE batch_id = ? - GROUP BY " . (($batch_type eq 'labels') ? 'itemnumber' : 'borrowernumber') . ",batch_id - HAVING count > 1 - ORDER BY batch_id, - count DESC "; - my $sth = C4::Context->dbh->prepare($query); - $sth->execute($batch_id); - warn $sth->errstr if $sth->errstr; - $sth->rows or return undef, $sth->errstr; - - my $del_query = " - DELETE - FROM $batch_type - WHERE batch_id = ? - AND " . (($batch_type eq 'labels') ? 'itemnumber' : 'borrowernumber') . " = ? - ORDER BY timestamp ASC - "; - my $killed = 0; - while (my $data = $sth->fetchrow_hashref()) { - my $itemnumber = $data->{(($batch_type eq 'labels') ? 'itemnumber' : 'borrowernumber')} or next; - my $limit = $data->{count} - 1 or next; - my $sth2 = C4::Context->dbh->prepare("$del_query LIMIT $limit"); - # die sprintf "$del_query LIMIT %s\n (%s, %s)", $limit, $batch_id, $itemnumber; - # $sth2->execute($batch_id, C4::Context->dbh->quote($data->{itemnumber}), $data->{count} - 1) - $sth2->execute($batch_id, $itemnumber) and - $killed += ($data->{count} - 1); - warn $sth2->errstr if $sth2->errstr; - } - return $killed, undef; -} - -sub split_lccn { - my ($lccn) = @_; - $_ = $lccn; - # lccn examples: 'HE8700.7 .P6T44 1983', 'BS2545.E8 H39 1996'; - my (@parts) = m/ - ^([a-zA-Z]+) # HE # BS - (\d+(?:\.\d)*) # 8700.7 # 2545 - \s* - (\.*\D+\d*) # .P6 # .E8 - \s* - (.*) # T44 1983 # H39 1996 # everything else (except any bracketing spaces) - \s* - /x; - unless (scalar @parts) { - $debug and print STDERR "split_lccn regexp failed to match string: $_\n"; - push @parts, $_; # if no match, just push the whole string. - } - push @parts, split /\s+/, pop @parts; # split the last piece into an arbitrary number of pieces at spaces - $debug and print STDERR "split_lccn array: ", join(" | ", @parts), "\n"; - return @parts; -} - -our $possible_decimal = qr/\d{3,}(?:\.\d+)?/; # at least three digits for a DDCN - -sub split_ddcn { - my ($ddcn) = @_; - $_ = $ddcn; - s/\///g; # in theory we should be able to simply remove all segmentation markers and arrive at the correct call number... - # ddcn examples: 'R220.3 H2793Z H32 c.2', 'BIO JP2 R5c.1' - - my (@parts) = m/ - ^([a-zA-Z-]+(?:$possible_decimal)?) # R220.3 # BIO # first example will require extra splitting - \s+ - (.+) # H2793Z H32 c.2 # R5c.1 # everything else (except bracketing spaces) - \s* - /x; - unless (scalar @parts) { - $debug and print STDERR "split_ddcn regexp failed to match string: $_\n"; - push @parts, $_; # if no match, just push the whole string. - } - - if ($parts[ 0] =~ /^([a-zA-Z]+)($possible_decimal)$/) { - shift @parts; # pull off the mathching first element, like example 1 - unshift @parts, $1, $2; # replace it with the two pieces - } - - push @parts, split /\s+/, pop @parts; # split the last piece into an arbitrary number of pieces at spaces - - if ($parts[-1] !~ /^.*\d-\d.*$/ && $parts[-1] =~ /^(.*\d+)(\D.*)$/) { - pop @parts; # pull off the mathching last element, like example 2 - push @parts, $1, $2; # replace it with the two pieces - } - - $debug and print STDERR "split_ddcn array: ", join(" | ", @parts), "\n"; - return @parts; -} - -sub split_fcn { - my ($fcn) = @_; - my @fcn_split = (); - # Split fiction call numbers based on spaces - SPLIT_FCN: - while ($fcn) { - if ($fcn =~ m/([A-Za-z0-9]+\.?[0-9]?)(\W?).*?/x) { - push (@fcn_split, $1); - $fcn = $'; - } - else { - last SPLIT_FCN; # No match, break out of the loop - } - } - return @fcn_split; -} - -my %itemtypemap; -# Class variable to avoid querying itemtypes for every DrawSpineText call!! -sub get_itemtype_descriptions () { - unless (scalar keys %itemtypemap) { - my $sth = C4::Context->dbh->prepare("SELECT itemtype,description FROM itemtypes"); - $sth->execute(); - while (my $data = $sth->fetchrow_hashref) { - $itemtypemap{$data->{itemtype}} = $data->{description}; - } - } - return \%itemtypemap; -} - -sub DrawSpineText { - my ( $x_pos, $y_pos, $label_height, $label_width, $fontname, $fontsize, $left_text_margin, - $text_wrap_cols, $item, $conf_data, $printingtype ) = @_; - - # Replace item's itemtype with the more user-friendly description... - my $descriptions = get_itemtype_descriptions(); - foreach (qw(itemtype itype)) { - my $description = $descriptions->{$$item->{$_}} or next; - $$item->{$_} = $description; - } - my $str = ''; - - my $top_text_margin = ( $fontsize + 3 ); #FIXME: This should be a template parameter and passed in... - my $line_spacer = ( $fontsize * 1 ); # number of pixels between text rows (This is actually leading: baseline to baseline minus font size. Recommended starting point is 20% of font size.). - - my $layout_id = $$conf_data->{'id'}; - - my $vPos = ( $y_pos + ( $label_height - $top_text_margin ) ); - - my @str_fields = get_text_fields($layout_id, 'codes' ); - my $record = GetMarcBiblio($$item->{biblionumber}); - # FIXME - returns all items, so you can't get data from an embedded holdings field. - # TODO - add a GetMarcBiblio1item(bibnum,itemnum) or a GetMarcItem(itemnum). - - my $old_fontname = $fontname; # We need to keep track of the original font passed in... - - # Grab the cn_source and if that is NULL, the DefaultClassificationSource syspref - my $cn_source = ($$item->{'cn_source'} ? $$item->{'cn_source'} : C4::Context->preference('DefaultClassificationSource')); - for my $field (@str_fields) { - $field->{'code'} or warn "get_text_fields($layout_id, 'codes') element missing 'code' field"; - if ($field->{'code'} eq 'itemtype') { - $field->{'data'} = C4::Context->preference('item-level_itypes') ? $$item->{'itype'} : $$item->{'itemtype'}; - } - elsif ($$conf_data->{'formatstring'}) { - # if labels_conf.formatstring has a value, then it overrides the hardcoded option. - $field->{'data'} = GetBarcodeData($field->{'code'},$$item,$record) ; - } - else { - $field->{'data'} = $$item->{$field->{'code'}}; - } - # This allows us to print the title in italic (oblique) type... (Times Roman has a different nomenclature.) - # It seems there should be a better way to handle fonts in the label/patron card tool altogether -fbcit - ($field->{code} eq 'title') ? (($old_fontname =~ /T/) ? ($fontname = 'TI') : ($fontname = ($old_fontname . 'O'))) : ($fontname = $old_fontname); - my $font = prFont($fontname); - # if the display option for this field is selected in the DB, - # and the item record has some values for this field, display it. - # Or if there is a csv list of fields to display, display them. - if ( ($$conf_data->{'formatstring'}) || ( $$conf_data->{$field->{code}} && $$item->{$field->{code}} ) ) { - # get the string - my $str = $field->{data} ; - # strip out naughty existing nl/cr's - $str =~ s/\n//g; - $str =~ s/\r//g; - my @strings; - my @callnumber_list = ('itemcallnumber', '050a', '050b', '082a', '952o'); # Fields which hold call number data ( 060? 090? 092? 099? ) - if ((grep {$field->{code} =~ m/$_/} @callnumber_list) and ($printingtype eq 'BIB') and ($$conf_data->{'callnum_split'})) { # If the field contains the call number, we do some sp - if ($cn_source eq 'lcc') { - @strings = split_lccn($str); - @strings = split_fcn($str) if !@strings; # If it was not a true lccn, try it as a fiction call number - push (@strings, $str) if !@strings; # If it was not that, send it on unsplit - } elsif ($cn_source eq 'ddc') { - @strings = split_ddcn($str); - @strings = split_fcn($str) if !@strings; - push (@strings, $str) if !@strings; - } else { - # FIXME Need error trapping here; something to be informative to the user perhaps -crn - push @strings, $str; - } - } else { - $str =~ s/\/$//g; # Here we will strip out all trailing '/' in fields other than the call number... - $str =~ s/\(/\\\(/g; # Escape '(' and ')' for the postscript stream... - $str =~ s/\)/\\\)/g; - # Wrap text lines exceeding $text_wrap_cols length... - $Text::Wrap::columns = $text_wrap_cols; - my @line = split(/\n/ ,wrap('', '', $str)); - # If this is a title field, limit to two lines; all others limit to one... - my $limit = ($field->{code} eq 'title') ? 2 : 1; - while (scalar(@line) > $limit) { - pop @line; - } - push(@strings, @line); - } - # loop for each string line - foreach my $str (@strings) { - my $hPos = $x_pos; - next if $str eq ''; - my $stringwidth = prStrWidth($str, $fontname, $fontsize); - if ( $$conf_data->{'text_justify'} eq 'R' ) { - $hPos += $label_width - ($left_text_margin + $stringwidth); - } elsif($$conf_data->{'text_justify'} eq 'C') { - # some code to try and center each line on the label based on font size and string point width... - my $whitespace = ( $label_width - ( $stringwidth + (2 * $left_text_margin) ) ); - $hPos += ($whitespace / 2) + $left_text_margin; - #warn "\$label_width=$label_width \$stringwidth=$stringwidth \$whitespace=$whitespace \$left_text_margin=$left_text_margin for $str\n"; - } else { - $hPos += $left_text_margin; - } -# utf8::encode($str); -# Say $str has a diacritical like: The séance -# WITOUT encode, PrintText crashes with: Wide character in syswrite at /usr/local/share/perl/5.8.8/PDF/Reuse.pm line 968 -# WITH encode, PrintText prints: The seÌ•ancee -# Neither is appropriate. - PrintText( $hPos, $vPos, $font, $fontsize, $str ); - $vPos -= $line_spacer; - } - } - } #foreach field -} - -sub PrintText { - my ( $hPos, $vPos, $font, $fontsize, $text ) = @_; - my $str = "BT /$font $fontsize Tf $hPos $vPos Td ($text) Tj ET"; - prAdd($str); -} - -sub DrawPatronCardText { - my ( $x_pos, $y_pos, $label_height, $label_width, $fontname, $fontsize, $left_text_margin, - $text_wrap_cols, $text, $printingtype ) - = @_; - - my $top_text_margin = 25; #FIXME: This should be a template parameter and passed in... - - my $vPos = ( $y_pos + ( $label_height - $top_text_margin ) ); - my $font = prFont($fontname); - - my $hPos = 0; - - foreach my $line (keys %$text) { - $debug and warn "Current text is \"$line\" and font size for \"$line\" is $text->{$line} points"; - # some code to try and center each line on the label based on font size and string point width... - my $stringwidth = prStrWidth($line, $fontname, $text->{$line}); - my $whitespace = ( $label_width - ( $stringwidth + (2 * $left_text_margin) ) ); - $hPos = ( ( $whitespace / 2 ) + $x_pos + $left_text_margin ); - - PrintText( $hPos, $vPos, $font, $text->{$line}, $line ); - my $line_spacer = ( $text->{$line} * 1 ); # number of pixels between text rows (This is actually leading: baseline to baseline minus font size. Recommended starting point is 20% (0.20) of font size.). - $vPos = $vPos - ($line_spacer + $text->{$line}); # Linefeed equiv: leading + font size - } -} - -# Not used anywhere. - -#sub SetFontSize { -# -# my ($fontsize) = @_; -#### fontsize -# my $str = "BT/F13 30 Tf288 720 Td( AAAAAAAAAA ) TjET"; -# prAdd($str); -#} - -sub DrawBarcode { - # x and y are from the top-left :) - my ( $x_pos, $y_pos, $height, $width, $barcode, $barcodetype ) = @_; - my $num_of_bars = length($barcode); - my $bar_width = $width * .8; # %80 of length of label width - my $tot_bar_length = 0; - my $bar_length = 0; - my $guard_length = 10; - my $xsize_ratio = 0; - - if ( $barcodetype eq 'CODE39' ) { - $bar_length = '17.5'; - $tot_bar_length = - ( $bar_length * $num_of_bars ) + ( $guard_length * 2 ); - $xsize_ratio = ( $bar_width / $tot_bar_length ); - eval { - PDF::Reuse::Barcode::Code39( - x => ( $x_pos + ( $width / 10 ) ), - y => ( $y_pos + ( $height / 10 ) ), - value => "*$barcode*", - ySize => ( .02 * $height ), - xSize => $xsize_ratio, - hide_asterisk => 1, - mode => 'graphic', # the only other option here is Type3... - ); - }; - } - elsif ( $barcodetype eq 'CODE39MOD' ) { - # get modulo43 checksum - my $c39 = CheckDigits('code_39'); - $barcode = $c39->complete($barcode); - - $bar_length = '19'; - $tot_bar_length = - ( $bar_length * $num_of_bars ) + ( $guard_length * 2 ); - $xsize_ratio = ( $bar_width / $tot_bar_length ); - eval { - PDF::Reuse::Barcode::Code39( - x => ( $x_pos + ( $width / 10 ) ), - y => ( $y_pos + ( $height / 10 ) ), - value => "*$barcode*", - ySize => ( .02 * $height ), - xSize => $xsize_ratio, - hide_asterisk => 1, - mode => 'graphic', # the only other option here is Type3... - ); - }; - } - elsif ( $barcodetype eq 'CODE39MOD10' ) { - # get modulo43 checksum - my $c39_10 = CheckDigits('visa'); - $barcode = $c39_10->complete($barcode); - - $bar_length = '19'; - $tot_bar_length = - ( $bar_length * $num_of_bars ) + ( $guard_length * 2 ); - $xsize_ratio = ( $bar_width / $tot_bar_length ); - eval { - PDF::Reuse::Barcode::Code39( - x => ( $x_pos + ( $width / 10 ) ), - y => ( $y_pos + ( $height / 10 ) ), - value => "*$barcode*", - ySize => ( .02 * $height ), - xSize => $xsize_ratio, - hide_asterisk => 1, - text => 0, - mode => 'graphic', # the only other option here is Type3... - ); - }; - } - elsif ( $barcodetype eq 'COOP2OF5' ) { - $bar_length = '9.43333333333333'; - $tot_bar_length = - ( $bar_length * $num_of_bars ) + ( $guard_length * 2 ); - $xsize_ratio = ( $bar_width / $tot_bar_length ) * .9; - eval { - PDF::Reuse::Barcode::COOP2of5( - x => ( $x_pos + ( $width / 10 ) ), - y => ( $y_pos + ( $height / 10 ) ), - value => $barcode, - ySize => ( .02 * $height ), - xSize => $xsize_ratio, - ); - }; - } - elsif ( $barcodetype eq 'INDUSTRIAL2OF5' ) { - $bar_length = '13.1333333333333'; - $tot_bar_length = - ( $bar_length * $num_of_bars ) + ( $guard_length * 2 ); - $xsize_ratio = ( $bar_width / $tot_bar_length ) * .9; - eval { - PDF::Reuse::Barcode::Industrial2of5( - x => ( $x_pos + ( $width / 10 ) ), - y => ( $y_pos + ( $height / 10 ) ), - value => $barcode, - ySize => ( .02 * $height ), - xSize => $xsize_ratio, - ); - }; - } # else {die "Unknown barcodetype '$barcodetype'";} - - if ($@) { - warn "DrawBarcode (type: $barcodetype) FAILED for value '$barcode' :$@"; - } - - my $moo2 = $tot_bar_length * $xsize_ratio; - - warn "x_pos,y_pos,barcode,barcodetype = $x_pos, $y_pos, $barcode, $barcodetype\n" - . "BAR_WDTH = $bar_width, TOT.BAR.LGHT=$tot_bar_length R*TOT.BAR =$moo2" if $debug; -} - -=head2 build_circ_barcode; - - build_circ_barcode( $x_pos, $y_pos, $barcode, $barcodetype, \$item); - -$item is the result of a previous call to GetLabelItems(); - -=cut - -sub build_circ_barcode { - my ( $x_pos_circ, $y_pos, $value, $barcodetype, $item ) = @_; - - #warn Dumper \$item; - #warn "Barcode (type: $barcodetype) value = $value\n"; - #$DB::single = 1; - - if ( $barcodetype eq 'EAN13' ) { - #testing EAN13 barcodes hack - $value = $value . '000000000'; - $value =~ s/-//; - $value = substr( $value, 0, 12 ); - #warn "revised value: $value"; - eval { - PDF::Reuse::Barcode::EAN13( - x => ( $x_pos_circ + 27 ), - y => ( $y_pos + 15 ), - value => $value, - # prolong => 2.96, - # xSize => 1.5, - # ySize => 1.2, -# added for xpdf compat. doesnt use type3 fonts., but increases filesize from 20k to 200k -# i think its embedding extra fonts in the pdf file. -# mode => 'graphic', - ); - }; - } - elsif ( $barcodetype eq 'Code39' ) { - eval { - PDF::Reuse::Barcode::Code39( - x => ( $x_pos_circ + 9 ), - y => ( $y_pos + 15 ), - value => $value, - # prolong => 2.96, - xSize => .85, - ySize => 1.3, - mode => 'graphic', # the only other option here is Type3... - ); - }; - } - elsif ( $barcodetype eq 'Matrix2of5' ) { - # testing MATRIX25 barcodes hack - # $value = $value.'000000000'; - $value =~ s/-//; - # $value = substr( $value, 0, 12 ); - #warn "revised value: $value"; - eval { - PDF::Reuse::Barcode::Matrix2of5( - x => ( $x_pos_circ + 27 ), - y => ( $y_pos + 15 ), - value => $value, - # prolong => 2.96, - # xSize => 1.5, - # ySize => 1.2, - ); - }; - } - elsif ( $barcodetype eq 'EAN8' ) { - #testing ean8 barcodes hack - $value = $value . '000000000'; - $value =~ s/-//; - $value = substr( $value, 0, 8 ); - #warn "revised value: $value"; - eval { - PDF::Reuse::Barcode::EAN8( - x => ( $x_pos_circ + 42 ), - y => ( $y_pos + 15 ), - value => $value, - prolong => 2.96, - xSize => 1.5, - # ySize => 1.2, - ); - }; - } - elsif ( $barcodetype eq 'UPC-E' ) { - eval { - PDF::Reuse::Barcode::UPCE( - x => ( $x_pos_circ + 27 ), - y => ( $y_pos + 15 ), - value => $value, - prolong => 2.96, - xSize => 1.5, - # ySize => 1.2, - ); - }; - } - elsif ( $barcodetype eq 'NW7' ) { - eval { - PDF::Reuse::Barcode::NW7( - x => ( $x_pos_circ + 27 ), - y => ( $y_pos + 15 ), - value => $value, - prolong => 2.96, - xSize => 1.5, - # ySize => 1.2, - ); - }; - } - elsif ( $barcodetype eq 'ITF' ) { - eval { - PDF::Reuse::Barcode::ITF( - x => ( $x_pos_circ + 27 ), - y => ( $y_pos + 15 ), - value => $value, - prolong => 2.96, - xSize => 1.5, - # ySize => 1.2, - ); - }; - } - elsif ( $barcodetype eq 'Industrial2of5' ) { - eval { - PDF::Reuse::Barcode::Industrial2of5( - x => ( $x_pos_circ + 27 ), - y => ( $y_pos + 15 ), - value => $value, - prolong => 2.96, - xSize => 1.5, - # ySize => 1.2, - ); - }; - } - elsif ( $barcodetype eq 'IATA2of5' ) { - eval { - PDF::Reuse::Barcode::IATA2of5( - x => ( $x_pos_circ + 27 ), - y => ( $y_pos + 15 ), - value => $value, - prolong => 2.96, - xSize => 1.5, - # ySize => 1.2, - ); - }; - } - elsif ( $barcodetype eq 'COOP2of5' ) { - eval { - PDF::Reuse::Barcode::COOP2of5( - x => ( $x_pos_circ + 27 ), - y => ( $y_pos + 15 ), - value => $value, - prolong => 2.96, - xSize => 1.5, - # ySize => 1.2, - ); - }; - } - elsif ( $barcodetype eq 'UPC-A' ) { - eval { - PDF::Reuse::Barcode::UPCA( - x => ( $x_pos_circ + 27 ), - y => ( $y_pos + 15 ), - value => $value, - prolong => 2.96, - xSize => 1.5, - # ySize => 1.2, - ); - }; - } - if ($@) { - $item->{'barcodeerror'} = 1; - #warn "BARCODE (type: $barcodetype) FAILED:$@"; - } -} - -=head2 draw_boundaries - - sub draw_boundaries ($x_pos_spine, $x_pos_circ1, $x_pos_circ2, - $y_pos, $spine_width, $label_height, $circ_width) - -This sub draws boundary lines where the label outlines are, to aid in printer testing, and debugging. - -=cut - -sub draw_boundaries { - my ( - $x_pos_spine, $x_pos_circ1, $x_pos_circ2, $y_pos, - $spine_width, $label_height, $circ_width - ) = @_; - - my $y_pos_initial = ( ( 792 - 36 ) - 90 ); - $y_pos = $y_pos_initial; # FIXME - why are we ignoring the y_pos parameter by redefining it? - my $i = 1; - - for ( $i = 1 ; $i <= 8 ; $i++ ) { - &drawbox( $x_pos_spine, $y_pos, ($spine_width), ($label_height) ); - #warn "OLD BOXES x=$x_pos_spine, y=$y_pos, w=$spine_width, h=$label_height"; - &drawbox( $x_pos_circ1, $y_pos, ($circ_width), ($label_height) ); - &drawbox( $x_pos_circ2, $y_pos, ($circ_width), ($label_height) ); - $y_pos = ( $y_pos - $label_height ); - } -} - -=head2 drawbox - - sub drawbox { $lower_left_x, $lower_left_y, - $upper_right_x, $upper_right_y ) - -this is a low level sub, that draws a pdf box, it is called by draw_boxes - -FYI: the $upper_right_x and $upper_right_y values are RELATIVE to $lower_left_x and $lower_left_y - -and $lower_left_x, $lower_left_y are ABSOLUTE, this caught me out! - -=cut - -sub drawbox { - my ( $llx, $lly, $urx, $ury ) = @_; - # warn "llx,y= $llx,$lly , urx,y=$urx,$ury \n"; - - my $str = "q\n"; # save the graphic state - $str .= "0.5 w\n"; # border color red - $str .= "1.0 0.0 0.0 RG\n"; # border color red - # $str .= "0.5 0.75 1.0 rg\n"; # fill color blue - $str .= "1.0 1.0 1.0 rg\n"; # fill color white - - $str .= "$llx $lly $urx $ury re\n"; # a rectangle - $str .= "B\n"; # fill (and a little more) - $str .= "Q\n"; # save the graphic state - - prAdd($str); -} - -1; -__END__ - -=head1 AUTHOR - -Mason James - -=cut - diff --git a/C4/Labels/Batch.pm b/C4/Labels/Batch.pm new file mode 100644 index 0000000000..8ac4f690ff --- /dev/null +++ b/C4/Labels/Batch.pm @@ -0,0 +1,307 @@ +package C4::Labels::Batch; + +use strict; +use warnings; + +use C4::Context; +use C4::Debug; + +BEGIN { + use version; our $VERSION = qv('1.0.0_1'); +} + +sub _check_params { + my $given_params = {}; + my $exit_code = 0; + my @valid_template_params = ( + 'label_id', + 'batch_id', + 'item_number', + 'branch_code', + ); + if (scalar(@_) >1) { + $given_params = {@_}; + foreach my $key (keys %{$given_params}) { + if (!(grep m/$key/, @valid_template_params)) { + warn sprintf('Unrecognized parameter type of "%s".', $key); + $exit_code = 1; + } + } + } + else { + if (!(grep m/$_/, @valid_template_params)) { + warn sprintf('Unrecognized parameter type of %s', $_); + $exit_code = 1; + } + } + return $exit_code; +} + +sub new { + my ($invocant) = shift; + my $type = ref($invocant) || $invocant; + my $self = { + batch_id => 0, + items => [], + branch_code => 'NB', + batch_stat => 0, # False if any data has changed and the db has not been updated + @_, + }; + my $sth = C4::Context->dbh->prepare("SELECT MAX(batch_id) FROM labels_batches;"); + $sth->execute(); + my $batch_id = $sth->fetchrow_array; + $self->{'batch_id'} = ++$batch_id unless $self->{'batch_id'} != 0; # this allows batch_id to be passed in for individual label printing + bless ($self, $type); + return $self; +} + +sub add_item { + my $self = shift; + my $item_number = shift; + my $query = "INSERT INTO labels_batches (batch_id, item_number, branch_code) VALUES (?,?,?);"; + my $sth = C4::Context->dbh->prepare($query); +# $sth->{'TraceLevel'} = 3; + $sth->execute($self->{'batch_id'}, $item_number, $self->{'branch_code'}); + if ($sth->err) { + warn sprintf('Database returned the following error on attempted INSERT: %s', $sth->errstr); + return -1; + } + $query = "SELECT max(label_id) FROM labels_batches WHERE batch_id=? AND item_number=? AND branch_code=?;"; + my $sth1 = C4::Context->dbh->prepare($query); + $sth1->execute($self->{'batch_id'}, $item_number, $self->{'branch_code'}); + my $label_id = $sth1->fetchrow_array; + push (@{$self->{'items'}}, {item_number => $item_number, label_id => $label_id}); + $self->{'batch_stat'} = 1; + return 0; +} + +sub get_attr { + my $self = shift; + return $self->{$_[0]}; +} + +sub remove_item { + my $self = shift; + my $label_id = shift; + my $query = "DELETE FROM labels_batches WHERE label_id=? AND batch_id=?;"; + my $sth = C4::Context->dbh->prepare($query); +# $sth->{'TraceLevel'} = 3; + $sth->execute($label_id, $self->{'batch_id'}); + if ($sth->err) { + warn sprintf('Database returned the following error on attempted DELETE: %s', $sth->errstr); + return -1; + } + @{$self->{'items'}} = grep{$_->{'label_id'} != $label_id} @{$self->{'items'}}; + $self->{'batch_stat'} = 1; + return 0; +} + +# FIXME: This method is effectively useless the way the current add_item method is written. Ideally, the items should be added to the object +# and then the save method called. This does not work well in practice due to the inability to pass objects accross cgi script calls. +# I'm leaving it here because it should be here and for consistency's sake. -cnighswonger +# +#=head2 $batch->save() +# +# Invoking the I method attempts to insert the batch into the database. The method returns +# the new record batch_id upon success and -1 upon failure (This avoids conflicting with a record +# batch_id of 1). Errors are logged to the Apache log. +# +# example: +# my $exitstat = $batch->save(); # to save the record behind the $batch object +# +#=cut +# +#sub save { +# my $self = shift; +# foreach my $item_number (@{$self->{'items'}}) { +# my $query = "INSERT INTO labels_batches (batch_id, item_number, branch_code) VALUES (?,?,?);"; +# my $sth1 = C4::Context->dbh->prepare($query); +# $sth1->execute($self->{'batch_id'}, $item_number->{'item_number'}, $self->{'branch_code'}); +# if ($sth1->err) { +# warn sprintf('Database returned the following error on attempted INSERT: %s', $sth1->errstr); +# return -1; +# } +# $self->{'batch_stat'} = 1; +# return $self->{'batch_id'}; +# } +#} + +sub retrieve { + my $invocant = shift; + my %opts = @_; + my $type = ref($invocant) || $invocant; + my $record_flag = 0; + my $query = "SELECT * FROM labels_batches WHERE batch_id = ? ORDER BY label_id"; + my $sth = C4::Context->dbh->prepare($query); +# $sth->{'TraceLevel'} = 3; + $sth->execute($opts{'batch_id'}); + my $self = { + batch_id => $opts{'batch_id'}, + items => [], + }; + while (my $record = $sth->fetchrow_hashref) { + $self->{'branch_code'} = $record->{'branch_code'}; + push (@{$self->{'items'}}, {item_number => $record->{'item_number'}, label_id => $record->{'label_id'}}); + $record_flag = 1; # true if one or more rows were retrieved + } + return -2 if $record_flag == 0; # a hackish sort of way of indicating no such record exists + if ($sth->err) { + warn sprintf('Database returned the following error on attempted SELECT: %s', $sth->errstr); + return -1; + } + $self->{'batch_stat'} = 1; + bless ($self, $type); + return $self; +} + +sub delete { + my $self = {}; + my %opts = (); + my $call_type = ''; + my @query_params = (); + if (ref($_[0])) { + $self = shift; # check to see if this is a method call + $call_type = 'C4::Labels::Batch->delete'; + @query_params = ($self->{'batch_id'}, $self->{'branch_code'}); + } + else { + %opts = @_; + $call_type = 'C4::Labels::Batch::delete'; + @query_params = ($opts{'batch_id'}, $opts{'branch_code'}); + } + if ($query_params[0] eq '') { # If there is no template id then we cannot delete it + warn sprtinf('%s : Cannot delete batch as the batch id is invalid or non-existent.', $call_type); + return -1; + } + my $query = "DELETE FROM labels_batches WHERE batch_id = ? AND branch_code =?"; + my $sth = C4::Context->dbh->prepare($query); +# $sth->{'TraceLevel'} = 3; + $sth->execute(@query_params); + if ($sth->err) { + warn sprintf('%s : Database returned the following error on attempted INSERT: %s', $call_type, $sth->errstr); + return -1; + } + return 0; +} + +sub remove_duplicates { + my $self = shift; + my %seen=(); + my $query = "DELETE FROM labels_batches WHERE label_id = ?;"; # ORDER BY timestamp ASC LIMIT ?;"; + my $sth = C4::Context->dbh->prepare($query); + my @duplicate_items = grep{$seen{$_->{'item_number'}}++} @{$self->{'items'}}; + foreach my $item (@duplicate_items) { + $sth->execute($item->{'label_id'}); + if ($sth->err) { + warn sprintf('Database returned the following error on attempted DELETE for label_id %s: %s', $item->{'label_id'}, $sth->errstr); + return -1; + } + $sth->finish(); # Per DBI.pm docs: "If execute() is called on a statement handle that's still active ($sth->{Active} is true) then it should effectively call finish() to tidy up the previous execution results before starting this new execution." + @{$self->{'items'}} = grep{$_->{'label_id'} != $item->{'label_id'}} @{$self->{'items'}}; # the correct label/item must be removed from the current batch object as well; this should be done *after* each sql DELETE in case the DELETE fails + } + return scalar(@duplicate_items); +} + +1; +__END__ + +=head1 NAME + +C4::Labels::Batch - A class for creating and manipulating batch objects in Koha + +=head1 ABSTRACT + +This module provides methods for creating, and otherwise manipulating batch objects used by Koha to create and export labels. + +=head1 METHODS + +=head2 new() + + Invoking the I method constructs a new batch object with no items. It is possible to pre-populate the batch with items and a branch code by passing them + as in the second example below. + + B The items list must be an arrayref pointing to an array of hashes containing a key/data pair after this fashion: {item_number => item_number}. The order of + the array elements determines the order of the items in the batch. + + example: + Cnew(); # Creates and returns a new batch object> + + Cnew(items => $arrayref, branch_code => branch_code) # Creates and returns a new batch object containing the items passed in + with the branch code passed in.> + + B This batch is I written to the database until C<$batch->save()> is invoked. You have been warned! + +=head2 $batch->add_item(item_number => $item_number, branch_code => $branch_code) + + Invoking the I method will add the supplied item to the batch object. + + example: + $batch->add_item(item_number => $item_number, branch_code => $branch_code); + +=head2 $batch->get_attr($attribute) + + Invoking the I method will return the requested attribute. + + example: + my @items = $batch->get_attr('items'); + +=head2 $batch->remove_item($item_number) + + Invoking the I method will remove the supplied item number from the batch object. + + example: + $batch->remove_item($item_number); + +=head2 C4::Labels::Batch->retrieve(batch_id => $batch_id) + + Invoking the I method constructs a new batch object containing the current values for batch_id. The method returns a new object upon success and 1 upon failure. + Errors are logged to the Apache log. + + examples: + + my $batch = C4::Labels::Batch->retrieve(batch_id => 1); # Retrieves batch 1 and returns an object containing the record + +=head2 delete() + + Invoking the delete method attempts to delete the template from the database. The method returns -1 upon failure. Errors are logged to the Apache log. + NOTE: This method may also be called as a function and passed a key/value pair simply deleteing that batch from the database. See the example below. + + examples: + my $exitstat = $batch->delete(); # to delete the record behind the $batch object + my $exitstat = C4::Labels::Batch->delete(batch_id => 1); # to delete batch 1 + +=head2 remove_duplicates() + + Invoking the remove_duplicates method attempts to remove duplicate items in the batch from the database. The method returns the count of duplicate records removed upon + success and -1 upon failure. Errors are logged to the Apache log. + NOTE: This method may also be called as a function and passed a key/value pair removing duplicates in the batch passed in. See the example below. + + examples: + my $remove_count = $batch->remove_duplicates(); # to remove duplicates the record behind the $batch object + my $remove_count = C4::Labels::Batch->remove_duplicates(batch_id => 1); # to remove duplicates in batch 1 + +=head1 AUTHOR + +Chris Nighswonger + +=head1 COPYRIGHT + +Copyright 2009 Foundations Bible College. + +=head1 LICENSE + +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. + +You should have received a copy of the GNU General Public License along with Koha; if not, write to the Free Software Foundation, Inc., 59 Temple Place, +Suite 330, Boston, MA 02111-1307 USA + +=head1 DISCLAIMER OF WARRANTY + +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. + +=cut + diff --git a/C4/Labels/Label.pm b/C4/Labels/Label.pm new file mode 100644 index 0000000000..9cf50262ca --- /dev/null +++ b/C4/Labels/Label.pm @@ -0,0 +1,798 @@ +package C4::Labels::Label; + +use strict; +use warnings; + +use Text::Wrap; +use Algorithm::CheckDigits; +use Text::CSV_XS; + +use C4::Context; +use C4::Debug; +use C4::Biblio; + +BEGIN { + use version; our $VERSION = qv('1.0.0_1'); +} + +my $possible_decimal = qr/\d{3,}(?:\.\d+)?/; # at least three digits for a DDCN + +sub _check_params { + my $given_params = {}; + my $exit_code = 0; + my @valid_label_params = ( + 'batch_id', + 'item_number', + 'llx', + 'lly', + 'height', + 'width', + 'top_text_margin', + 'left_text_margin', + 'barcode_type', + 'printing_type', + 'guidebox', + 'font', + 'font_size', + 'callnum_split', + 'justify', + 'format_string', + 'text_wrap_cols', + 'barcode', + ); + if (scalar(@_) >1) { + $given_params = {@_}; + foreach my $key (keys %{$given_params}) { + if (!(grep m/$key/, @valid_label_params)) { + warn sprintf('Unrecognized parameter type of "%s".', $key); + $exit_code = 1; + } + } + } + else { + if (!(grep m/$_/, @valid_label_params)) { + warn sprintf('Unrecognized parameter type of "%s".', $_); + $exit_code = 1; + } + } + return $exit_code; +} + +sub _guide_box { + my ( $llx, $lly, $width, $height ) = @_; + my $obj_stream = "q\n"; # save the graphic state + $obj_stream .= "0.5 w\n"; # border line width + $obj_stream .= "1.0 0.0 0.0 RG\n"; # border color red + $obj_stream .= "1.0 1.0 1.0 rg\n"; # fill color white + $obj_stream .= "$llx $lly $width $height re\n"; # a rectangle + $obj_stream .= "B\n"; # fill (and a little more) + $obj_stream .= "Q\n"; # restore the graphic state + return $obj_stream; +} + +sub _get_label_item { + my $item_number = shift; + my $barcode_only = shift || 0; + my $dbh = C4::Context->dbh; +# FIXME This makes for a very bulky data structure; data from tables w/duplicate col names also gets overwritten. +# Something like this, perhaps, but this also causes problems because we need more fields sometimes. +# SELECT i.barcode, i.itemcallnumber, i.itype, bi.isbn, bi.issn, b.title, b.author + my $sth = $dbh->prepare("SELECT bi.*, i.*, b.* FROM items AS i, biblioitems AS bi ,biblio AS b WHERE itemnumber=? AND i.biblioitemnumber=bi.biblioitemnumber AND bi.biblionumber=b.biblionumber;"); + $sth->execute($item_number); + if ($sth->err) { + warn sprintf('Database returned the following error: %s', $sth->errstr); + } + my $data = $sth->fetchrow_hashref; + # Replaced item's itemtype with the more user-friendly description... + my $sth1 = $dbh->prepare("SELECT itemtype,description FROM itemtypes WHERE itemtype = ?"); + $sth1->execute($data->{'itemtype'}); + if ($sth1->err) { + warn sprintf('Database returned the following error: %s', $sth1->errstr); + } + my $data1 = $sth->fetchrow_hashref; + $data->{'itemtype'} = $data1->{'description'}; + $data->{'itype'} = $data1->{'description'}; + $barcode_only ? return $data->{'barcode'} : return $data; +} + +sub _get_text_fields { + my $format_string = shift; + my $csv = Text::CSV_XS->new({allow_whitespace => 1}); + my $status = $csv->parse($format_string); + my @sorted_fields = map {{ 'code' => $_, desc => $_ }} $csv->fields(); + my $error = $csv->error_input(); + warn sprintf('Text field sort failed with this error: %s', $error) if $error; + return \@sorted_fields; +} + + +sub _split_lccn { + my ($lccn) = @_; + $_ = $lccn; + # lccn examples: 'HE8700.7 .P6T44 1983', 'BS2545.E8 H39 1996'; + my (@parts) = m/ + ^([a-zA-Z]+) # HE # BS + (\d+(?:\.\d)*) # 8700.7 # 2545 + \s* + (\.*\D+\d*) # .P6 # .E8 + \s* + (.*) # T44 1983 # H39 1996 # everything else (except any bracketing spaces) + \s* + /x; + unless (scalar @parts) { + warn sprintf('regexp failed to match string: %s', $_); + push @parts, $_; # if no match, just push the whole string. + } + push @parts, split /\s+/, pop @parts; # split the last piece into an arbitrary number of pieces at spaces + $debug and warn "split_lccn array: ", join(" | ", @parts), "\n"; + return @parts; +} + +sub _split_ddcn { + my ($ddcn) = @_; + $_ = $ddcn; + s/\///g; # in theory we should be able to simply remove all segmentation markers and arrive at the correct call number... + my (@parts) = m/ + ^([a-zA-Z-]+(?:$possible_decimal)?) # R220.3 # BIO # first example will require extra splitting + \s+ + (.+) # H2793Z H32 c.2 # R5c.1 # everything else (except bracketing spaces) + \s* + /x; + unless (scalar @parts) { + warn sprintf('regexp failed to match string: %s', $_); + push @parts, $_; # if no match, just push the whole string. + } + + if ($parts[ 0] =~ /^([a-zA-Z]+)($possible_decimal)$/) { + shift @parts; # pull off the mathching first element, like example 1 + unshift @parts, $1, $2; # replace it with the two pieces + } + + push @parts, split /\s+/, pop @parts; # split the last piece into an arbitrary number of pieces at spaces + + if ($parts[-1] !~ /^.*\d-\d.*$/ && $parts[-1] =~ /^(.*\d+)(\D.*)$/) { + pop @parts; # pull off the mathching last element, like example 2 + push @parts, $1, $2; # replace it with the two pieces + } + + $debug and print STDERR "split_ddcn array: ", join(" | ", @parts), "\n"; + return @parts; +} + +sub _split_fcn { + my ($fcn) = @_; + my @fcn_split = (); + # Split fiction call numbers based on spaces + SPLIT_FCN: + while ($fcn) { + if ($fcn =~ m/([A-Za-z0-9]+\.?[0-9]?)(\W?).*?/x) { + push (@fcn_split, $1); + $fcn = $'; + } + else { + last SPLIT_FCN; # No match, break out of the loop + } + } + unless (scalar @fcn_split) { + warn sprintf('regexp failed to match string: %s', $_); + push (@fcn_split, $_); + } + return @fcn_split; +} + +sub _get_barcode_data { + my ( $f, $item, $record ) = @_; + my $kohatables = _desc_koha_tables(); + my $datastring = ''; + my $match_kohatable = join( + '|', + ( + @{ $kohatables->{'biblio'} }, + @{ $kohatables->{'biblioitems'} }, + @{ $kohatables->{'items'} } + ) + ); + FIELD_LIST: + while ($f) { + my $err = ''; + $f =~ s/^\s?//; + if ( $f =~ /^'(.*)'.*/ ) { + # single quotes indicate a static text string. + $datastring .= $1; + $f = $'; + next FIELD_LIST; + } + elsif ( $f =~ /^($match_kohatable).*/ ) { + if ($item->{$f}) { + $datastring .= $item->{$f}; + } else { + $debug and warn sprintf("The '%s' field contains no data.", $f); + } + $f = $'; + next FIELD_LIST; + } + elsif ( $f =~ /^([0-9a-z]{3})(\w)(\W?).*?/ ) { + my ($field,$subf,$ws) = ($1,$2,$3); + my $subf_data; + my ($itemtag, $itemsubfieldcode) = &GetMarcFromKohaField("items.itemnumber",''); + my @marcfield = $record->field($field); + if(@marcfield) { + if($field eq $itemtag) { # item-level data, we need to get the right item. + ITEM_FIELDS: + foreach my $itemfield (@marcfield) { + if ( $itemfield->subfield($itemsubfieldcode) eq $item->{'itemnumber'} ) { + if ($itemfield->subfield($subf)) { + $datastring .= $itemfield->subfield($subf) . $ws; + } + else { + warn sprintf("The '%s' field contains no data.", $f); + } + last ITEM_FIELDS; + } + } + } else { # bib-level data, we'll take the first matching tag/subfield. + if ($marcfield[0]->subfield($subf)) { + $datastring .= $marcfield[0]->subfield($subf) . $ws; + } + else { + warn sprintf("The '%s' field contains no data.", $f); + } + } + } + $f = $'; + next FIELD_LIST; + } + else { + warn sprintf('Failed to parse label format string: %s', $f); + last FIELD_LIST; # Failed to match + } + } + return $datastring; +} + +sub _desc_koha_tables { + my $dbh = C4::Context->dbh(); + my $kohatables; + for my $table ( 'biblio','biblioitems','items' ) { + my $sth = $dbh->column_info(undef,undef,$table,'%'); + while (my $info = $sth->fetchrow_hashref()){ + push @{$kohatables->{$table}} , $info->{'COLUMN_NAME'} ; + } + $sth->finish; + } + return $kohatables; +} + +### This series of functions calculates the position of text and barcode on individual labels +### Please *do not* add printing types which are non-atomic. Instead, build code which calls the necessary atomic printing types to form the non-atomic types. See the ALT type +### in labels/label-create-pdf.pl as an example. +### NOTE: Each function must be passed seven parameters and return seven even if some are 0 or undef + +sub _BIB { + my $self = shift; + my $line_spacer = ($self->{'font_size'} * 1); # number of pixels between text rows (This is actually leading: baseline to baseline minus font size. Recommended starting point is 20% of font size.). + my $text_lly = ($self->{'lly'} + ($self->{'height'} - $self->{'top_text_margin'})); + return $self->{'llx'}, $text_lly, $line_spacer, 0, 0, 0, 0; +} + +sub _BAR { + my $self = shift; + my $barcode_llx = $self->{'llx'} + $self->{'left_text_margin'}; # this places the bottom left of the barcode the left text margin distance to right of the the left edge of the label ($llx) + my $barcode_lly = $self->{'lly'} + $self->{'top_text_margin'}; # this places the bottom left of the barcode the top text margin distance above the bottom of the label ($lly) + my $barcode_width = 0.8 * $self->{'width'}; # this scales the barcode width to 80% of the label width + my $barcode_y_scale_factor = 0.01 * $self->{'height'}; # this scales the barcode height to 10% of the label height + return 0, 0, 0, $barcode_llx, $barcode_lly, $barcode_width, $barcode_y_scale_factor; +} + +sub _BIBBAR { + my $self = shift; + my $barcode_llx = $self->{'llx'} + $self->{'left_text_margin'}; # this places the bottom left of the barcode the left text margin distance to right of the the left edge of the label ($self->{'llx'}) + my $barcode_lly = $self->{'lly'} + $self->{'top_text_margin'}; # this places the bottom left of the barcode the top text margin distance above the bottom of the label ($lly) + my $barcode_width = 0.8 * $self->{'width'}; # this scales the barcode width to 80% of the label width + my $barcode_y_scale_factor = 0.01 * $self->{'height'}; # this scales the barcode height to 10% of the label height + my $line_spacer = ($self->{'font_size'} * 1); # number of pixels between text rows (This is actually leading: baseline to baseline minus font size. Recommended starting point is 20% of font size.). + my $text_lly = ($self->{'lly'} + ($self->{'height'} - $self->{'top_text_margin'})); + return $self->{'llx'}, $text_lly, $line_spacer, $barcode_llx, $barcode_lly, $barcode_width, $barcode_y_scale_factor; +} + +sub _BARBIB { + my $self = shift; + my $barcode_llx = $self->{'llx'} + $self->{'left_text_margin'}; # this places the bottom left of the barcode the left text margin distance to right of the the left edge of the label ($self->{'llx'}) + my $barcode_lly = ($self->{'lly'} + $self->{'height'}) - $self->{'top_text_margin'}; # this places the bottom left of the barcode the top text margin distance below the top of the label ($self->{'lly'}) + my $barcode_width = 0.8 * $self->{'width'}; # this scales the barcode width to 80% of the label width + my $barcode_y_scale_factor = 0.01 * $self->{'height'}; # this scales the barcode height to 10% of the label height + my $line_spacer = ($self->{'font_size'} * 1); # number of pixels between text rows (This is actually leading: baseline to baseline minus font size. Recommended starting point is 20% of font size.). + my $text_lly = (($self->{'lly'} + $self->{'height'}) - $self->{'top_text_margin'} - (($self->{'lly'} + $self->{'height'}) - $barcode_lly)); + return $self->{'llx'}, $text_lly, $line_spacer, $barcode_llx, $barcode_lly, $barcode_width, $barcode_y_scale_factor; +} + +sub new { + my ($invocant, %params) = @_; + my $type = ref($invocant) || $invocant; + my $self = { + batch_id => $params{'batch_id'}, + item_number => $params{'item_number'}, + llx => $params{'llx'}, + lly => $params{'lly'}, + height => $params{'height'}, + width => $params{'width'}, + top_text_margin => $params{'top_text_margin'}, + left_text_margin => $params{'left_text_margin'}, + barcode_type => $params{'barcode_type'}, + printing_type => $params{'printing_type'}, + guidebox => $params{'guidebox'}, + font => $params{'font'}, + font_size => $params{'font_size'}, + callnum_split => $params{'callnum_split'}, + justify => $params{'justify'}, + format_string => $params{'format_string'}, + text_wrap_cols => $params{'text_wrap_cols'}, + barcode => 0, + }; + if ($self->{'guidebox'}) { + $self->{'guidebox'} = _guide_box($self->{'llx'}, $self->{'lly'}, $self->{'width'}, $self->{'height'}); + } + bless ($self, $type); + return $self; +} + +sub get_label_type { + my $self = shift; + return $self->{'printing_type'}; +} + +sub get_attr { + my $self = shift; + if (_check_params(@_) eq 1) { + return -1; + } + my ($attr) = @_; + if (exists($self->{$attr})) { + return $self->{$attr}; + } + else { + return -1; + } + return; +} + +sub create_label { + my $self = shift; + my $label_text = ''; + my ($text_llx, $text_lly, $line_spacer, $barcode_llx, $barcode_lly, $barcode_width, $barcode_y_scale_factor); + { + no strict 'refs'; + ($text_llx, $text_lly, $line_spacer, $barcode_llx, $barcode_lly, $barcode_width, $barcode_y_scale_factor) = &{"_$self->{'printing_type'}"}($self); # an obfuscated call to the correct printing type sub + } + if ($self->{'printing_type'} =~ /BIB/) { + $label_text = draw_label_text( $self, + llx => $text_llx, + lly => $text_lly, + line_spacer => $line_spacer, + ); + } + if ($self->{'printing_type'} =~ /BAR/) { + barcode( $self, + llx => $barcode_llx, + lly => $barcode_lly, + width => $barcode_width, + y_scale_factor => $barcode_y_scale_factor, + ); + } + return $label_text if $label_text; + return; +} + +sub draw_label_text { + my ($self, %params) = @_; + my @label_text = (); + my $text_llx = 0; + my $text_lly = $params{'lly'}; + my $font = $self->{'font'}; + my $item = _get_label_item($self->{'item_number'}); + my $label_fields = _get_text_fields($self->{'format_string'}); + my $record = GetMarcBiblio($item->{'biblionumber'}); + # FIXME - returns all items, so you can't get data from an embedded holdings field. + # TODO - add a GetMarcBiblio1item(bibnum,itemnum) or a GetMarcItem(itemnum). + my $cn_source = ($item->{'cn_source'} ? $item->{'cn_source'} : C4::Context->preference('DefaultClassificationSource')); + LABEL_FIELDS: # process data for requested fields on current label + for my $field (@$label_fields) { + if ($field->{'code'} eq 'itemtype') { + $field->{'data'} = C4::Context->preference('item-level_itypes') ? $item->{'itype'} : $item->{'itemtype'}; + } + else { + $field->{'data'} = _get_barcode_data($field->{'code'},$item,$record); + } + ($field->{'code'} eq 'title') ? (($font =~ /T/) ? ($font = 'TI') : ($font = ($font . 'O'))) : ($font = $font); + my $field_data = $field->{'data'}; + if ($field_data) { + $field_data =~ s/\n//g; + $field_data =~ s/\r//g; + } + my @label_lines; + my @callnumber_list = ('itemcallnumber', '050a', '050b', '082a', '952o'); # Fields which hold call number data FIXME: ( 060? 090? 092? 099? ) + if ((grep {$field->{'code'} =~ m/$_/} @callnumber_list) and ($self->{'printing_type'} eq 'BIB') and ($self->{'callnum_split'})) { # If the field contains the call number, we do some sp + if ($cn_source eq 'lcc') { + @label_lines = _split_lccn($field_data); + @label_lines = _split_fcn($field_data) if !@label_lines; # If it was not a true lccn, try it as a fiction call number + push (@label_lines, $field_data) if !@label_lines; # If it was not that, send it on unsplit + } elsif ($cn_source eq 'ddc') { + @label_lines = _split_ddcn($field_data); + @label_lines = _split_fcn($field_data) if !@label_lines; + push (@label_lines, $field_data) if !@label_lines; + } else { + warn sprintf('Call number splitting failed for: %s. Please add this call number to bug #2500 at bugs.koha.org', $field_data); + push @label_lines, $field_data; + } + } + else { + if ($field_data) { + $field_data =~ s/\/$//g; # Here we will strip out all trailing '/' in fields other than the call number... + $field_data =~ s/\(/\\\(/g; # Escape '(' and ')' for the pdf object stream... + $field_data =~ s/\)/\\\)/g; + } + eval{$Text::Wrap::columns = $self->{'text_wrap_cols'};}; + my @line = split(/\n/ ,wrap('', '', $field_data)); + # If this is a title field, limit to two lines; all others limit to one... FIXME: this is rather arbitrary + if ($field->{'code'} eq 'title' && scalar(@line) >= 2) { + while (scalar(@line) > 2) { + pop @line; + } + } else { + while (scalar(@line) > 1) { + pop @line; + } + } + push(@label_lines, @line); + } + LABEL_LINES: # generate lines of label text for current field + foreach my $line (@label_lines) { + next LABEL_LINES if $line eq ''; + my $string_width = C4::Labels::PDF->StrWidth($line, $font, $self->{'font_size'}); + if ($self->{'justify'} eq 'R') { + $text_llx = $params{'llx'} + $self->{'width'} - ($self->{'left_text_margin'} + $string_width); + } + elsif($self->{'justify'} eq 'C') { + # some code to try and center each line on the label based on font size and string point width... + my $whitespace = ($self->{'width'} - ($string_width + (2 * $self->{'left_text_margin'}))); + $text_llx = (($whitespace / 2) + $params{'llx'} + $self->{'left_text_margin'}); + } + else { + $text_llx = ($params{'llx'} + $self->{'left_text_margin'}); + } + push @label_text, { + text_llx => $text_llx, + text_lly => $text_lly, + font => $font, + font_size => $self->{'font_size'}, + line => $line, + }; + $text_lly = $text_lly - $params{'line_spacer'}; + } + $font = $self->{'font'}; # reset font for next field + } #foreach field + return \@label_text; +} + +sub barcode { + my $self = shift; + my %params = @_; + $params{'barcode_data'} = _get_label_item($self->{'item_number'}, 1) if !$params{'barcode_data'}; + $params{'barcode_type'} = $self->{'barcode_type'} if !$params{'barcode_type'}; + my $x_scale_factor = 1; + my $num_of_bars = length($params{'barcode_data'}); + my $tot_bar_length = 0; + my $bar_length = 0; + my $guard_length = 10; + my $hide_text = 'yes'; + if ($params{'barcode_type'} =~ m/CODE39/) { + $bar_length = '17.5'; + $tot_bar_length = ($bar_length * $num_of_bars) + ($guard_length * 2); + $x_scale_factor = ($params{'width'} / $tot_bar_length); + if ($params{'barcode_type'} eq 'CODE39MOD') { + my $c39 = CheckDigits('visa'); # get modulo43 checksum + $params{'barcode_data'} = $c39->complete($params{'barcode_data'}); + } + elsif ($params{'barcode_type'} eq 'CODE39MOD10') { + my $c39_10 = CheckDigits('visa'); # get modulo43 checksum + $params{'barcode_data'} = $c39_10->complete($params{'barcode_data'}); + $hide_text = ''; + } + eval { + PDF::Reuse::Barcode::Code39( + x => $params{'llx'}, + y => $params{'lly'}, + value => "*$params{barcode_data}*", + xSize => $x_scale_factor, + ySize => $params{'y_scale_factor'}, + hide_asterisk => 1, + text => $hide_text, + mode => 'graphic', + ); + }; + if ($@) { + warn sprintf('Barcode generation failed for item %s with this error: %s', $self->{'item_number'}, $@); + } + } + elsif ($params{'barcode_type'} eq 'COOP2OF5') { + $bar_length = '9.43333333333333'; + $tot_bar_length = ($bar_length * $num_of_bars) + ($guard_length * 2); + $x_scale_factor = ($params{'width'} / $tot_bar_length) * 0.9; + eval { + PDF::Reuse::Barcode::COOP2of5( + x => $params{'llx'}, + y => $params{'lly'}, + value => "*$params{barcode_data}*", + xSize => $x_scale_factor, + ySize => $params{'y_scale_factor'}, + mode => 'graphic', + ); + }; + if ($@) { + warn sprintf('Barcode generation failed for item %s with this error: %s', $self->{'item_number'}, $@); + } + } + elsif ( $params{'barcode_type'} eq 'INDUSTRIAL2OF5' ) { + $bar_length = '13.1333333333333'; + $tot_bar_length = ($bar_length * $num_of_bars) + ($guard_length * 2); + $x_scale_factor = ($params{'width'} / $tot_bar_length) * 0.9; + eval { + PDF::Reuse::Barcode::Industrial2of5( + x => $params{'llx'}, + y => $params{'lly'}, + value => "*$params{barcode_data}*", + xSize => $x_scale_factor, + ySize => $params{'y_scale_factor'}, + mode => 'graphic', + ); + }; + if ($@) { + warn sprintf('Barcode generation failed for item %s with this error: %s', $self->{'item_number'}, $@); + } + } +} + +sub csv_data { + my $self = shift; + my $label_fields = _get_text_fields($self->{'format_string'}); + my $item = _get_label_item($self->{'item_number'}); + my $bib_record = GetMarcBiblio($item->{biblionumber}); + my @csv_data = (map { _get_barcode_data($_->{'code'},$item,$bib_record) } @$label_fields); + return \@csv_data; +} + +1; +__END__ + +=head1 NAME + +C4::Labels::Label - A class for creating and manipulating label objects in Koha + +=head1 ABSTRACT + +This module provides methods for creating, and otherwise manipulating single label objects used by Koha to create and export labels. + +=head1 METHODS + +=head2 new() + + Invoking the I method constructs a new label object containing the supplied values. Depending on the final output format of the label data + the minimal required parameters change. (See the implimentation of this object type in labels/label-create-pdf.pl and labels/label-create-csv.pl + and labels/label-create-xml.pl for examples.) The following parameters are optionally accepted as key => value pairs: + + C Batch id with which this label is associated + C Item number of item to be the data source for this label + C Height of this label (All measures passed to this method B be supplied in postscript points) + C Width of this label + C Top margin of this label + C Left margin of this label + C Defines the barcode type to be used on labels. NOTE: At present only the following barcode types are supported in the label creator code: + +=over 9 + +=item . + CODE39 = Code 3 of 9 + +=item . + CODE39MOD = Code 3 of 9 with modulo 43 checksum + +=item . + CODE39MOD10 = Code 3 of 9 with modulo 10 checksum + +=item . + COOP2OF5 = A varient of 2 of 5 barcode based on NEC's "Process 8000" code + +=item . + INDUSTRIAL2OF5 = The standard 2 of 5 barcode (a binary level bar code developed by Identicon Corp. and Computer Identics Corp. in 1970) + +=back + + C Defines the general layout to be used on labels. NOTE: At present there are only five printing types supported in the label creator code: + +=over 9 + +=item . +BIB = Only the bibliographic data is printed + +=item . +BARBIB = Barcode proceeds bibliographic data + +=item . +BIBBAR = Bibliographic data proceeds barcode + +=item . +ALT = Barcode and bibliographic data are printed on alternating labels + +=item . +BAR = Only the barcode is printed + +=back + + C Setting this to '1' will result in a guide box being drawn around the labels marking the edge of each label + C Defines the type of font to be used on labels. NOTE: The following fonts are available by default on most systems: + +=over 9 + +=item . +TR = Times-Roman + +=item . +TB = Times Bold + +=item . +TI = Times Italic + +=item . +TBI = Times Bold Italic + +=item . +C = Courier + +=item . +CB = Courier Bold + +=item . +CO = Courier Oblique (Italic) + +=item . +CBO = Courier Bold Oblique + +=item . +H = Helvetica + +=item . +HB = Helvetica Bold + +=item . +HBO = Helvetical Bold Oblique + +=back + + C Defines the size of the font in postscript points to be used on labels + C Setting this to '1' will enable call number splitting on labels + C Defines the text justification to be used on labels. NOTE: The following justification styles are currently supported by label creator code: + +=over 9 + +=item . +L = Left + +=item . +C = Center + +=item . +R = Right + +=back + + C Defines what fields will be printed and in what order they will be printed on labels. These include any of the data fields that may be mapped + to your MARC frameworks. Specify MARC subfields as a 4-character tag-subfield string: ie. 254a Enclose a whitespace-separated list of fields + to concatenate on one line in double quotes. ie. "099a 099b" or "itemcallnumber barcode" Static text strings may be entered in single-quotes: + ie. 'Some static text here.' + C Defines the column after which the text will wrap to the next line. + +=head2 get_label_type() + + Invoking the I method will return the printing type of the label object. + + example: + Cget_label_type();> + +=head2 get_attr($attribute) + + Invoking the I method will return the value of the requested attribute or -1 on errors. + + example: + Cget_attr($attribute);> + +=head2 create_label() + + Invoking the I method generates the text for that label and returns it as an arrayref of an array contianing the formatted text as well as creating the barcode + and writing it directly to the pdf stream. The handling of the barcode is not quite good OO form due to the linear format of PDF::Reuse::Barcode. Be aware that the instantiating + code is responsible to properly format the text for insertion into the pdf stream as well as the actual insertion. + + example: + my $label_text = $label->create_label(); + +=head2 draw_label_text() + + Invoking the I method generates the label text for the label object and returns it as an arrayref of an array containing the formatted text. The same caveats + apply to this method as to C. This method accepts the following parameters as key => value pairs: (NOTE: The unit is the postscript point - 72 per inch) + + C The lower-left x coordinate for the text block (The point of origin for all PDF's is the lower left of the page per ISO 32000-1) + C The lower-left y coordinate for the text block + C The top margin for the text block. + C The number of pixels between text rows (This is actually leading: baseline to baseline minus font size. Recommended starting point is 20% of font size) + C The font to use for this label. See documentation on the new() method for supported fonts. + C The font size in points to use for this label. + C The style of justification to use for this label. See documentation on the new() method for supported justification styles. + + example: + Cdraw_label_text( + llx => $text_llx, + lly => $text_lly, + top_text_margin => $label_top_text_margin, + line_spacer => $text_leading, + font => $text_font, + font_size => $text_font_size, + justify => $text_justification, + );> + +=head2 barcode() + + Invoking the I method generates a barcode for the label object and inserts it into the current pdf stream. This method accepts the following parameters as key => value + pairs (C is optional and omitting it will cause the barcode from the current item to be used. C is also optional. Omission results in the barcode + type of the current template being used.): + + C The lower-left x coordinate for the barcode block (The point of origin for all PDF's is the lower left of the page per ISO 32000-1) + C The lower-left y coordinate for the barcode block + C The width of the barcode block + C The scale factor to be applied to the y axis of the barcode block + C The data to be encoded in the barcode + C The barcode type (See the C method for supported barcode types) + + example: + C<$label->barcode( + llx => $barcode_llx, + lly => $barcode_lly, + width => $barcode_width, + y_scale_factor => $barcode_y_scale_factor, + barcode_data => $barcode, + barcode_type => $barcodetype, + );> + +=head2 csv_data() + + Invoking the I method returns an arrayref of an array containing the label data suitable for passing to Text::CSV_XS->combine() to produce csv output. + + example: + Ccsv_data();> + +=head1 AUTHOR + +Mason James + +Chris Nighswonger + +=head1 COPYRIGHT + +Copyright 2006 Katipo Communications. + +Copyright 2009 Foundations Bible College. + +=head1 LICENSE + +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. + +You should have received a copy of the GNU General Public License along with Koha; if not, write to the Free Software Foundation, Inc., 59 Temple Place, +Suite 330, Boston, MA 02111-1307 USA + +=head1 DISCLAIMER OF WARRANTY + +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. + +=cut diff --git a/C4/Labels/Layout.pm b/C4/Labels/Layout.pm new file mode 100644 index 0000000000..da2e26f4c5 --- /dev/null +++ b/C4/Labels/Layout.pm @@ -0,0 +1,419 @@ +package C4::Labels::Layout; + +use strict; +use warnings; + +use DBI qw(neat); + +use C4::Context; +use C4::Debug; +use C4::Labels::PDF; + +BEGIN { + use version; our $VERSION = qv('1.0.0_1'); +} + +# FIXME: Consider this style parameter verification instead... +# my %param = @_; +# for (keys %param) +# { my $lc = lc($_); +# if (exists $default{$lc}) +# { $default{$lc} = $param{$_}; +# } +# else +# { print STDERR "Unknown parameter $_ , not used \n"; +# } +# } + +sub _check_params { + my $exit_code = 0; + my @valtmpl_id_params = ( + 'barcode_type', + 'printing_type', + 'layout_name', + 'guidebox', + 'font', + 'font_size', + 'callnum_split', + 'text_justify', + 'format_string', + ); + if (scalar(@_) >1) { + my %given_params = @_; + foreach my $key (keys %given_params) { + if (!(grep m/$key/, @valtmpl_id_params)) { + warn sprintf('(Multiple parameters) Unrecognized parameter type of "%s".', $key); + $exit_code = 1; + } + } + } + else { + if (!(grep m/$_/, @valtmpl_id_params)) { + warn sprintf('(Single parameter) Unrecognized parameter type of "%s".', $_); + $exit_code = 1; + } + } + return $exit_code; +} + +sub new { + my $invocant = shift; + if (_check_params(@_) eq 1) { + return -1; + } + my $type = ref($invocant) || $invocant; + my $self = { + barcode_type => 'CODE39', + printing_type => 'BAR', + layout_name => 'DEFAULT', + guidebox => 0, + font => 'TR', + font_size => 3, + callnum_split => 0, + text_justify => 'L', + format_string => 'title, author, isbn, issn, itemtype, barcode, callnumber', + @_, + }; + bless ($self, $type); + return $self; +} + +sub retrieve { + my $invocant = shift; + my %opts = @_; + my $type = ref($invocant) || $invocant; + my $query = "SELECT * FROM labels_layouts WHERE layout_id = ?"; + my $sth = C4::Context->dbh->prepare($query); + $sth->execute($opts{'layout_id'}); + if ($sth->err) { + warn sprintf('Database returned the following error: %s', $sth->errstr); + return -1; + } + my $self = $sth->fetchrow_hashref; + bless ($self, $type); + return $self; +} + +sub delete { + my $self = {}; + my %opts = (); + my $call_type = ''; + my $query_param = ''; + if (ref($_[0])) { + $self = shift; # check to see if this is a method call + $call_type = 'C4::Labels::Layout->delete'; + $query_param = $self->{'layout_id'}; + } + else { + %opts = @_; + $call_type = 'C4::Labels::Layout::delete'; + $query_param = $opts{'layout_id'}; + } + if ($query_param eq '') { # If there is no layout id then we cannot delete it + warn sprintf('%s : Cannot delete layout as the layout id is invalid or non-existant.', $call_type); + return -1; + } + my $query = "DELETE FROM labels_layouts WHERE layout_id = ?"; + my $sth = C4::Context->dbh->prepare($query); + $sth->execute($query_param); + if ($sth->err) { + warn sprintf('%s : Database returned the following error: %s', $call_type, $sth->errstr); + return -1; + } + return 0; +} + +sub save { + my $self = shift; + if ($self->{'layout_id'}) { # if we have an id, the record exists and needs UPDATE + my @params; + my $query = "UPDATE labels_layouts SET "; + foreach my $key (keys %{$self}) { + next if $key eq 'layout_id'; + push (@params, $self->{$key}); + $query .= "$key=?, "; + } + $query = substr($query, 0, (length($query)-2)); + $query .= " WHERE layout_id=?;"; + push (@params, $self->{'layout_id'}); + my $sth = C4::Context->dbh->prepare($query); + #local $sth->{TraceLevel} = "3"; # enable DBI trace and set level; outputs to STDERR + $sth->execute(@params); + if ($sth->err) { + warn sprintf('Database returned the following error: %s', $sth->errstr); + return -1; + } + return $self->{'layout_id'}; + } + else { # otherwise create a new record + my @params; + my $query = "INSERT INTO labels_layouts ("; + foreach my $key (keys %{$self}) { + push (@params, $self->{$key}); + $query .= "$key, "; + } + $query = substr($query, 0, (length($query)-2)); + $query .= ") VALUES ("; + for (my $i=1; $i<=(scalar keys %$self); $i++) { + $query .= "?,"; + } + $query = substr($query, 0, (length($query)-1)); + $query .= ");"; + my $sth = C4::Context->dbh->prepare($query); + $sth->execute(@params); + if ($sth->err) { + warn sprintf('Database returned the following error: %s', $sth->errstr); + return -1; + } + my $sth1 = C4::Context->dbh->prepare("SELECT MAX(layout_id) FROM labels_layouts;"); + $sth1->execute(); + my $id = $sth1->fetchrow_array; + return $id; + } +} + +sub get_attr { + my $self = shift; + if (_check_params(@_) eq 1) { + return -1; + } + my ($attr) = @_; + if (exists($self->{$attr})) { + return $self->{$attr}; + } + else { + return -1; + } + return; +} + +sub set_attr { + my $self = shift; + if (_check_params(@_) eq 1) { + return -1; + } + my %attrs = @_; + foreach my $attrib (keys(%attrs)) { + $self->{$attrib} = $attrs{$attrib}; + }; + return 0; +} + +sub get_text_wrap_cols { + my $self = shift; + my %params = @_; + my $string = ''; + my $strwidth = 0; + my $col_count = 0; + my $textlimit = $params{'label_width'} - ( 3 * $params{'left_text_margin'}); + + while ($strwidth < $textlimit) { + $string .= '0'; + $col_count++; + $strwidth = C4::Labels::PDF->StrWidth( $string, $self->{'font'}, $self->{'font_size'} ); + } + return $col_count; +} + +1; +__END__ + +=head1 NAME + +C4::Labels::Layout -A class for creating and manipulating layout objects in Koha + +=head1 ABSTRACT + +This module provides methods for creating, retrieving, and otherwise manipulating label layout objects used by Koha to create and export labels. + +=head1 METHODS + +=head2 new() + + Invoking the I method constructs a new layout object containing the default values for a layout. + The following parameters are optionally accepted as key => value pairs: + + C Defines the barcode type to be used on labels. NOTE: At present only the following barcode types are supported in the label creator code: + +=over 9 + +=item . + CODE39 = Code 3 of 9 + +=item . + CODE39MOD = Code 3 of 9 with modulo 43 checksum + +=item . + CODE39MOD10 = Code 3 of 9 with modulo 10 checksum + +=item . + COOP2OF5 = A varient of 2 of 5 barcode based on NEC's "Process 8000" code + +=item . + INDUSTRIAL2OF5 = The standard 2 of 5 barcode (a binary level bar code developed by Identicon Corp. and Computer Identics Corp. in 1970) + +=back + + C Defines the general layout to be used on labels. NOTE: At present there are only five printing types supported in the label creator code: + +=over 9 + +=item . +BIB = Only the bibliographic data is printed + +=item . +BARBIB = Barcode proceeds bibliographic data + +=item . +BIBBAR = Bibliographic data proceeds barcode + +=item . +ALT = Barcode and bibliographic data are printed on alternating labels + +=item . +BAR = Only the barcode is printed + +=back + + C The descriptive name for this layout. + C Setting this to '1' will result in a guide box being drawn around the labels marking the edge of each label + C Defines the type of font to be used on labels. NOTE: The following fonts are available by default on most systems: + +=over 9 + +=item . +TR = Times-Roman + +=item . +TB = Times Bold + +=item . +TI = Times Italic + +=item . +TBI = Times Bold Italic + +=item . +C = Courier + +=item . +CB = Courier Bold + +=item . +CO = Courier Oblique (Italic) + +=item . +CBO = Courier Bold Oblique + +=item . +H = Helvetica + +=item . +HB = Helvetica Bold + +=item . +HBO = Helvetical Bold Oblique + +=back + + C Defines the size of the font in postscript points to be used on labels + C Setting this to '1' will enable call number splitting on labels + C Defines the text justification to be used on labels. NOTE: The following justification styles are currently supported by label creator code: + +=over 9 + +=item . +L = Left + +=item . +C = Center + +=item . +R = Right + +=back + + C Defines what fields will be printed and in what order they will be printed on labels. These include any of the data fields that may be mapped + to your MARC frameworks. Specify MARC subfields as a 4-character tag-subfield string: ie. 254a Enclose a whitespace-separated list of fields + to concatenate on one line in double quotes. ie. "099a 099b" or "itemcallnumber barcode" Static text strings may be entered in single-quotes: + ie. 'Some static text here.' + + example: + Cnew(); # Creates and returns a new layout object> + + Cnew(barcode_type => 'CODE39', printing_type => 'BIBBAR', font => 'C', font_size => 6); # Creates and returns a new layout object using + the supplied values to override the defaults> + + B This layout is I written to the database until save() is invoked. You have been warned! + +=head2 retrieve(layout_id => layout_id) + + Invoking the I method constructs a new layout object containing the current values for layout_id. The method returns a new object upon success and 1 upon failure. + Errors are logged to the Apache log. + + example: + Cretrieve(layout_id => 1); # Retrieves layout record 1 and returns an object containing the record> + +=head2 delete() + + Invoking the delete method attempts to delete the layout from the database. The method returns 0 upon success and -1 upon failure. Errors are logged to the Apache log. + NOTE: This method may also be called as a function and passed a key/value pair simply deleteing that template from the database. See the example below. + + examples: + Cdelete(); # to delete the record behind the $layout object> + Cdelete(layout_id => 1); # to delete layout record 1> + +=head2 save() + + Invoking the I method attempts to insert the layout into the database if the layout is new and update the existing layout record if the layout exists. + The method returns the new record id upon success and -1 upon failure (This avoids conflicting with a record id of 1). Errors are logged to the Apache log. + + example: + Csave(); # to save the record behind the $layout object> + +=head2 get_attr($attribute) + + Invoking the I method will return the value of the requested attribute or -1 on errors. + + example: + Cget_attr($attribute);> + +=head2 set_attr(attribute => value, attribute_2 => value) + + Invoking the I method will set the value of the supplied attributes to the supplied values. The method accepts key/value pairs separated by + commas. + + example: + C<$layout->set_attr(attribute => value);> + +=head2 get_text_wrap_cols() + + Invoking the I method will return the number of columns that can be printed on the label before wrapping to the next line. + + examples: + Cget_text_wrap_cols();> + +=head1 AUTHOR + +Chris Nighswonger + +=head1 COPYRIGHT + +Copyright 2009 Foundations Bible College. + +=head1 LICENSE + +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. + +You should have received a copy of the GNU General Public License along with Koha; if not, write to the Free Software Foundation, Inc., 59 Temple Place, +Suite 330, Boston, MA 02111-1307 USA + +=head1 DISCLAIMER OF WARRANTY + +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. + +=cut diff --git a/C4/Labels/Lib.pm b/C4/Labels/Lib.pm new file mode 100644 index 0000000000..2229c60359 --- /dev/null +++ b/C4/Labels/Lib.pm @@ -0,0 +1,514 @@ +package C4::Labels::Lib; + +# Copyright 2009 Foundations Bible College. +# +# This file is part of Koha. +# +# Koha is free software; you can redistribute it and/or modify it under the +# terms of the GNU General Public License as published by the Free Software +# Foundation; either version 2 of the License, or (at your option) any later +# version. +# +# Koha is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along with +# Koha; if not, write to the Free Software Foundation, Inc., 59 Temple Place, +# Suite 330, Boston, MA 02111-1307 USA + +use strict; +use warnings; + +use Data::Dumper; + +use C4::Context; +use C4::Debug; + +BEGIN { + use version; our $VERSION = qv('1.0.0_1'); + use base qw(Exporter); + our @EXPORT_OK = qw(get_all_templates + get_all_layouts + get_all_profiles + get_batch_summary + get_label_summary + get_barcode_types + get_label_types + get_font_types + get_text_justification_types + get_label_output_formats + get_column_names + get_table_names + get_unit_values + html_table + ); +} + +#=head2 C4::Labels::Lib::_SELECT() +# +# This function returns a recordset upon success and 1 upon failure. Errors are logged to the Apache log. +# +# examples: +# +# my $field_value = _SELECT(field_name, table_name, condition); +# +#=cut + +sub _SELECT { + my @params = @_; + my $query = "SELECT $params[0] FROM $params[1]"; + $params[2] ? $query .= " WHERE $params[2];" : $query .= ';'; + my $sth = C4::Context->dbh->prepare($query); +# $sth->{'TraceLevel'} = 3; + $sth->execute(); + if ($sth->err) { + warn sprintf('Database returned the following error: %s', $sth->errstr); + return 1; + } + my $record_set = []; + while (my $row = $sth->fetchrow_hashref()) { + push(@$record_set, $row); + } + return $record_set; +} + +my $barcode_types = [ + {type => 'CODE39', name => 'Code 39', desc => 'Translates the characters 0-9, A-Z, \'-\', \'*\', \'+\', \'$\', \'%\', \'/\', \'.\' and \' \' to a barcode pattern.', selected => 0}, + {type => 'CODE39MOD', name => 'Code 39 + Modulo43', desc => 'Translates the characters 0-9, A-Z, \'-\', \'*\', \'+\', \'$\', \'%\', \'/\', \'.\' and \' \' to a barcode pattern. Encodes Mod 43 checksum.', selected => 0}, + {type => 'CODE39MOD10', name => 'Code 39 + Modulo10', desc => 'Translates the characters 0-9, A-Z, \'-\', \'*\', \'+\', \'$\', \'%\', \'/\', \'.\' and \' \' to a barcode pattern. Encodes Mod 10 checksum.', selected => 0}, + {type => 'COOP2OF5', name => 'COOP2of5', desc => 'Creates COOP2of5 barcodes from a string consisting of the numeric characters 0-9', selected => 0}, +# {type => 'EAN13', name => 'EAN13', desc => 'Creates EAN13 barcodes from a string of 12 or 13 digits. The check number (the 13:th digit) is calculated if not supplied.', selected => 0}, +# {type => 'EAN8', name => 'EAN8', desc => 'Translates a string of 7 or 8 digits to EAN8 barcodes. The check number (the 8:th digit) is calculated if not supplied.', selected => 0}, +# {type => 'IATA2of5', name => 'IATA2of5', desc => 'Creates IATA2of5 barcodes from a string consisting of the numeric characters 0-9', selected => 0}, + {type => 'INDUSTRIAL2OF5', name => 'Industrial2of5', desc => 'Creates Industrial2of5 barcodes from a string consisting of the numeric characters 0-9', selected => 0}, +# {type => 'ITF', name => 'Interleaved2of5', desc => 'Translates the characters 0-9 to a barcodes. These barcodes could also be called 'Interleaved2of5'.', selected => 0}, +# {type => 'MATRIX2OF5', name => 'Matrix2of5', desc => 'Creates Matrix2of5 barcodes from a string consisting of the numeric characters 0-9', selected => 0}, +# {type => 'NW7', name => 'NW7', desc => 'Creates a NW7 barcodes from a string consisting of the numeric characters 0-9', selected => 0}, +# {type => 'UPCA', name => 'UPCA', desc => 'Translates a string of 11 or 12 digits to UPCA barcodes. The check number (the 12:th digit) is calculated if not supplied.', selected => 0}, +# {type => 'UPCE', name => 'UPCE', desc => 'Translates a string of 6, 7 or 8 digits to UPCE barcodes. If the string is 6 digits long, '0' is added first in the string. The check number (the 8:th digit) is calculated if not supplied.', selected => 0}, +]; + +my $label_types = [ + {type => 'BIB', name => 'Biblio', desc => 'Only the bibliographic data is printed.', selected => 0}, + {type => 'BARBIB', name => 'Barcode/Biblio', desc => 'Barcode proceeds bibliographic data.', selected => 0}, + {type => 'BIBBAR', name => 'Biblio/Barcode', desc => 'Bibliographic data proceeds barcode.', selected => 0}, + {type => 'ALT', name => 'Alternating', desc => 'Barcode and bibliographic data are printed on alternating labels.', selected => 0}, + {type => 'BAR', name => 'Barcode', desc => 'Only the barcode is printed.', selected => 0}, +]; + +my $font_types = [ + {type => 'TR', name => 'Times-Roman', selected => 0}, + {type => 'TB', name => 'Times-Bold', selected => 0}, + {type => 'TI', name => 'Times-Italic', selected => 0}, + {type => 'TBI', name => 'Times-Bold-Italic', selected => 0}, + {type => 'C', name => 'Courier', selected => 0}, + {type => 'CB', name => 'Courier-Bold', selected => 0}, + {type => 'CO', name => 'Courier-Oblique', selected => 0}, + {type => 'CBO', name => 'Courier-Bold-Oblique', selected => 0}, + {type => 'H', name => 'Helvetica', selected => 0}, + {type => 'HB', name => 'Helvetica-Bold', selected => 0}, + {type => 'HBO', name => 'Helvetica-Bold-Oblique', selected => 0}, +]; + +my $text_justification_types = [ + {type => 'L', name => 'Left', selected => 0}, + {type => 'C', name => 'Center', selected => 0}, + {type => 'R', name => 'Right', selected => 0}, +# {type => 'F', name => 'Full', selected => 0}, +]; + +my $unit_values = [ + {type => 'POINT', desc => 'PostScript Points', value => 1, selected => 0}, + {type => 'AGATE', desc => 'Adobe Agates', value => 5.1428571, selected => 0}, + {type => 'INCH', desc => 'US Inches', value => 72, selected => 0}, + {type => 'MM', desc => 'SI Millimeters', value => 2.83464567, selected => 0}, + {type => 'CM', desc => 'SI Centimeters', value => 28.3464567, selected => 0}, +]; + +my $label_output_formats = [ + {type => 'pdf', desc => 'PDF File'}, + {type => 'csv', desc => 'CSV File'}, +]; + +=head2 C4::Labels::Lib::get_all_templates() + + This function returns a reference to a hash containing all templates upon success and 1 upon failure. Errors are logged to the Apache log. + + examples: + + my $templates = get_all_templates(); + +=cut + +sub get_all_templates { + my %params = @_; + my @templates = (); + my $query = "SELECT " . ($params{'field_list'} ? $params{'field_list'} : '*') . " FROM labels_templates"; + $query .= ($params{'filter'} ? " WHERE $params{'filter'};" : ';'); + my $sth = C4::Context->dbh->prepare($query); + $sth->execute(); + if ($sth->err) { + warn sprintf('Database returned the following error: %s', $sth->errstr); + return -1; + } + ADD_TEMPLATES: + while (my $template = $sth->fetchrow_hashref) { + push(@templates, $template); + } + return \@templates; +} + +=head2 C4::Labels::Lib::get_all_layouts() + + This function returns a reference to a hash containing all layouts upon success and 1 upon failure. Errors are logged to the Apache log. + + examples: + + my $layouts = get_all_layouts(); + +=cut + +sub get_all_layouts { + my %params = @_; + my @layouts = (); + #my $query = "SELECT * FROM labels_layouts;"; + my $query = "SELECT " . ($params{'field_list'} ? $params{'field_list'} : '*') . " FROM labels_layouts"; + $query .= ($params{'filter'} ? " WHERE $params{'filter'};" : ';'); + my $sth = C4::Context->dbh->prepare($query); + $sth->execute(); + if ($sth->err) { + warn sprintf('Database returned the following error: %s', $sth->errstr); + return -1; + } + ADD_LAYOUTS: + while (my $layout = $sth->fetchrow_hashref) { + push(@layouts, $layout); + } + return \@layouts; +} + +=head2 C4::Labels::Lib::get_all_profiles() + + This function returns an arrayref whose elements are hashes containing all profiles upon success and 1 upon failure. Errors are logged + to the Apache log. Two parameters are accepted. The first limits the field(s) returned. This parameter should be string of comma separted + fields. ie. "field_1, field_2, ...field_n" The second limits the records returned based on a string containing a valud SQL 'WHERE' filter. + NOTE: Do not pass in the keyword 'WHERE.' + + examples: + + my $profiles = get_all_profiles(); + my $profiles = get_all_profiles(field_list => field_list, filter => filter_string); + +=cut + +sub get_all_profiles { + my %params = @_; + my @profiles = (); + my $query = "SELECT " . ($params{'field_list'} ? $params{'field_list'} : '*') . " FROM printers_profile"; + $query .= ($params{'filter'} ? " WHERE $params{'filter'};" : ';'); + my $sth = C4::Context->dbh->prepare($query); +# $sth->{'TraceLevel'} = 3 if $debug; + $sth->execute(); + if ($sth->err) { + warn sprintf('Database returned the following error: %s', $sth->errstr); + return -1; + } + ADD_PROFILES: + while (my $profile = $sth->fetchrow_hashref) { + push(@profiles, $profile); + } + return \@profiles; +} + +=head2 C4::Labels::Lib::get_batch_summary() + + This function returns an arrayref whose elements are hashes containing the batch_ids of current batches along with the item count + for each batch upon success and 1 upon failure. Item counts are stored under the key '_item_count' Errors are logged to the Apache log. + One parameter is accepted which limits the records returned based on a string containing a valud SQL 'WHERE' filter. + + NOTE: Do not pass in the keyword 'WHERE.' + + examples: + + my $batches = get_batch_summary(); + my $batches = get_batch_summary(filter => filter_string); + +=cut + +sub get_batch_summary { + my %params = @_; + my @batches = (); + my $query = "SELECT DISTINCT batch_id FROM labels_batches"; + $query .= ($params{'filter'} ? " WHERE $params{'filter'};" : ';'); + my $sth = C4::Context->dbh->prepare($query); +# $sth->{'TraceLevel'} = 3; + $sth->execute(); + if ($sth->err) { + warn sprintf('Database returned the following error on attempted SELECT: %s', $sth->errstr); + return -1; + } + ADD_BATCHES: + while (my $batch = $sth->fetchrow_hashref) { + my $query = "SELECT count(item_number) FROM labels_batches WHERE batch_id=?;"; + my $sth1 = C4::Context->dbh->prepare($query); + $sth1->execute($batch->{'batch_id'}); + if ($sth1->err) { + warn sprintf('Database returned the following error on attempted SELECT count: %s', $sth1->errstr); + return -1; + } + my $count = $sth1->fetchrow_arrayref; + $batch->{'_item_count'} = @$count[0]; + push(@batches, $batch); + } + return \@batches; +} + +=head2 C4::Labels::Lib::get_label_summary() + + This function returns an arrayref whose elements are hashes containing the label_ids of current labels along with the item count + for each label upon success and 1 upon failure. Item counts are stored under the key '_item_count' Errors are logged to the Apache log. + One parameter is accepted which limits the records returned based on a string containing a valud SQL 'WHERE' filter. + + NOTE: Do not pass in the keyword 'WHERE.' + + examples: + + my $labels = get_label_summary(); + my $labels = get_label_summary(items => @item_list); + +=cut + +sub get_label_summary { + my %params = @_; + my $label_number = 0; + my @label_summaries = (); + my $query = "SELECT b.title, b.author, bi.itemtype, i.barcode, i.biblionumber FROM biblio AS b, biblioitems AS bi ,items AS i, labels_batches AS l WHERE itemnumber=? AND l.item_number=i.itemnumber AND i.biblioitemnumber=bi.biblioitemnumber AND bi.biblionumber=b.biblionumber AND l.batch_id=?;"; + my $sth = C4::Context->dbh->prepare($query); + foreach my $item (@{$params{'items'}}) { + $label_number++; + $sth->execute($item->{'item_number'}, $params{'batch_id'}); + if ($sth->err) { + warn sprintf('Database returned the following error on attempted SELECT: %s', $sth->errstr); + return -1; + } + my $record = $sth->fetchrow_hashref; + my $label_summary->{'_label_number'} = $label_number; + $record->{'author'} =~ s/[^\.|\w]$// if $record->{'author'}; # strip off ugly trailing chars... but not periods or word chars + $record->{'title'} =~ s/\W*$//; # strip off ugly trailing chars + # FIXME contructing staff interface URLs should be done *much* higher up the stack - for the most part, C4 module code + # should not know that it's part of a web app + $record->{'title'} = ' ' . $record->{'title'} . ''; + $label_summary->{'_summary'} = $record->{'title'} . " | " . ($record->{'author'} ? $record->{'author'} : 'N/A'); + $label_summary->{'_item_type'} = $record->{'itemtype'}; + $label_summary->{'_barcode'} = $record->{'barcode'}; + $label_summary->{'_item_number'} = $item->{'item_number'}; + $label_summary->{'_label_id'} = $item->{'label_id'}; + push (@label_summaries, $label_summary); + } + return \@label_summaries; +} + +=head2 C4::Labels::Lib::get_barcode_types() + + This function returns a reference to an array of hashes containing all barcode types along with their name and description. + + examples: + + my $barcode_types = get_barcode_types(); + +=cut + +sub get_barcode_types { + return $barcode_types; +} + +=head2 C4::Labels::Lib::get_label_types() + + This function returns a reference to an array of hashes containing all label types along with their name and description. + + examples: + + my $label_types = get_label_types(); + +=cut + +sub get_label_types { + return $label_types; +} + +=head2 C4::Labels::Lib::get_font_types() + + This function returns a reference to an array of hashes containing all font types along with their name and description. + + examples: + + my $font_types = get_font_types(); + +=cut + +sub get_font_types { + return $font_types; +} + +=head2 C4::Labels::Lib::get_text_justification_types() + + This function returns a reference to an array of hashes containing all text justification types along with their name and description. + + examples: + + my $text_justification_types = get_text_justification_types(); + +=cut + +sub get_text_justification_types { + return $text_justification_types; +} + +=head2 C4::Labels::Lib::get_unit_values() + + This function returns a reference to an array of hashes containing all unit types along with their description and multiplier. NOTE: All units are relative to a PostScript Point. + There are 72 PS points to the inch. + + examples: + + my $unit_values = get_unit_values(); + +=cut + +sub get_unit_values { + return $unit_values; +} + +=head2 C4::Labels::Lib::get_label_output_formats() + + This function returns a reference to an array of hashes containing all label output formats along with their description. + + examples: + + my $label_output_formats = get_label_output_formats(); + +=cut + +sub get_label_output_formats { + return $label_output_formats; +} + +=head2 C4::Labels::Lib::get_column_names($table_name) + +Return an arrayref of an array containing the column names of the supplied table. + +=cut + +sub get_column_names { + my $table = shift; + my $dbh = C4::Context->dbh(); + my $column_names = []; + my $sth = $dbh->column_info(undef,undef,$table,'%'); + while (my $info = $sth->fetchrow_hashref()){ + $$column_names[$info->{'ORDINAL_POSITION'}] = $info->{'COLUMN_NAME'}; + } + return $column_names; +} + +=head2 C4::Labels::Lib::get_table_names($search_term) + +Return an arrayref of an array containing the table names which contain the supplied search term. + +=cut + +sub get_table_names { + my $search_term = shift; + my $dbh = C4::Context->dbh(); + my $table_names = []; + my $sth = $dbh->table_info(undef,undef,"%$search_term%"); + while (my $info = $sth->fetchrow_hashref()){ + push (@$table_names, $info->{'TABLE_NAME'}); + } + return $table_names; +} + +=head2 C4::Labels::Lib::html_table() + + This function returns an arrayref of an array of hashes contianing the supplied data formatted suitably to + be passed off as a T::P template parameter and used to build an html table. + + examples: + + my $table = html_table(header_fields, array_of_row_data); + +=cut + +sub html_table { + my $headers = shift; + my $data = shift; + return undef if scalar(@$data) == 0; # no need to generate a table if there is not data to display + my $table = []; + my $fields = []; + my @headers = (); + my @table_columns = (); + my ($row_index, $col_index) = (0,0); + my $cols = 0; # number of columns to wrap on + my $field_count = 0; + my $select_value = undef; + my $link_field = undef; + POPULATE_HEADER: + foreach my $header (@$headers) { + my @key = keys %$header; + if ($key[0] eq 'select' ) { + push (@table_columns, $key[0]); + $$fields[$col_index] = {hidden => 0, select_field => 0, field_name => ($key[0]), field_label => $header->{$key[0]}{'label'}}; + # do special formatting stuff.... + $select_value = $header->{$key[0]}{'value'}; + } + else { + # do special formatting stuff.... + $link_field->{$key[0]} = ($header->{$key[0]}{'link_field'} == 1 ? 1 : 0); + push (@table_columns, $key[0]); + $$fields[$col_index] = {hidden => 0, select_field => 0, field_name => ($key[0]), field_label => $header->{$key[0]}{'label'}}; + } + $field_count++; + $col_index++; + } + $$table[$row_index] = {header_fields => $fields}; + $cols = $col_index; + $field_count *= scalar(@$data); # total fields to be displayed in the table + $col_index = 0; + $row_index++; + $fields = []; + POPULATE_TABLE: + foreach my $db_row (@$data) { + POPULATE_ROW: + foreach my $table_column (@table_columns) { + if (grep {$table_column eq $_} keys %$db_row) { + $$fields[$col_index] = {hidden => 0, link_field => $link_field->{$table_column}, select_field => 0, field_name => ($table_column . "_tbl"), field_value => $db_row->{$table_column}}; + $col_index++; + next POPULATE_ROW; + } + elsif ($table_column =~ m/^_((.*)_(.*$))/) { # this a special case + my $table_name = get_table_names($2); + my $record_set = _SELECT($1, @$table_name[0], $2 . "_id = " . $db_row->{$2 . "_id"}); + $$fields[$col_index] = {hidden => 0, link_field => $link_field->{$table_column}, select_field => 0, field_name => ($table_column . "_tbl"), field_value => $$record_set[0]{$1}}; + $col_index++; + next POPULATE_ROW; + } + elsif ($table_column eq 'select' ) { + $$fields[$col_index] = {hidden => 0, select_field => 1, field_name => 'select', field_value => $db_row->{$select_value}}; + } + } + $$table[$row_index] = {text_fields => $fields}; + $col_index = 0; + $row_index++; + $fields = []; + } + return $table; +} + +1; +__END__ + +=head1 AUTHOR + +Chris Nighswonger + +=cut diff --git a/C4/Labels/PDF.pm b/C4/Labels/PDF.pm new file mode 100644 index 0000000000..b661d45046 --- /dev/null +++ b/C4/Labels/PDF.pm @@ -0,0 +1,291 @@ +package C4::Labels::PDF; + +# Copyright 2009 Foundations Bible College. +# +# This file is part of Koha. +# +# Koha is free software; you can redistribute it and/or modify it under the +# terms of the GNU General Public License as published by the Free Software +# Foundation; either version 2 of the License, or (at your option) any later +# version. +# +# Koha is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along with +# Koha; if not, write to the Free Software Foundation, Inc., 59 Temple Place, +# Suite 330, Boston, MA 02111-1307 USA + +use strict; +use warnings; +use PDF::Reuse; +use PDF::Reuse::Barcode; + +BEGIN { + use version; our $VERSION = qv('1.0.0_1'); +} + +sub _InitVars { + my $self = shift; + my $param = shift; + prInitVars($param); +} + +sub new { + my $invocant = shift; + my $type = ref($invocant) || $invocant; + my %opts = @_; + my $self = {}; + _InitVars() if ($opts{InitVars} == 0); + _InitVars($opts{InitVars}) if ($opts{InitVars} > 0); + delete($opts{InitVars}); + prDocDir($opts{'DocDir'}) if $opts{'DocDir'}; + delete($opts{'DocDir'}); + prFile(%opts); + bless ($self, $type); + return $self; +} + +sub End { + my $self = shift; + prEnd(); +} + +sub Add { + my $self = shift; + my $string = shift; + prAdd($string); +} + +sub Bookmark { + my $self = shift; + my $reference = shift; + prBookmark($reference); +} + +sub Compress { + my $self = shift; + my $directive = shift; + prCompress($directive); +} + +sub Doc { + my $self = shift; + my %params = @_; + prDoc(%params); +} + +sub DocForm { + my $self = shift; + my %params = @_; + return prDocForm(%params); +} + +sub Extract { + my $self = shift; + my ($pdfFile, $pageNo, $oldInternalName) = @_; + return prExtract($pdfFile, $pageNo, $oldInternalName); +} + +sub Field { + my $self = shift; + my ($fieldName, $value) = @_; + prField($fieldName, $value); +} + +sub Font { + my $self = shift; + my $fontName = shift; + return prFont($fontName); +} + +sub FontSize { + my $self = shift; + my $size = shift; + return prFontSize($size); +} + +sub Form { + my $self = shift; + my %params = @_; + return prForm(%params); +} + +sub GetLogBuffer { + my $self = shift; + return prGetLogBuffer(); +} + +sub GraphState { + my $self = shift; + my $string = shift; + prGraphState($string); +} + +sub Image { + my $self = shift; + my %params = @_; + return prImage(%params); +} + +sub Init { + my $self = shift; + my ($string, $duplicateCode) = @_; + prInit($string, $duplicateCode); +} + +sub Jpeg { + my $self = shift; + my ($imageFile, $width, $height) = @_; + return prJpeg($imageFile, $width, $height); +} + +sub Js { + my $self = shift; + my $string_or_fileName = shift; + prJs($string_or_fileName); +} + +sub Link { + my $self = shift; + my %params = @_; + prLink(%params); +} + +sub Log { + my $self = shift; + my $string = shift; + prLog($string); +} + +sub LogDir { + my $self = shift; + my $directory = shift; + prLogDir($directory); +} + +sub Mbox { + my $self = shift; + my ($lowerLeftX, $lowerLeftY, $upperRightX, $upperRightY) = @_; + prMbox($lowerLeftX, $lowerLeftY, $upperRightX, $upperRightY); +} + +sub Page { + my $self = shift; + my $noLog = shift; + prPage($noLog); +} + +sub SinglePage { + my $self = shift; + my ($file, $pageNumber) = @_; + return prSinglePage($file, $pageNumber); +} + +sub StrWidth { + my $self = shift; + my ($string, $font, $fontSize) = @_; + return prStrWidth($string, $font, $fontSize); +} + +sub Text { + my $self = shift; + my ($x, $y, $string, $align, $rotation) = @_; + return prText($x, $y, $string, $align, $rotation); +} + +sub TTFont { + my $self = shift; + my $path = shift; + return prTTFont($path); +} + +sub Code128 { + my $self = shift; + my %opts = @_; + PDF::Reuse::Barcode::Code128(%opts); +} + +sub Code39 { + my $self = shift; + my %opts = @_; + PDF::Reuse::Barcode::Code39(%opts); +} + +sub COOP2of5 { + my $self = shift; + my %opts = @_; + PDF::Reuse::Barcode::COOP2of5(%opts); +} + +sub EAN13 { + my $self = shift; + my %opts = @_; + PDF::Reuse::Barcode::EAN13(%opts); +} + +sub EAN8 { + my $self = shift; + my %opts = @_; + PDF::Reuse::Barcode::EAN8(%opts); +} + +sub IATA2of5 { + my $self = shift; + my %opts = @_; + PDF::Reuse::Barcode::IATA2of5(%opts); +} + +sub Industrial2of5 { + my $self = shift; + my %opts = @_; + PDF::Reuse::Barcode::Industrial2of5(%opts); +} + +sub ITF { + my $self = shift; + my %opts = @_; + PDF::Reuse::Barcode::ITF(%opts); +} + +sub Matrix2of5 { + my $self = shift; + my %opts = @_; + PDF::Reuse::Barcode::Matrix2of5(%opts); +} + +sub NW7 { + my $self = shift; + my %opts = @_; + PDF::Reuse::Barcode::NW7(%opts); +} + +sub UPCA { + my $self = shift; + my %opts = @_; + PDF::Reuse::Barcode::UPCA(%opts); +} + +sub UPCE { + my $self = shift; + my %opts = @_; + PDF::Reuse::Barcode::UPCE(%opts); +} + +1; +__END__ + + +=head1 NAME + +C4::Labels::PDF - A class wrapper for PDF::Reuse and PDF::Reuse::Barcode to allow usage as a psuedo-object. For usage see + PDF::Reuse documentation and C4::Labels::PDF code. + +=cut + +=head1 AUTHOR + +Chris Nighswonger + +=cut diff --git a/C4/Labels/Profile.pm b/C4/Labels/Profile.pm new file mode 100644 index 0000000000..5cc4f73037 --- /dev/null +++ b/C4/Labels/Profile.pm @@ -0,0 +1,355 @@ +package C4::Labels::Profile; + +use strict; +use warnings; + +use C4::Context; +use C4::Debug; +use C4::Labels::Lib 1.000000 qw(get_unit_values); + +BEGIN { + use version; our $VERSION = qv('1.0.0_1'); +} + +sub _check_params { + my $given_params = {}; + my $exit_code = 0; + my @valid_profile_params = ( + 'printer_name', + 'template_id', + 'paper_bin', + 'offset_horz', + 'offset_vert', + 'creep_horz', + 'creep_vert', + 'units', + ); + if (scalar(@_) >1) { + $given_params = {@_}; + foreach my $key (keys %{$given_params}) { + if (!(grep m/$key/, @valid_profile_params)) { + warn sprintf('Unrecognized parameter type of "%s".', $key); + $exit_code = 1; + } + } + } + else { + if (!(grep m/$_/, @valid_profile_params)) { + warn sprintf('Unrecognized parameter type of "%s".', $_); + $exit_code = 1; + } + } + return $exit_code; +} + +sub _conv_points { + my $self = shift; + my @unit_value = grep {$_->{'type'} eq $self->{units}} @{get_unit_values()}; + $self->{offset_horz} = $self->{offset_horz} * $unit_value[0]->{'value'}; + $self->{offset_vert} = $self->{offset_vert} * $unit_value[0]->{'value'}; + $self->{creep_horz} = $self->{creep_horz} * $unit_value[0]->{'value'}; + $self->{creep_vert} = $self->{creep_vert} * $unit_value[0]->{'value'}; + return $self; +} + +sub new { + my $invocant = shift; + if (_check_params(@_) eq 1) { + return -1; + } + my $type = ref($invocant) || $invocant; + my $self = { + printer_name => 'Default Printer', + template_id => '', + paper_bin => 'Tray 1', + offset_horz => 0, + offset_vert => 0, + creep_horz => 0, + creep_vert => 0, + units => 'POINT', + @_, + }; + bless ($self, $type); + return $self; +} + +sub retrieve { + my $invocant = shift; + my %opts = @_; + my $type = ref($invocant) || $invocant; + my $query = "SELECT * FROM printers_profile WHERE profile_id = ?"; + my $sth = C4::Context->dbh->prepare($query); + $sth->execute($opts{profile_id}); + if ($sth->err) { + warn sprintf('Database returned the following error: %s', $sth->errstr); + return -1; + } + my $self = $sth->fetchrow_hashref; + $self = _conv_points($self) if ($opts{convert} && $opts{convert} == 1); + bless ($self, $type); + return $self; +} + +sub delete { + my $self = {}; + my %opts = (); + my $call_type = ''; + my $query_param = ''; + if (ref($_[0])) { + $self = shift; # check to see if this is a method call + $call_type = 'C4::Labels::Profile->delete'; + $query_param = $self->{'profile_id'}; + } + else { + %opts = @_; + $call_type = 'C4::Labels::Profile::delete'; + $query_param = $opts{'profile_id'}; + } + if ($query_param eq '') { # If there is no profile id then we cannot delete it + warn sprintf('%s : Cannot delete layout as the profile id is invalid or non-existant.', $call_type); + return -1; + } + my $query = "DELETE FROM printers_profile WHERE profile_id = ?"; + my $sth = C4::Context->dbh->prepare($query); +# $sth->{'TraceLevel'} = 3; + $sth->execute($query_param); +} + +sub save { + my $self = shift; + if ($self->{'profile_id'}) { # if we have an profile_id, the record exists and needs UPDATE + my @params; + my $query = "UPDATE printers_profile SET "; + foreach my $key (keys %{$self}) { + next if $key eq 'profile_id'; + push (@params, $self->{$key}); + $query .= "$key=?, "; + } + $query = substr($query, 0, (length($query)-2)); + push (@params, $self->{'profile_id'}); + $query .= " WHERE profile_id=?;"; + my $sth = C4::Context->dbh->prepare($query); +# $sth->{'TraceLevel'} = 3; + $sth->execute(@params); + if ($sth->err) { + warn sprintf('Database returned the following error on attempted UPDATE: %s', $sth->errstr); + return -1; + } + return $self->{'profile_id'}; + } + else { # otherwise create a new record + my @params; + my $query = "INSERT INTO printers_profile ("; + foreach my $key (keys %{$self}) { + push (@params, $self->{$key}); + $query .= "$key, "; + } + $query = substr($query, 0, (length($query)-2)); + $query .= ") VALUES ("; + for (my $i=1; $i<=(scalar keys %$self); $i++) { + $query .= "?,"; + } + $query = substr($query, 0, (length($query)-1)); + $query .= ");"; + my $sth = C4::Context->dbh->prepare($query); + $sth->execute(@params); + if ($sth->err) { + warn sprintf('Database returned the following error on attempted INSERT: %s', $sth->errstr); + return -1; + } + my $sth1 = C4::Context->dbh->prepare("SELECT MAX(profile_id) FROM printers_profile;"); + $sth1->execute(); + my $tmpl_id = $sth1->fetchrow_array; + return $tmpl_id; + } +} + +sub get_attr { + my $self = shift; + if (_check_params(@_) eq 1) { + return -1; + } + my ($attr) = @_; + if (exists($self->{$attr})) { + return $self->{$attr}; + } + else { + warn sprintf('%s is currently undefined.', $attr); + return -1; + } +} + +sub set_attr { + my $self = shift; + if (_check_params(@_) eq 1) { + return -1; + } + my %attrs = @_; + foreach my $attrib (keys(%attrs)) { + $self->{$attrib} = $attrs{$attrib}; + }; + return 0; +} + +1; +__END__ + +=head1 NAME + +C4::Labels::Profile - A class for creating and manipulating profile objects in Koha + +=head1 ABSTRACT + +This module provides methods for creating, retrieving, and otherwise manipulating label profile objects used by Koha to create and export labels. + +=head1 METHODS + +=head2 new() + + Invoking the I method constructs a new profile object containing the default values for a template. + The following parameters are optionally accepted as key => value pairs: + + C The name of the printer to which this profile applies. + C The template to which this profile may be applied. NOTE: There may be multiple profiles which may be applied to the same template. + C The paper bin of the above printer to which this profile applies. NOTE: printer name, template id, and paper bin must form a unique combination. + C Amount of compensation for horizontal offset (position of text on a single label). This amount is measured in the units supplied by the units parameter in this profile. + C Amount of compensation for vertical offset. + C Amount of compensation for horizontal creep (tendency of text to 'creep' off of the labels over the span of the entire page). + C Amount of compensation for vertical creep. + C The units of measure used for this template. These B match the measures you supply above or + bad things will happen to your document. NOTE: The only supported units at present are: + +=over 9 + +=item . +POINT = Postscript Points (This is the base unit in the Koha label creator.) + +=item . +AGATE = Adobe Agates (5.1428571 points per) + +=item . +INCH = US Inches (72 points per) + +=item . +MM = SI Millimeters (2.83464567 points per) + +=item . +CM = SI Centimeters (28.3464567 points per) + +=back + + example: + Cnew(); # Creates and returns a new profile object> + + Cnew(template_id => 1, paper_bin => 'Bypass Tray', offset_horz => 0.02, units => 'POINT'); # Creates and returns a new profile object using + the supplied values to override the defaults> + + B This profile is I written to the database until save() is invoked. You have been warned! + +=head2 retrieve(profile_id => $profile_id, convert => 1) + + Invoking the I method constructs a new profile object containing the current values for profile_id. The method returns a new object upon success and 1 upon failure. + Errors are logged to the Apache log. One further option maybe accessed. See the examples below for further description. + + examples: + + Cretrieve(profile_id => 1); # Retrieves profile record 1 and returns an object containing the record> + + Cretrieve(profile_id => 1, convert => 1); # Retrieves profile record 1, converts the units to points and returns an object containing the record> + +=head2 delete() + + Invoking the delete method attempts to delete the profile from the database. The method returns -1 upon failure. Errors are logged to the Apache log. + NOTE: This method may also be called as a function and passed a key/value pair simply deleteing that profile from the database. See the example below. + + examples: + Cdelete(); # to delete the record behind the $profile object> + C 1); # to delete profile record 1> + +=head2 save() + + Invoking the I method attempts to insert the profile into the database if the profile is new and update the existing profile record if the profile exists. The method returns + the new record profile_id upon success and -1 upon failure (This avoids conflicting with a record profile_id of 1). Errors are logged to the Apache log. + + example: + Csave(); # to save the record behind the $profile object> + +=head2 get_attr($attribute) + + Invoking the I method will return the value of the requested attribute or -1 on errors. + + example: + Cget_attr($attribute);> + +=head2 set_attr(attribute => value, attribute_2 => value) + + Invoking the I method will set the value of the supplied attributes to the supplied values. The method accepts key/value pairs separated by commas. + + example: + $profile->set_attr(attribute => value); + +=head1 AUTHOR + +Chris Nighswonger + +=head1 COPYRIGHT + +Copyright 2009 Foundations Bible College. + +=head1 LICENSE + +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. + +You should have received a copy of the GNU General Public License along with Koha; if not, write to the Free Software Foundation, Inc., 59 Temple Place, +Suite 330, Boston, MA 02111-1307 USA + +=head1 DISCLAIMER OF WARRANTY + +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. + +=cut + +#=head1 +#drawbox( ($left_margin), ($top_margin), ($page_width-(2*$left_margin)), ($page_height-(2*$top_margin)) ); # FIXME: Breakout code to print alignment page for printer profile setup +# +#=head2 draw_boundaries +# +# sub draw_boundaries ($llx_spine, $llx_circ1, $llx_circ2, +# $lly, $spine_width, $label_height, $circ_width) +# +#This sub draws boundary lines where the label outlines are, to aid in printer testing, and debugging. +# +#=cut +# +## FIXME: Template use for profile adjustment... +##sub draw_boundaries { +## +## my ( +## $llx_spine, $llx_circ1, $llx_circ2, $lly, +## $spine_width, $label_height, $circ_width +## ) = @_; +## +## my $lly_initial = ( ( 792 - 36 ) - 90 ); +## $lly = $lly_initial; # FIXME - why are we ignoring the y_pos parameter by redefining it? +## my $i = 1; +## +## for ( $i = 1 ; $i <= 8 ; $i++ ) { +## +## _draw_box( $llx_spine, $lly, ($spine_width), ($label_height) ); +## +## #warn "OLD BOXES x=$llx_spine, y=$lly, w=$spine_width, h=$label_height"; +## _draw_box( $llx_circ1, $lly, ($circ_width), ($label_height) ); +## _draw_box( $llx_circ2, $lly, ($circ_width), ($label_height) ); +## +## $lly = ( $lly - $label_height ); +## +## } +##} +# +# +# +#=cut diff --git a/C4/Labels/Template.pm b/C4/Labels/Template.pm new file mode 100644 index 0000000000..61751f95c0 --- /dev/null +++ b/C4/Labels/Template.pm @@ -0,0 +1,396 @@ +package C4::Labels::Template; + +use strict; +use warnings; +use PDF::Reuse; +use POSIX qw(ceil); + +use C4::Context; +use C4::Debug; +use C4::Labels::Profile 1.000000; +use C4::Labels::PDF 1.000000; +use C4::Labels::Lib 1.000000 qw(get_unit_values); + +BEGIN { + use version; our $VERSION = qv('1.0.0_1'); +} + +sub _check_params { + my $given_params = {}; + my $exit_code = 0; + my @valid_template_params = ( + 'profile_id', + 'template_code', + 'template_desc', + 'page_width', + 'page_height', + 'label_width', + 'label_height', + 'top_text_margin', + 'left_text_margin', + 'top_margin', + 'left_margin', + 'cols', + 'rows', + 'col_gap', + 'row_gap', + 'units', + ); + if (scalar(@_) >1) { + $given_params = {@_}; + foreach my $key (keys %{$given_params}) { + if (!(grep m/$key/, @valid_template_params)) { + warn sprintf('Unrecognized parameter type of "%s".', $key); + $exit_code = 1; + } + } + } + else { + if (!(grep m/$_/, @valid_template_params)) { + warn sprintf('Unrecognized parameter type of "%s".', $_); + $exit_code = 1; + } + } + return $exit_code; +} + +sub _conv_points { + my $self = shift; + my @unit_value = grep {$_->{'type'} eq $self->{'units'}} @{get_unit_values()}; + $self->{'page_width'} = $self->{'page_width'} * $unit_value[0]->{'value'}; + $self->{'page_height'} = $self->{'page_height'} * $unit_value[0]->{'value'}; + $self->{'label_width'} = $self->{'label_width'} * $unit_value[0]->{'value'}; + $self->{'label_height'} = $self->{'label_height'} * $unit_value[0]->{'value'}; + $self->{'top_text_margin'} = $self->{'top_text_margin'} * $unit_value[0]->{'value'}; + $self->{'left_text_margin'} = $self->{'left_text_margin'} * $unit_value[0]->{'value'}; + $self->{'top_margin'} = $self->{'top_margin'} * $unit_value[0]->{'value'}; + $self->{'left_margin'} = $self->{'left_margin'} * $unit_value[0]->{'value'}; + $self->{'col_gap'} = $self->{'col_gap'} * $unit_value[0]->{'value'}; + $self->{'row_gap'} = $self->{'row_gap'} * $unit_value[0]->{'value'}; + return $self; +} + +sub _apply_profile { + my $self = shift; + my $profile = C4::Labels::Profile->retrieve(profile_id => $self->{'profile_id'}, convert => 1); + $self->{'top_margin'} = $self->{'top_margin'} + $profile->get_attr('offset_vert'); # controls vertical offset + $self->{'left_margin'} = $self->{'left_margin'} + $profile->get_attr('offset_horz'); # controls horizontal offset + $self->{'label_height'} = $self->{'label_height'} + $profile->get_attr('creep_vert'); # controls vertical creep + $self->{'label_width'} = $self->{'label_width'} + $profile->get_attr('creep_horz'); # controls horizontal creep + return $self; +} + +sub new { + my $invocant = shift; + if (_check_params(@_) eq 1) { + return -1; + } + my $type = ref($invocant) || $invocant; + my $self = { + profile_id => '0', + template_code => 'DEFAULT TEMPLATE', + template_desc => 'Default description', + page_width => 0, + page_height => 0, + label_width => 0, + label_height => 0, + top_text_margin => 0, + left_text_margin => 0, + top_margin => 0, + left_margin => 0, + cols => 0, + rows => 0, + col_gap => 0, + row_gap => 0, + units => 'POINT', + template_stat => 0, # false if any data has changed and the db has not been updated + @_, + }; + bless ($self, $type); + return $self; +} + +sub retrieve { + my $invocant = shift; + my %opts = @_; + my $type = ref($invocant) || $invocant; + my $query = "SELECT * FROM labels_templates WHERE template_id = ?"; + my $sth = C4::Context->dbh->prepare($query); + $sth->execute($opts{template_id}); + if ($sth->err) { + warn sprintf('Database returned the following error: %s', $sth->errstr); + return -1; + } + my $self = $sth->fetchrow_hashref; + $self = _conv_points($self) if (($opts{convert} && $opts{convert} == 1) || $opts{profile_id}); + $self = _apply_profile($self) if $opts{profile_id} && $self->{'profile_id'}; # don't bother if there is no profile_id + $self->{'template_stat'} = 1; + bless ($self, $type); + return $self; +} + +sub delete { + my $self = {}; + my %opts = (); + my $call_type = ''; + my $query_param = ''; + if (ref($_[0])) { + $self = shift; # check to see if this is a method call + $call_type = 'C4::Labels::Template->delete'; + $query_param = $self->{'template_id'}; + } + else { + %opts = @_; + $call_type = 'C4::Labels::Template::delete'; + $query_param = $opts{'template_id'}; + } + if ($query_param eq '') { # If there is no template id then we cannot delete it + warn sprintf('%s : Cannot delete layout as the template id is invalid or non-existant.', $call_type); + return -1; + } + my $query = "DELETE FROM labels_templates WHERE template_id = ?"; + my $sth = C4::Context->dbh->prepare($query); + $sth->execute($query_param); + $self->{'template_stat'} = 0; +} + +sub save { + my $self = shift; + if ($self->{'template_id'}) { # if we have an template_id, the record exists and needs UPDATE + my @params; + my $query = "UPDATE labels_templates SET "; + foreach my $key (keys %{$self}) { + next if ($key eq 'template_id') || ($key eq 'template_stat'); + push (@params, $self->{$key}); + $query .= "$key=?, "; + } + $query = substr($query, 0, (length($query)-2)); + push (@params, $self->{'template_id'}); + $query .= " WHERE template_id=?;"; + my $sth = C4::Context->dbh->prepare($query); + $sth->execute(@params); + if ($sth->err) { + warn sprintf('Database returned the following error: %s', $sth->errstr); + return -1; + } + $self->{'template_stat'} = 1; + return $self->{'template_id'}; + } + else { # otherwise create a new record + my @params; + my $query = "INSERT INTO labels_templates ("; + foreach my $key (keys %{$self}) { + next if $key eq 'template_stat'; + push (@params, $self->{$key}); + $query .= "$key, "; + } + $query = substr($query, 0, (length($query)-2)); + $query .= ") VALUES ("; + for (my $i=1; $i<=((scalar keys %$self) - 1); $i++) { # key count less keys not db related... + $query .= "?,"; + } + $query = substr($query, 0, (length($query)-1)); + $query .= ");"; + my $sth = C4::Context->dbh->prepare($query); + $sth->execute(@params); + if ($sth->err) { + warn sprintf('Database returned the following error: %s', $sth->errstr); + return -1; + } + my $sth1 = C4::Context->dbh->prepare("SELECT MAX(template_id) FROM labels_templates;"); + $sth1->execute(); + my $template_id = $sth1->fetchrow_array; + $self->{'template_id'} = $template_id; + $self->{'template_stat'} = 1; + return $template_id; + } +} + +sub get_attr { + my $self = shift; + if (_check_params(@_) eq 1) { + return -1; + } + my ($attr) = @_; + if (exists($self->{$attr})) { + return $self->{$attr}; + } + else { + return -1; + } +} + +sub set_attr { + my $self = shift; + if (_check_params(@_) eq 1) { + return -1; + } + my %attrs = @_; + foreach my $attrib (keys(%attrs)) { + $self->{$attrib} = $attrs{$attrib}; + }; +} + +sub get_label_position { + my ($self, $start_label) = @_; + my ($row_count, $col_count, $llx, $lly) = 0,0,0,0; + if ($start_label eq 1) { + $row_count = 1; + $col_count = 1; + $llx = $self->{'left_margin'}; + $lly = ($self->{'page_height'} - $self->{'top_margin'} - $self->{'label_height'}); + return ($row_count, $col_count, $llx, $lly); + } + else { + $row_count = ceil($start_label / $self->{'cols'}); + $col_count = ($start_label - (($row_count - 1) * $self->{'cols'})); + $llx = $self->{'left_margin'} + ($self->{'label_width'} * ($col_count - 1)) + ($self->{'col_gap'} * ($col_count - 1)); + $lly = $self->{'page_height'} - $self->{'top_margin'} - ($self->{'label_height'} * $row_count) - ($self->{'row_gap'} * ($row_count - 1)); + return ($row_count, $col_count, $llx, $lly); + } +} + +1; +__END__ + +=head1 NAME + +C4::Labels::Template - A class for creating and manipulating template objects in Koha + +=head1 ABSTRACT + +This module provides methods for creating, retrieving, and otherwise manipulating label template objects used by Koha to create and export labels. + +=head1 METHODS + +=head2 new() + + Invoking the I method constructs a new template object containing the default values for a template. + The following parameters are optionally accepted as key => value pairs: + + C A valid profile id to be assciated with this template. NOTE: The profile must exist in the database and B be assigned to another template. + C A template code. ie. 'Avery 5160 | 1 x 2-5/8' + C A readable description of the template. ie. '3 columns, 10 rows of labels' + C The width of the page measured in the units supplied by the units parameter in this template. + C The height of the page measured in the same units. + C The width of a single label on the page this template applies to. + C The height of a single label on the page. + C The measure of the top margin on a single label on the page. + C The measure of the left margin on a single label on the page. + C The measure of the top margin of the page. + C The measure of the left margin of the page. + C The number of columns of labels on the page. + C The number of rows of labels on the page. + C The measure of the gap between the columns of labels on the page. + C The measure of the gap between the rows of labels on the page. + C The units of measure used for this template. These B match the measures you supply above or + bad things will happen to your document. NOTE: The only supported units at present are: + +=over 9 + +=item . +POINT = Postscript Points (This is the base unit in the Koha label creator.) + +=item . +AGATE = Adobe Agates (5.1428571 points per) + +=item . +INCH = US Inches (72 points per) + +=item . +MM = SI Millimeters (2.83464567 points per) + +=item . +CM = SI Centimeters (28.3464567 points per) + +=back + + example: + my $template = Template->new(); # Creates and returns a new template object with the defaults + + my $template = C4::Labels::Template->new(profile_id => 1, page_width => 8.5, page_height => 11.0, units => 'INCH'); # Creates and returns a new template object using + the supplied values to override the defaults + + B This template is I written to the database untill save() is invoked. You have been warned! + +=head2 retrieve(template_id => $template_id) + + Invoking the I method constructs a new template object containing the current values for template_id. The method returns + a new object upon success and -1 upon failure. Errors are logged to the Apache log. Two further options may be accessed. See the example + below for further description. + + examples: + + Cretrieve(template_id => 1); # Retrieves template record 1 and returns an object containing the record> + + Cretrieve(template_id => 1, convert => 1); # Retrieves template record 1, converts the units to points, + and returns an object containing the record> + + Cretrieve(template_id => 1, profile_id => 1); # Retrieves template record 1, converts the units + to points, applies the currently associated profile id, and returns an object containing the record.> + +=head2 delete() + + Invoking the delete method attempts to delete the template from the database. The method returns -1 upon failure. Errors are logged to the Apache log. + NOTE: This method may also be called as a function and passed a key/value pair simply deleteing that template from the database. See the example below. + + examples: + Cdelete(); # to delete the record behind the $template object> + C 1); # to delete template record 1> + +=head2 save() + + Invoking the I method attempts to insert the template into the database if the template is new and update the existing template record if + the template exists. The method returns the new record template_id upon success and -1 upon failure (This avoids template_ids conflicting with a + record template_id of 1). Errors are logged to the Apache log. + + example: + Csave(); # to save the record behind the $template object> + +=head2 get_attr($attribute) + + Invoking the I method will return the value of the requested attribute or -1 on errors. + + example: + Cget_attr($attribute);> + +=head2 set_attr(attribute => value, attribute_2 => value) + + Invoking the I method will set the value of the supplied attributes to the supplied values. The method accepts key/value pairs separated by + commas. + + example: + C<$template->set_attr(attribute => value);> + +=head2 get_label_position($start_label) + + Invoking the I method will return the row, column coordinates on the starting page and the lower left x,y coordinates on the starting + label for the template object. + + examples: + Cget_label_position($start_label);> + +=head1 AUTHOR + +Chris Nighswonger + +=head1 COPYRIGHT + +Copyright 2009 Foundations Bible College. + +=head1 LICENSE + +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. + +You should have received a copy of the GNU General Public License along with Koha; if not, write to the Free Software Foundation, Inc., 59 Temple Place, +Suite 330, Boston, MA 02111-1307 USA + +=head1 DISCLAIMER OF WARRANTY + +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. + +=cut diff --git a/C4/Patroncards/Patroncards.pm b/C4/Patroncards/Patroncards.pm new file mode 100644 index 0000000000..e3cf150694 --- /dev/null +++ b/C4/Patroncards/Patroncards.pm @@ -0,0 +1,292 @@ +package C4::Labels::Patroncard; + +# Copyright 2009 Foundations Bible College. +# +# This file is part of Koha. +# +# Koha is free software; you can redistribute it and/or modify it under the +# terms of the GNU General Public License as published by the Free Software +# Foundation; either version 2 of the License, or (at your option) any later +# version. +# +# Koha is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along with +# Koha; if not, write to the Free Software Foundation, Inc., 59 Temple Place, +# Suite 330, Boston, MA 02111-1307 USA + +use strict; +use warnings; + +use C4::Context; +use C4::Debug; +use C4::Biblio; +use C4::Labels::Layout 1.000000; # use version 1.0.0 or better +use C4::Labels::Template 1.000000; +use Data::Dumper; + +BEGIN { + use version; our $VERSION = qv('1.0.0_1'); +} + +sub _check_params { + my $given_params = {}; + my $exit_code = 0; + my @valid_template_params = ( + 'layout_id', + 'tmpl_id', + 'prof_id', + ); + if (scalar(@_) >1) { + $given_params = {@_}; + foreach my $key (keys %{$given_params}) { + if (!(grep m/$key/, @valid_template_params)) { + warn sprintf('Unrecognized parameter type of "%s".', $key); + $exit_code = 1; + } + } + } + else { + if (!(grep m/$_/, @valid_template_params)) { + warn sprintf('Unrecognized parameter type of "%s".', $_); + $exit_code = 1; + } + } + return $exit_code; +} + +=head1 NAME + +C4::Labels::Batch - A class for creating and manipulating batch objects in Koha + +=cut + +=head1 METHODS + +=head2 C4::Labels::Batch->new(layout_id => layout_id, tmpl_id => template_id, prof_id => prof_id) + + Invoking the I method constructs a new batch object with no items. + + example: + my $batch = C4::Labels::Batch->new(layout_id => layout_id, tmpl_id => template_id, prof_id => prof_id); + # Creates and returns a new batch object + + B This batch is I written to the database untill $batch->save() is invoked. You have been warned! + +=cut + +sub new { + my ($invocant, %params) = @_; + my $type = ref($invocant) || $invocant; + my $self = { + batch_id => 0, + layout_id => $params{layout_id}, + tmpl_id => $params{tmpl_id}, + prof_id => $params{prof_id}, + items => [], + batch_stat => 0, # False if any data has changed and the db has not been updated + }; + bless ($self, $type); + return $self; +} + +=head2 $batch->add_item($item_number) + + Invoking the I method will add the supplied item to the batch object. + + example: + $batch->add_item($item_number); + +=cut + +sub add_item { + my $self = shift; + my $item_num = shift; + push (@{$self->{items}}, $item_num); + $self->{batch_stat} = 0; +} + +=head2 $batch->get_attr() + + Invoking the I method will return the requested attribute. + + example: + my @items = $batch->get_attr($attr); + +=cut + +sub get_attr { + my $self = shift; + return $self->{$_[0]}; +} + +=head2 $batch->delete_item() + + Invoking the I method will delete the supplied item from the batch object. + + example: + $batch->delete_item(); + +=cut + +sub delete_item { + my $self = shift; + my $item_num = shift; + my $index = 0; + ++$index until $$self->{items}[$index] == $item_num or $item_num > $#$self->{items}; + delete ($$self->{items}[$index]); + $self->{batch_stat} = 0; +} + +=head2 $batch->save() + + Invoking the I method attempts to insert the batch into the database if the batch is new and + update the existing batch record if the batch exists. The method returns the new record batch_id upon + success and -1 upon failure (This avoids conflicting with a record batch_id of 1). Errors are + logged to the Apache log. + + example: + my $exitstat = $batch->save(); # to save the record behind the $batch object + +=cut + +sub save { + my $self = shift; + if ($self->{batch_id} > 0) { + foreach my $item_number (@$self->{items}) { + my $query = "UPDATE labels_batches SET item_number=?, layout_id=?, tmpl_id=?, prof_id=? WHERE batch_id=?;"; + warn "DEBUG: Updating: $query\n" if $debug; + my $sth->C4::Context->dbh->prepare($query); + $sth->execute($item_number, $self->{layout_id}, $self->{tmpl_id}, $self->{prof_id}, $self->{batch_id}); + if ($sth->err) { + warn sprintf('Database returned the following error: %s', $sth->errstr); + return -1; + } + } + } + else { + foreach my $item_number (@$self->{items}) { + my $query = "INSERT INTO labels_batches (item_number, layout_id, tmpl_id, prof_id) VALUES (?,?,?,?);"; + warn "DEBUG: Inserting: $query\n" if $debug; + my $sth->C4::Context->dbh->prepare($query); + $sth->execute($item_number, $self->{layout_id}, $self->{tmpl_id}, $self->{prof_id}); + if ($sth->err) { + warn sprintf('Database returned the following error: %s', $sth->errstr); + return -1; + } + my $sth1 = C4::Context->dbh->prepare("SELECT MAX(batch_id) FROM labels_batches;"); + $sth1->execute(); + my $batch_id = $sth1->fetchrow_array; + $self->{batch_id} = $batch_id; + return $batch_id; + } + } + $self->{batch_stat} = 1; +} + +=head2 C4::Labels::Template->retrieve(template_id) + + Invoking the I method constructs a new template object containing the current values for template_id. The method returns + a new object upon success and 1 upon failure. Errors are logged to the Apache log. Two further options may be accessed. See the example + below for further description. + + examples: + + my $template = C4::Labels::Template->retrieve(template_id => 1); # Retrieves template record 1 and returns an object containing the record + + my $template = C4::Labels::Template->retrieve(template_id => 1, convert => 1); # Retrieves template record 1, converts the units to points, + and returns an object containing the record + + my $template = C4::Labels::Template->retrieve(template_id => 1, prof_id => prof_id); # Retrieves template record 1, converts the units + to points, applies the given profile id, and returns an object containing the record + +=cut + +sub retrieve { + my $invocant = shift; + my %opts = @_; + my $type = ref($invocant) || $invocant; + my $query = "SELECT * FROM labels_batches WHERE batch_id = ? ORDER BY label_id"; + my $sth = C4::Context->dbh->prepare($query); + $sth->execute($opts{batch_id}); + if ($sth->err) { + warn sprintf('Database returned the following error: %s', $sth->errstr); + return 1; + } + my $self = { + items => [], + }; + while (my $record = $sth->fetchrow_hashref) { + $self->{batch_id} = $record->{batch_id}; # FIXME: seems a bit wasteful to re-initialize these every trip: is there a better way? + $self->{layout_id} = $record->{layout_id}; + $self->{tmpl_id} = $record->{tmpl_id}; + $self->{prof_id} = $record->{prof_id}; + push (@{$self->{items}}, $record->{item_number}); + } + $self->{batch_stat} = 1; + bless ($self, $type); + return $self; +} + +=head2 C4::Labels::Batch->delete(batch_id => batch_id) | $batch->delete() + + Invoking the delete method attempts to delete the batch from the database. The method returns 0 upon success + and 1 upon failure. Errors are logged to the Apache log. + + examples: + my $exitstat = $batch->delete(); # to delete the record behind the $batch object + my $exitstat = C4::Labels::Batch->delete(batch_id => 1); # to delete batch record 1 + +=cut + +sub delete { + my $self = shift; + my %opts = @_; + if ((ref $self) && !$self->{'batch_id'}) { # If there is no batch batch_id then we cannot delete it from the db + warn 'Cannot delete batch: Batch has not been saved.'; + return 1; + } + elsif (!$opts{batch_id}) { + warn 'Cannot delete batch: Missing batch_id.'; + return 1; + } + my $query = "DELETE FROM labels_batches WHERE batch_id = ?"; + my $sth = C4::Context->dbh->prepare($query); + $sth->execute($self->{'batch_id'}); + return 0; +} + + +1; +__END__ + +=head1 AUTHOR + +Chris Nighswonger + +=cut + + +# +# elsif ( $label_type eq 'PATCRD' ) { +# my $patron_data = $item; +# +# #FIXME: This needs to be paramatized and passed in from the user... +# #Each element of this hash is a separate line on the patron card. Keys are the text to print and the associated data is the point size. +# my $text = { +# $patron_data->{'description'} => $template->get_attr('font_size'), +# $patron_data->{'branchname'} => ($template->get_attr('font_size') + 3), +# }; +# +# $debug and warn "Generating patron card for cardnumber $patron_data->{'cardnumber'}"; +# +# my $barcode_height = $label_height / 2.75; #FIXME: Scaling barcode height; this needs to be a user parameter. +# $label->barcode( $llx, $lly, $barcode_height, $label_width, $patron_data->{'cardnumber'}, +# $barcodetype ); +# DrawPatronCardText( $llx, $lly, $label_height, $label_width, $template->get_attr('font'), $template->get_attr('font_size'), +# $left_text_margin, $text_wrap_cols, $text, $label_type ); +# _calc_next_label_pos(); +# } + diff --git a/installer/data/mysql/en/optional/sample_labels.sql b/installer/data/mysql/en/optional/sample_labels.sql index 28702f8c50..c0fdd13942 100644 --- a/installer/data/mysql/en/optional/sample_labels.sql +++ b/installer/data/mysql/en/optional/sample_labels.sql @@ -1,25 +1,21 @@ -- Label Templates LOCK TABLES `labels_templates` WRITE; -INSERT INTO `labels_templates` -(tmpl_id,tmpl_code,tmpl_desc,page_width,page_height,label_width,label_height,topmargin,leftmargin,cols,`rows`,colgap,rowgap, -active,units,fontsize,font) -VALUES -(1,'Avery 5160 | 1 x 2-5/8','3 columns, 10 rows of labels',8.5,11,2.625,1,0.5,0.1875,3,10,0.125,0,1,'INCH',7,'TR'), -(2,'Gaylord 8511 Spine Label','Prints only the left-hand column of a Gaylord 8511.',8.5,11,1,1.25,0.6,0.5,1,8,0,0,NULL,'INCH',10,'TR'), -(3,'Avery 5460 vertical','',3.625,5.625,1.5,0.75,0.38,0.35,2,7,0.25,0,NULL,'INCH',8,'TR'), -(4,'Avery 5460 spine labels','',5.625,3.625,0.75,1.5,0.35,0.31,7,2,0,0.25,NULL,'INCH',8,'TR'), -(5,'Avery 8163','2rows x 5 rows',8.5,11,4,2,0.5,0.17,2,5,0.2,0.01,NULL,'INCH',11,'TR'), -(6,'cards','Avery 5160 | 1 x 2-5/8 : 1 x 2-5/8\" [3x10] : equivalent: Gaylord JD-ML3000',8.5,11,2.75,1.05,0.25,0,3,10,0.2,0.01,NULL,'INCH',8,'TR'), -(7,'HB-PC0001','A template for home brewed patron card forms',8.5,11,3.125,1.875,0.375,0.5625,2,5,1.125,0.1875,NULL,'INCH',16,'TR'); -UNLOCK TABLES; -LOCK TABLES `labels_conf` WRITE; -/*!40000 ALTER TABLE `labels_conf` DISABLE KEYS */; -INSERT INTO `labels_conf` -(id,barcodetype,title,subtitle,itemtype,barcode,dewey,classification,subclass,itemcallnumber,author,issn,isbn,startlabel, -printingtype,formatstring,layoutname,guidebox,active,fonttype,ccode,callnum_split) -VALUES -(5,'CODE39',2,0,3,0,0,0,0,4,1,0,0,1,'BIBBAR','biblio and barcode',1,1,NULL,NULL,NULL,NULL), -(6,'CODE39',2,0,0,0,0,3,4,0,1,0,3,1,'BAR','alternating',1,1,NULL,NULL,NULL,NULL), -(7,'CODE39',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,2,NULL,NULL,1,'PATCRD','Patron ID Cards',1,NULL,NULL,NULL,NULL,NULL); -/*!40000 ALTER TABLE `labels_conf` ENABLE KEYS */; +/*!40000 ALTER TABLE `labels_templates` DISABLE KEYS */; +INSERT INTO `labels_templates` VALUES +(1,0,'Avery 5160 | 1 x 2-5/8', '3 columns, 10 rows of labels', 8.5, 11, 2.63, 1, 0.139, 0, 0.35, 0.23, 3, 10, 0.13, 0, 'INCH'), +(2,0,'Gaylord 8511 Spine Label','Prints only the left-hand column of a Gaylord 8511.', 8.5, 11, 1, 1.25, 0.6, 0.5, 0, 0, 1, 8, 0, 0, 'INCH'), +(3,0,'Avery 5460 vertical', '', 3.625, 5.625, 1.5, 0.75, 0.38, 0.35, 2, 7, 2, 1, 0.25, 0, 'INCH'), +(4,0,'Avery 5460 spine labels', '', 5.625, 3.625, 0.75, 1.5, 0.35, 0.31, 7, 2, 1, 0, 0.25, 0, 'INCH'), +(5,0,'Avery 8163', '2rows x 5 rows', 8.5, 11, 4, 2, 0, 0, 0.5, 0.17, 2, 5, 0.2, 0.01, 'INCH'), +(6,0,'cards', 'Avery 5160 | 1 x 2-5/8 : 1 x 2-5/8\" [3x10] : equivalent: Gaylord JD-ML3000', 8.5, 11, 2.75, 1.05, 0, 0, 0.25, 0, 3, 10, 0.2, 0.01, 'INCH'), +(7,0,'Demco WS14942260', '1\" X 1.5\" Spine Label', 8.5, 11, 1.5, 1, 0.236, 0, 0.4, 0.25, 5, 10, 0.0625, 0, 'INCH'); +/*!40000 ALTER TABLE `labels_templates` ENABLE KEYS */; +UNLOCK TABLES; +LOCK TABLES `labels_layouts` WRITE; +/*!40000 ALTER TABLE `labels_layouts` DISABLE KEYS */; +INSERT INTO `labels_layouts` VALUES +(1,'CODE39','BIBBAR', 'biblio and barcode', 0, 'TR',7,0,'L','title, author, itemcallnumber'), +(2,'CODE39','BIB', 'spine', 0, 'TR',3,1,'L','itemcallnumber'), +(3,'CODE39','BARBIB', 'barcode and biblio', 0, 'TR',3,1,'L','title, author, itemcallnumber'); +/*!40000 ALTER TABLE `labels_layouts` ENABLE KEYS */; UNLOCK TABLES; diff --git a/installer/data/mysql/en/optional/sample_labels.txt b/installer/data/mysql/en/optional/sample_labels.txt index 685c938b71..2018fc64f0 100644 --- a/installer/data/mysql/en/optional/sample_labels.txt +++ b/installer/data/mysql/en/optional/sample_labels.txt @@ -5,4 +5,5 @@ Gaylord 8511 Spine Label Avery 5460 - vertical Avery 5460 - spine labels Avery 8163 - 2rows x 5 rows -cards Avery 5160 | 1 x 2-5/8 : 1 x 2-5/8\" [3x10] : equivalent: Gaylord JD-ML3000 +cards Avery 5160 | 1 x 2-5/8 : 1 x 2-5/8" [3x10] : equivalent: Gaylord JD-ML3000 +Demco WS14942260 | 1" X 1.5" Spine Label diff --git a/installer/data/mysql/fr-FR/2-Optionel/sample_labels.sql b/installer/data/mysql/fr-FR/2-Optionel/sample_labels.sql index a2dac43d50..80b3645704 100644 --- a/installer/data/mysql/fr-FR/2-Optionel/sample_labels.sql +++ b/installer/data/mysql/fr-FR/2-Optionel/sample_labels.sql @@ -1,24 +1,20 @@ -- Label Templates set NAMES 'utf8'; LOCK TABLES `labels_templates` WRITE; -INSERT INTO `labels_templates` -(tmpl_id,tmpl_code,tmpl_desc,page_width,page_height,label_width,label_height,topmargin,leftmargin,cols,`rows`,colgap,rowgap, -active,units,fontsize,font) -VALUES -(1,'Avery 5160 | 1 x 2-5/8','3 colonnes, 10 lignes d''étiquette',8.5,11,2.625,1,0.5,0.1875,3,10,0.125,0,1,'INCH',7,'TR'), -(2,'Gaylord 8511 Spine Label','Imprime uniquement dans la colnne de gauche d''une planche Gaylord 8511.',8.5,11,1,1.25,0.6,0.5,1,8,0,0,NULL,'INCH',10,'TR'), -(3,'Avery 5460 vertical','',3.625,5.625,1.5,0.75,0.38,0.35,2,7,0.25,0,NULL,'INCH',8,'TR'), -(4,'Avery 5460 Etiquettes de cote','',5.625,3.625,0.75,1.5,0.35,0.31,7,2,0,0.25,NULL,'INCH',8,'TR'), -(5,'Avery 8163','2colonnes x 5 colonnes',8.5,11,4,2,0.5,0.17,2,5,0.2,0.01,NULL,'INCH',11,'TR'), -(6,'cards','Avery 5160 | 1 x 2-5/8 : 1 x 2-5/8\" [3x10] : equivalent: Gaylord JD-ML3000',8.5,11,2.75,1.05,0.25,0,3,10,0.2,0.01,NULL,'INCH',8,'TR'); +INSERT INTO `labels_templates` VALUES +(1,0,'Avery 5160 | 1 x 2-5/8', '3 colonnes, 10 lignes d''étiquette', 8.5, 11, 2.63, 1, 0.139, 0, 0.35, 0.23, 3, 10, 0.13, 0, 'INCH'), +(2,0,'Gaylord 8511 Spine Label','Imprime uniquement dans la colnne de gauche d''une planche Gaylord 8511.', 8.5, 11, 1, 1.25, 0.6, 0.5, 0, 0, 1, 8, 0, 0, 'INCH'), +(3,0,'Avery 5460 vertical', '', 3.625, 5.625, 1.5, 0.75, 0.38, 0.35, 2, 7, 2, 1, 0.25, 0, 'INCH'), +(4,0,'Avery 5460 spine labels', '', 5.625, 3.625, 0.75, 1.5, 0.35, 0.31, 7, 2, 1, 0, 0.25, 0, 'INCH'), +(5,0,'Avery 8163', '2colonnes x 5 colonnes', 8.5, 11, 4, 2, 0, 0, 0.5, 0.17, 2, 5, 0.2, 0.01, 'INCH'), +(6,0,'cards', 'Avery 5160 | 1 x 2-5/8 : 1 x 2-5/8\" [3x10] : equivalent: Gaylord JD-ML3000', 8.5, 11, 2.75, 1.05, 0, 0, 0.25, 0, 3, 10, 0.2, 0.01, 'INCH'), +(7,0,'Demco WS14942260', '1\" X 1.5\" Etiquettes de cotes', 8.5, 11, 1.5, 1, 0.236, 0, 0.4, 0.25, 5, 10, 0.0625, 0, 'INCH'); UNLOCK TABLES; -LOCK TABLES `labels_conf` WRITE; -/*!40000 ALTER TABLE `labels_conf` DISABLE KEYS */; -INSERT INTO `labels_conf` -(id,barcodetype,title,subtitle,itemtype,barcode,dewey,classification,subclass,itemcallnumber,author,issn,isbn,startlabel, -printingtype,formatstring,layoutname,guidebox,active,fonttype,ccode,callnum_split) -VALUES -(5,'CODE39',2,0,3,0,0,0,0,4,1,0,0,1,'BIBBAR','biblio and barcode',1,1,NULL,NULL,NULL,NULL), -(6,'CODE39',2,0,0,0,0,3,4,0,1,0,3,1,'BAR','alternating',1,1,NULL,NULL,NULL,NULL); -/*!40000 ALTER TABLE `labels_conf` ENABLE KEYS */; +LOCK TABLES `labels_layouts` WRITE; +/*!40000 ALTER TABLE `labels_layouts` DISABLE KEYS */; +INSERT INTO `labels_layouts` VALUES +(1,'CODE39','BIBBAR','biblio and barcode',0,'TR',7,0,'L','title, author, itemcallnumber'), +(2,'CODE39','BIB','spine',0,'TR',3,1,'L','itemcallnumber'), +(3,'CODE39','BARBIB','barcode and biblio',0,'TR',3,1,'L','title, author, itemcallnumber'); +/*!40000 ALTER TABLE `labels_layouts` ENABLE KEYS */; UNLOCK TABLES; diff --git a/installer/data/mysql/fr-FR/2-Optionel/sample_labels.txt b/installer/data/mysql/fr-FR/2-Optionel/sample_labels.txt index a532480804..022869eda6 100644 --- a/installer/data/mysql/fr-FR/2-Optionel/sample_labels.txt +++ b/installer/data/mysql/fr-FR/2-Optionel/sample_labels.txt @@ -4,4 +4,5 @@ Gaylord 8511 Spine Label Avery 5460 - vertical Avery 5460 - spine labels Avery 8163 - 2rows x 5 rows -cards Avery 5160 | 1 x 2-5/8 : 1 x 2-5/8\" [3x10] : equivalent: Gaylord JD-ML3000 +cards Avery 5160 | 1 x 2-5/8 : 1 x 2-5/8" [3x10] : equivalent: Gaylord JD-ML3000 +Demco WS14942260 | 1" X 1.5" Etiquettes de cotes diff --git a/installer/data/mysql/kohastructure.sql b/installer/data/mysql/kohastructure.sql index a12f4fdb7e..eb319b5971 100644 --- a/installer/data/mysql/kohastructure.sql +++ b/installer/data/mysql/kohastructure.sql @@ -1228,60 +1228,40 @@ CREATE TABLE `itemtypes` ( ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- --- Table structure for table `labels` +-- Table structure for table `labels_batches` -- -DROP TABLE IF EXISTS `labels`; -CREATE TABLE `labels` ( - `labelid` int(11) NOT NULL auto_increment, - `batch_id` int(10) NOT NULL default 1, - `itemnumber` varchar(100) NOT NULL default '', +DROP TABLE IF EXISTS `labels_batches`; +CREATE TABLE `labels_batches` ( + `label_id` int(11) NOT NULL auto_increment, + `batch_id` int(10) NOT NULL default '1', + `item_number` int(11) NOT NULL default '0', `timestamp` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP, - PRIMARY KEY (`labelid`) + `branch_code` varchar(10) NOT NULL default 'NB', + PRIMARY KEY USING BTREE (`label_id`), + KEY `branch_fk` (`branch_code`), + KEY `item_fk` (`item_number`), + CONSTRAINT `item_fk_constraint` FOREIGN KEY (`item_number`) REFERENCES `items` (`itemnumber`) ON DELETE CASCADE, + CONSTRAINT `branch_fk_constraint` FOREIGN KEY (`branch_code`) REFERENCES `branches` (`branchcode`) ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- --- Table structure for table `labels_conf` +-- Table structure for table `labels_layouts` -- -DROP TABLE IF EXISTS `labels_conf`; -CREATE TABLE `labels_conf` ( - `id` int(4) NOT NULL auto_increment, - `barcodetype` char(100) default '', - `title` int(1) default '0', - `subtitle` int(1) default '0', - `itemtype` int(1) default '0', - `barcode` int(1) default '0', - `dewey` int(1) default '0', - `classification` int(1) default NULL, - `subclass` int(1) default '0', - `itemcallnumber` int(1) default '0', - `author` int(1) default '0', - `issn` int(1) default '0', - `isbn` int(1) default '0', - `startlabel` int(2) NOT NULL default '1', - `printingtype` char(32) default 'BAR', - `formatstring` mediumtext default NULL, - `layoutname` char(20) NOT NULL default 'TEST', +DROP TABLE IF EXISTS `labels_layouts`; +CREATE TABLE `labels_layouts` ( + `layout_id` int(4) NOT NULL auto_increment, + `barcode_type` char(100) NOT NULL default 'CODE39', + `printing_type` char(32) NOT NULL default 'BAR', + `layout_name` char(20) NOT NULL default 'DEFAULT', `guidebox` int(1) default '0', - `active` tinyint(1) default '1', - `fonttype` char(10) collate utf8_unicode_ci default NULL, - `ccode` char(4) collate utf8_unicode_ci default NULL, - `callnum_split` int(1) default NULL, - `text_justify` char(1) collate utf8_unicode_ci default NULL, - PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - --- --- Table structure for table `labels_profile` --- - -DROP TABLE IF EXISTS `labels_profile`; -CREATE TABLE `labels_profile` ( - `tmpl_id` int(4) NOT NULL, - `prof_id` int(4) NOT NULL, - UNIQUE KEY `tmpl_id` (`tmpl_id`), - UNIQUE KEY `prof_id` (`prof_id`) + `font` char(10) character set utf8 collate utf8_unicode_ci NOT NULL default 'TR', + `font_size` int(4) NOT NULL default '10', + `callnum_split` int(1) default '0', + `text_justify` char(1) character set utf8 collate utf8_unicode_ci NOT NULL default 'L', + `format_string` varchar(210) NOT NULL default 'barcode', + PRIMARY KEY USING BTREE (`layout_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- @@ -1290,24 +1270,25 @@ CREATE TABLE `labels_profile` ( DROP TABLE IF EXISTS `labels_templates`; CREATE TABLE `labels_templates` ( -`tmpl_id` int(4) NOT NULL auto_increment, - `tmpl_code` char(100) default '', - `tmpl_desc` char(100) default '', - `page_width` float default '0', - `page_height` float default '0', - `label_width` float default '0', - `label_height` float default '0', - `topmargin` float default '0', - `leftmargin` float default '0', - `cols` int(2) default '0', - `rows` int(2) default '0', - `colgap` float default '0', - `rowgap` float default '0', - `active` int(1) default NULL, - `units` char(20) default 'PX', - `fontsize` int(4) NOT NULL default '3', - `font` char(10) NOT NULL default 'TR', - PRIMARY KEY (`tmpl_id`) + `template_id` int(4) NOT NULL auto_increment, + `profile_id` int(4) default NULL, + `template_code` char(100) NOT NULL default 'DEFAULT TEMPLATE', + `template_desc` char(100) NOT NULL default 'Default description', + `page_width` float NOT NULL default '0', + `page_height` float NOT NULL default '0', + `label_width` float NOT NULL default '0', + `label_height` float NOT NULL default '0', + `top_text_margin` float NOT NULL default '0', + `left_text_margin` float NOT NULL default '0', + `top_margin` float NOT NULL default '0', + `left_margin` float NOT NULL default '0', + `cols` int(2) NOT NULL default '0', + `rows` int(2) NOT NULL default '0', + `col_gap` float NOT NULL default '0', + `row_gap` float NOT NULL default '0', + `units` char(20) NOT NULL default 'POINT', + PRIMARY KEY (`template_id`), + KEY `template_profile_fk_constraint` (`profile_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- @@ -1630,18 +1611,17 @@ CREATE TABLE `printers` ( DROP TABLE IF EXISTS `printers_profile`; CREATE TABLE `printers_profile` ( - `prof_id` int(4) NOT NULL auto_increment, - `printername` varchar(40) NOT NULL, - `tmpl_id` int(4) NOT NULL, - `paper_bin` varchar(20) NOT NULL, - `offset_horz` float default NULL, - `offset_vert` float default NULL, - `creep_horz` float default NULL, - `creep_vert` float default NULL, - `unit` char(20) NOT NULL default 'POINT', - PRIMARY KEY (`prof_id`), - UNIQUE KEY `printername` (`printername`,`tmpl_id`,`paper_bin`), - CONSTRAINT `printers_profile_pnfk_1` FOREIGN KEY (`tmpl_id`) REFERENCES `labels_templates` (`tmpl_id`) ON DELETE CASCADE ON UPDATE CASCADE + `profile_id` int(4) NOT NULL auto_increment, + `printer_name` varchar(40) NOT NULL default 'Default Printer', + `template_id` int(4) NOT NULL default '0', + `paper_bin` varchar(20) NOT NULL default 'Bypass', + `offset_horz` float NOT NULL default '0', + `offset_vert` float NOT NULL default '0', + `creep_horz` float NOT NULL default '0', + `creep_vert` float NOT NULL default '0', + `units` char(20) NOT NULL default 'POINT', + PRIMARY KEY (`profile_id`), + UNIQUE KEY `printername` (`printer_name`,`template_id`,`paper_bin`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- diff --git a/installer/data/mysql/labels_upgrade.pl b/installer/data/mysql/labels_upgrade.pl new file mode 100644 index 0000000000..15d9b19948 --- /dev/null +++ b/installer/data/mysql/labels_upgrade.pl @@ -0,0 +1,184 @@ +#!/usr/bin/perl +# +# Copyright 2009 Foundations Bible College. +# +# This file is part of Koha. +# +# Koha is free software; you can redistribute it and/or modify it under the +# terms of the GNU General Public License as published by the Free Software +# Foundation; either version 2 of the License, or (at your option) any later +# version. +# +# Koha is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along with +# Koha; if not, write to the Free Software Foundation, Inc., 59 Temple Place, +# Suite 330, Boston, MA 02111-1307 USA + +use C4::Context; + +my $sth = C4::Context->dbh; + +# NOTE: As long as we die on error *before* the DROP TABLE instructions are executed, the script may simply be rerun after addressing whatever errors occur; If we get past the data conversion without error, the DROPs and ALTERs could be executed manually if need be. + +# Turn off key checks for duration of script... +$sth->do(" + SET UNIQUE_CHECKS = 0; +") or die "DB ERROR: " . $sth->errstr . "\n"; + +$sth->do(" + SET FOREIGN_KEY_CHECKS = 0; +") or die "DB ERROR: " . $sth->errstr . "\n"; + +# Create new tables with temporary names... +$sth->do(" + DROP TABLE IF EXISTS labels_batches_tmp;"); +$sth->do(" + CREATE TABLE `labels_batches_tmp` ( + `label_id` int(11) NOT NULL auto_increment, + `batch_id` int(10) NOT NULL default '1', + `item_number` int(11) NOT NULL default '0', + `timestamp` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP, + `branch_code` varchar(10) NOT NULL default 'NB', + PRIMARY KEY USING BTREE (`label_id`), + KEY `branch_fk_constraint` (`branch_code`), + KEY `item_fk_constraint` (`item_number`), + FOREIGN KEY (`branch_code`) REFERENCES `branches` (`branchcode`) ON DELETE CASCADE, + FOREIGN KEY (`item_number`) REFERENCES `items` (`itemnumber`) ON DELETE CASCADE + ) ENGINE=InnoDB DEFAULT CHARSET=utf8; +") or die "DB ERROR: " . $sth->errstr . "\n"; + +$sth->do(" + DROP TABLE IF EXISTS labels_layouts_tmp;"); +$sth->do(" + CREATE TABLE `labels_layouts_tmp` ( + `layout_id` int(4) NOT NULL auto_increment, + `barcode_type` char(100) NOT NULL default 'CODE39', + `printing_type` char(32) NOT NULL default 'BAR', + `layout_name` char(20) NOT NULL default 'DEFAULT', + `guidebox` int(1) default '0', + `font` char(10) character set utf8 collate utf8_unicode_ci NOT NULL default 'TR', + `font_size` int(4) NOT NULL default '10', + `callnum_split` int(1) default '0', + `text_justify` char(1) character set utf8 collate utf8_unicode_ci NOT NULL default 'L', + `format_string` varchar(210) NOT NULL default 'barcode', + PRIMARY KEY USING BTREE (`layout_id`) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8; +") or die "DB ERROR: " . $sth->errstr . "\n"; + +$sth->do(" + DROP TABLE IF EXISTS labels_templates_tmp;"); +$sth->do(" + CREATE TABLE `labels_templates_tmp` ( + `template_id` int(4) NOT NULL auto_increment, + `profile_id` int(4) default NULL, + `template_code` char(100) NOT NULL default 'DEFAULT TEMPLATE', + `template_desc` char(100) NOT NULL default 'Default description', + `page_width` float NOT NULL default '0', + `page_height` float NOT NULL default '0', + `label_width` float NOT NULL default '0', + `label_height` float NOT NULL default '0', + `top_text_margin` float NOT NULL default '0', + `left_text_margin` float NOT NULL default '0', + `top_margin` float NOT NULL default '0', + `left_margin` float NOT NULL default '0', + `cols` int(2) NOT NULL default '0', + `rows` int(2) NOT NULL default '0', + `col_gap` float NOT NULL default '0', + `row_gap` float NOT NULL default '0', + `units` char(20) NOT NULL default 'POINT', + PRIMARY KEY (`template_id`), + KEY `template_profile_fk_constraint` (`profile_id`) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8; +") or die "DB ERROR: " . $sth->errstr . "\n"; + +$sth->do(" + DROP TABLE IF EXISTS printers_profile_tmp;"); +$sth->do(" + CREATE TABLE `printers_profile_tmp` ( + `profile_id` int(4) NOT NULL auto_increment, + `printer_name` varchar(40) NOT NULL default 'Default Printer', + `template_id` int(4) NOT NULL default '0', + `paper_bin` varchar(20) NOT NULL default 'Bypass', + `offset_horz` float NOT NULL default '0', + `offset_vert` float NOT NULL default '0', + `creep_horz` float NOT NULL default '0', + `creep_vert` float NOT NULL default '0', + `units` char(20) NOT NULL default 'POINT', + PRIMARY KEY (`profile_id`), + UNIQUE KEY `printername` (`printer_name`,`template_id`,`paper_bin`) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8; +") or die "DB ERROR: " . $sth->errstr . "\n"; + +# Migrate data from existing tables to new tables... + +$sth->do("INSERT INTO `labels_batches_tmp` (label_id, batch_id, item_number) SELECT labelid, batch_id, itemnumber FROM labels;") or die "DB ERROR: " . $sth->errstr . "\n"; +# Since the new label creator keys batches on branch code we must add a branch code during the conversion; the simplest solution appears to be to grab the top branch code from the branches table... +$sth->do("UPDATE `labels_batches_tmp` SET branch_code=(SELECT branchcode FROM branches LIMIT 0,1);") or die "DB ERROR: " . $sth->errstr . "\n"; + + +$sth->do("INSERT INTO `labels_layouts_tmp` (layout_id, barcode_type, printing_type, layout_name, guidebox, callnum_split, text_justify, format_string) SELECT lc.id, lc.barcodetype, lc.printingtype, lc.layoutname, lc.guidebox, lc.callnum_split, lc.text_justify, lc.formatstring FROM labels_conf AS lc;") or die "DB ERROR: " . $sth->errstr . "\n"; + +$sth->do("INSERT INTO `labels_templates_tmp` (template_id, template_code, template_desc, page_width, page_height, label_width, label_height, top_margin, left_margin, cols, rows, col_gap, row_gap, units) SELECT lt.tmpl_id, lt.tmpl_code, lt.tmpl_desc, lt.page_width, lt.page_height, lt.label_width, lt.label_height, lt.topmargin, lt.leftmargin, lt.cols, lt.rows, lt.colgap, lt.rowgap, lt.units FROM labels_templates AS lt;") or die "DB ERROR: " . $sth->errstr . "\n"; + +$sth->do("INSERT INTO `printers_profile_tmp` (profile_id, printer_name, template_id, paper_bin, offset_horz, offset_vert, creep_horz, creep_vert, units) SELECT prof_id, printername, tmpl_id, paper_bin, offset_horz, offset_vert, creep_horz, creep_vert, unit FROM printers_profile;") or die "DB ERROR: " . $sth->errstr . "\n"; + + +my $sth1 = C4::Context->dbh->prepare("SELECT layout_id, format_string FROM labels_layouts_tmp;"); +#$sth1->{'TraceLevel'} = 3; +$sth1->execute or die "DB ERROR: " . $sth1->errstr . "\n"; +while (my $layout = $sth1->fetchrow_hashref()) { + if (!$layout->{'format_string'}) { + my $sth2 = C4::Context->dbh->prepare("SELECT id, title, subtitle, itemtype, barcode, dewey, classification, subclass, itemcallnumber, author, issn, isbn, ccode FROM labels_conf WHERE id = " . $layout->{'layout_id'}); + $sth2->execute or die "DB ERROR: " . $sth2->errstr . "\n"; + my $record = $sth2->fetchrow_hashref(); + my @label_fields = (); + RECORD: + foreach (keys(%$record)) { + next RECORD if $record->{$_} eq '' or $_ eq 'id'; + $label_fields[$record->{$_}] = $_; + } + shift @label_fields; + my $format_string = join (",", @label_fields); +# my $format_string = s/^,//i; + $sth->do("UPDATE `labels_layouts_tmp` SET format_string=\'$format_string\' WHERE layout_id = " . $record->{'id'}) or die "DB ERROR: " . $sth->errstr . "\n"; + } +} + +my $sth3 = C4::Context->dbh->prepare("SELECT template_id FROM labels_templates_tmp;"); +$sth3->execute or die "DB ERROR: " . $sth3->errstr . "\n"; +RECORD: +while (my $template = $sth3->fetchrow_hashref()) { + my $sth4 = C4::Context->dbh->prepare("SELECT profile_id FROM printers_profile_tmp WHERE template_id = " . $template->{'template_id'}); + $sth4->execute or die "DB ERROR: " . $sth4->errstr . "\n"; + my $profile_id = $sth4->fetchrow_hashref(); + next RECORD if $profile_id->{'profile_id'} eq ''; + $sth->do("UPDATE `labels_templates_tmp` SET profile_id=\'" . $profile_id->{'profile_id'} . "\' WHERE template_id = " . $template->{'template_id'}) or die "DB ERROR: " . $sth->errstr . "\n"; +} + +# Drop old tables.... + +$sth->do("DROP TABLE IF EXISTS labels;") or die "DB ERROR: " . $sth->errstr . "\n"; +$sth->do("DROP TABLE IF EXISTS labels_conf;") or die "DB ERROR: " . $sth->errstr . "\n"; +$sth->do("DROP TABLE IF EXISTS labels_profile;") or die "DB ERROR: " . $sth->errstr . "\n"; +$sth->do("DROP TABLE IF EXISTS labels_templates;") or die "DB ERROR: " . $sth->errstr . "\n"; +$sth->do("DROP TABLE IF EXISTS printers_profile;") or die "DB ERROR: " . $sth->errstr . "\n"; + +# Rename temporary tables to permenant names... + +$sth->do("ALTER TABLE labels_batches_tmp RENAME TO labels_batches;") or die "DB ERROR: " . $sth->errstr . "\n"; +$sth->do("ALTER TABLE labels_layouts_tmp RENAME TO labels_layouts;") or die "DB ERROR: " . $sth->errstr . "\n"; +$sth->do("ALTER TABLE labels_templates_tmp RENAME TO labels_templates;") or die "DB ERROR: " . $sth->errstr . "\n"; +$sth->do("ALTER TABLE printers_profile_tmp RENAME TO printers_profile;") or die "DB ERROR: " . $sth->errstr . "\n"; + + +# Re-enable key checks... +$sth->do(" + SET UNIQUE_CHECKS = 1; +") or die "DB ERROR: " . $sth->errstr . "\n"; + +$sth->do(" + SET FOREIGN_KEY_CHECKS = 1; +") or die "DB ERROR: " . $sth->errstr . "\n"; diff --git a/installer/data/mysql/updatedatabase.pl b/installer/data/mysql/updatedatabase.pl index 5f3d7a1ac7..e783a838fe 100755 --- a/installer/data/mysql/updatedatabase.pl +++ b/installer/data/mysql/updatedatabase.pl @@ -2596,6 +2596,15 @@ if (C4::Context->preference("Version") < TransformToNum($DBversion)) { print "Upgrade to $DBversion done (bug 3481: add permanent_location column to deleteditems)\n"; } +$DBversion = '3.01.00.053'; +if (C4::Context->preference("Version") < TransformToNum($DBversion)) { + my $upgrade_script = C4::Context->config("intranetdir") . "/installer/data/mysql/labels_upgrade.pl"; + system("perl $upgrade_script"); + print "Upgrade to $DBversion done (Migrated labels tables and data to new schema.) NOTE: All existing label batches have been assigned to the first branch in the list of branches. This is ONLY true of migrated label batches.\n"; + SetVersion ($DBversion); +} + + =item DropAllForeignKeys($table) Drop all foreign keys of the table $table diff --git a/koha-tmpl/intranet-tmpl/prog/en/css/label.css b/koha-tmpl/intranet-tmpl/prog/en/css/label.css new file mode 100644 index 0000000000..1e14598638 --- /dev/null +++ b/koha-tmpl/intranet-tmpl/prog/en/css/label.css @@ -0,0 +1,37 @@ +div.homeimage { + background-attachment: scroll; + background-color: transparent; + background-image: url(../../img/label-creator-image.png); + background-position: top right; + background-repeat: no-repeat; + min-width: 800px; +} + +div.lci_01 { + float: right; + clear: right; + height: 90px; + width: 280px; + margin: 2px; + padding: 2px; +} + +div.lci_02 { + float: right; + clear: right; + height: 165px; + width: 582px; + margin: 2px; + padding: 2px; +} + +div.lci_03 { + float: right; + clear: right; + height: 55px; + width: 305px; + margin: 2px; + padding: 2px; +} + + diff --git a/koha-tmpl/intranet-tmpl/prog/en/css/staff-global.css b/koha-tmpl/intranet-tmpl/prog/en/css/staff-global.css index 41ba3e90f3..076e405a2c 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/css/staff-global.css +++ b/koha-tmpl/intranet-tmpl/prog/en/css/staff-global.css @@ -5,10 +5,14 @@ a, a:link, a:visited, a:active { color : #0000CC; } -.yui-button a,.yui-button a:link,.yui-button a:visited { +.yui-button,.yui-button a:link,.yui-button a:visited { color : #000; } +a.yuimenuitemlabel { + color: #000000; +} + a:hover { color : #669ACC; } @@ -227,6 +231,15 @@ table { border-right : 1px solid #BCBCBC; } +table.borderless { + border-collapse : separate; + border: 0 none; +} + +#label-search-results { + width: 700px; +} + td, th { border-bottom : 1px solid #BCBCBC; border-left : 1px solid #BCBCBC; @@ -237,6 +250,11 @@ td { background-color : White; } +td.borderless { + border-collapse : separate; + border : 0 none; +} + th { background-color : #E8E8E8; font-weight : bold; @@ -323,6 +341,9 @@ legend { display : inline; } +div.justify { + text-align: justify; +} div#header_search { background-position : .5em .5em; @@ -474,7 +495,7 @@ fieldset.brief ol, fieldset.brief li { list-style-type : none; } -fieldset.brief div.hint, fieldset.rows div.hint { +fieldset.brief div.hint, fieldset.rows div.hint, div.yui-u div.hint { color : #999999; font-size : 95%; margin-bottom : .4em; @@ -534,7 +555,7 @@ fieldset.rows fieldset { } .yui-u fieldset.rows label, .yui-u fieldset.rows span.label { - width: 6em; + width: 10em; } .yui-u fieldset.rows div.hint { @@ -777,7 +798,7 @@ fieldset.rows .inputnote { visibility:visible; /* you propably don't need to change this one */ display:block; } -#newbiblio a, #addchild a, #newentry a, #newshelf a, #newmenuc .first-child, #newsupplier .first-child, #newlabel a, #newtemplate a, #newlabelbatch a, #newpatroncardbatch a, #newprofile a, #newsubscription a, #newdictionary a, #neworder a { +#newbiblio a, #addchild a, #newentry a, #newshelf a, #newmenuc .first-child, #newsupplier .first-child, #newlabel a, #newtemplate a, #newbatch a, #newprofile a, #newsubscription a, #newdictionary a, #neworder a { padding-left : 34px; background-image: url("../../img/toolbar-new.gif"); background-position : center left; @@ -806,7 +827,7 @@ fieldset.rows .inputnote { background-repeat : no-repeat; } -#editpatron a, #editmenuc .first-child, #editshelf a, #edit a, #editsupplier a { +#editpatron a, #editmenuc .first-child, #editshelf a, #edit a, #editsupplier a, #managelabel a, #managetemplate a, #managelabelbatch a, #manageprofile a { padding-left : 34px; background-image: url("../../img/toolbar-edit.gif"); background-position : center left; @@ -1103,6 +1124,11 @@ div.alert strong { color : #900; } +div.dialog { + background : #FFC url(../../img/dialog-bg.gif) repeat-x left 0; + text-align : center; +} + div.message { background : white url("../../img/message-bg.gif") repeat-x left 0; border : 1px solid #bcbcbc; @@ -1694,3 +1720,72 @@ span.permissiondesc { color: black; } +.hintsClass { + font-family: tahoma, verdana, arial; + font-size: 12px; + background-color: #f0f0f0; + color: #000000; + border: 1px solid #808080; + padding: 5px; +} +.hintSource { + color: green; + text-decoration: underline; + cursor: pointer; +} + +h1#pdf { + background:transparent url(../../img/pdficon_large.gif) no-repeat scroll 0%; + border: 0; + margin:0.75em .3em 0.75em .7em; + padding:0; +} + +h1#pdf a { + border:0; + cursor:pointer; + display:block; + height:0px !important; + margin:0; + overflow:hidden; + padding:44px 0 0; + text-decoration:none; + width:35px; +} + +h1#csv { + background:transparent url(../../img/csv_icon.gif) no-repeat scroll 0%; + border: 0; + margin:0.75em .3em 0.75em .7em; + padding:0; +} + +h1#csv a { + border:0; + cursor:pointer; + display:block; + height:0px !important; + margin:0; + overflow:hidden; + padding:44px 0 0; + text-decoration:none; + width:35px; +} + +h1#xml { + background:transparent url(../../img/icon_xml.gif) no-repeat scroll 0%; + border: 0; + margin:0.75em .3em 0.75em .7em; + padding:0; +} + +h1#xml a { + border:0; + cursor:pointer; + display:block; + height:0px !important; + margin:0; + overflow:hidden; + padding:44px 0 0; + text-decoration:none; + width:35px; diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/header.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/header.inc index fd28c3e2b3..4c034e93bd 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/includes/header.inc +++ b/koha-tmpl/intranet-tmpl/prog/en/includes/header.inc @@ -1,38 +1,66 @@ - + diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/labels-batches-toolbar.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/labels-batches-toolbar.inc new file mode 100644 index 0000000000..e139feb7e8 --- /dev/null +++ b/koha-tmpl/intranet-tmpl/prog/en/includes/labels-batches-toolbar.inc @@ -0,0 +1,179 @@ +
+ + +
diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/labels-menu.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/labels-menu.inc index b9341ec00a..0eb16430c7 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/includes/labels-menu.inc +++ b/koha-tmpl/intranet-tmpl/prog/en/includes/labels-menu.inc @@ -1,8 +1,8 @@ diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/labels-new-toolbar.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/labels-new-toolbar.inc new file mode 100644 index 0000000000..35553df11b --- /dev/null +++ b/koha-tmpl/intranet-tmpl/prog/en/includes/labels-new-toolbar.inc @@ -0,0 +1,23 @@ + + diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/labels-toolbar.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/labels-toolbar.inc new file mode 100644 index 0000000000..28003f9378 --- /dev/null +++ b/koha-tmpl/intranet-tmpl/prog/en/includes/labels-toolbar.inc @@ -0,0 +1,75 @@ + + diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/tools-labels-batches-toolbar.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/tools-labels-batches-toolbar.inc deleted file mode 100644 index 52946b5488..0000000000 --- a/koha-tmpl/intranet-tmpl/prog/en/includes/tools-labels-batches-toolbar.inc +++ /dev/null @@ -1,85 +0,0 @@ - -
- -
- -
- -
- diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/tools-labels-toolbar.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/tools-labels-toolbar.inc deleted file mode 100644 index 99736b99c4..0000000000 --- a/koha-tmpl/intranet-tmpl/prog/en/includes/tools-labels-toolbar.inc +++ /dev/null @@ -1,29 +0,0 @@ -
- -
diff --git a/koha-tmpl/intranet-tmpl/prog/en/lib/greybox/gb_styles.css b/koha-tmpl/intranet-tmpl/prog/en/lib/greybox/gb_styles.css index 52fdc17182..75e29e3216 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/lib/greybox/gb_styles.css +++ b/koha-tmpl/intranet-tmpl/prog/en/lib/greybox/gb_styles.css @@ -60,7 +60,16 @@ .GB_header table { margin: 0; width: 100%; - border-collapse: collapse; + border-collapse: separate; + border-right: 0px; + border-top: 0px; +} + +.GB_header td { + background-color: #333333; + border-bottom: 0px; + border-left: 0px; + padding: 0em 0em; } .GB_header .caption { @@ -68,6 +77,7 @@ color: #eee; white-space: nowrap; font-size: 20px; + border-collapse: separate; } .GB_header .close { @@ -146,3 +156,15 @@ .GB_Window .on { border-bottom: 1px solid #333; } .GB_Window .click { border-bottom: 1px solid red; } + +table { + border-collapse: separate; + border-spacing: 0; + border: hidden none; +} + +.header { + cursor: auto; + background-position: center center; + background-repeat: repeat; +} diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/z3950_search.tmpl b/koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/z3950_search.tmpl index fe256a6786..b599622946 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/z3950_search.tmpl +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/z3950_search.tmpl @@ -116,8 +116,9 @@ $(document).ready(function(){ - " title="MARC" rel="gb_page_center[600,500]">MARC" title="MARC" rel="gb_page_center[600,500]">Card - ,)">Import + " title="MARC" rel="gb_page_center[600,500]">MARC + " title="MARC" rel="gb_page_center[600,500]">Card + ,)">Import diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/labels/label-create-layout.tmpl b/koha-tmpl/intranet-tmpl/prog/en/modules/labels/label-create-layout.tmpl deleted file mode 100644 index f4f4ed94f7..0000000000 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/labels/label-create-layout.tmpl +++ /dev/null @@ -1,255 +0,0 @@ -Koha › Tools › Labels › Create Layout - - - - - - - - -
- -
-
-
- - -
- -
-Create Layout -
  1. -" />
  2. - -
  3. -Choose Order Of Fields to Print - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    - - - - - - - - -
    - - - - - - - - -
    - - - - - - - - -
    - - - - - -
  4. - -
  5. -
  6. - -
  7. -
  8. -
  9. -
  10. - - -
-
- Cancel
-
- -
-
-
- -
-
- \ No newline at end of file diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/labels/label-create-profile.tmpl b/koha-tmpl/intranet-tmpl/prog/en/modules/labels/label-create-profile.tmpl deleted file mode 100644 index f69dbac9fb..0000000000 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/labels/label-create-profile.tmpl +++ /dev/null @@ -1,95 +0,0 @@ - -Koha › Tools › Labels - - - - - - - - - -
- -
-
-
- - - - -

Create Printer Profile

- -
-

Error Creating Profile

-

- -

-
-
- -
-
-
Profile Settings - -
    - -
  1. - -
  2. -
  3. - -
  4. -
  5. - -
  6. -
  7. -
    Offset: -
    1. -
    -
  8. -
  9. -
    Creep: -
    1. - -
    2. -
    3. - -
    -
    -
  10. -
  11. -
  12. -
-
-
- Cancel -
-
- -
-
- -
-
- diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/labels/label-create-template.tmpl b/koha-tmpl/intranet-tmpl/prog/en/modules/labels/label-create-template.tmpl deleted file mode 100644 index 5c5a6f4ab3..0000000000 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/labels/label-create-template.tmpl +++ /dev/null @@ -1,86 +0,0 @@ -Koha › Tools › Labels - - - - - - - - -
- -
-
-
- - -
- -
-Create Label Template - -
    - -
  1. -
  2. - -
  3. -
  4. - -
  5. -
  6. - -
  7. -
  8. - -
  9. -
  10. - -
  11. -
  12. - -
  13. -
  14. - -
  15. -
  16. - -
  17. -
  18. - -
  19. -
  20. - -
  21. -
  22. - -
  23. - -
  24. - -
  25. - -
  26. -
-
-
- - -
-
- -
-
-
- -
-
- diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/labels/label-edit-batch.tmpl b/koha-tmpl/intranet-tmpl/prog/en/modules/labels/label-edit-batch.tmpl new file mode 100644 index 0000000000..de26dea047 --- /dev/null +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/labels/label-edit-batch.tmpl @@ -0,0 +1,75 @@ + + Koha › Tools › Labels › Manage Label Batches + + + + + + + +
+
+
+
+ +
+
+
Current Branch:
+ +
+

Items in batch number

+ + + + + + + + + + + + + + + + + + + + +
">
+
+ +

There are no items in this batch yet

+

Use the toolbar above to add items.

+ +
+ +
+
+ WARNING: An error was encountered and Please have your system administrator check the error log for details. +
+
+ +
+
+ duplicate item(s) found and removed from batch . +
+
+ +
+
+
+
+ +
+
+
+ diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/labels/label-edit-layout.tmpl b/koha-tmpl/intranet-tmpl/prog/en/modules/labels/label-edit-layout.tmpl index 04d9e38d29..e40c41531f 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/labels/label-edit-layout.tmpl +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/labels/label-edit-layout.tmpl @@ -1,264 +1,182 @@ -Koha › Tools › Labels - - + + Koha › Tools › Labels + + - - - - - -
- -
-
-
- -
-
-EditCreate Label Layout -
    -
  1. -" />
  2. - -
  3. -
  4. - - -
  5. -
  6. - - -
  7. -
    - -Bibliographic Data to Print - - -Choose Order Of Text Fields to Print - -Choose Order Of Text Fields to Print - -
    -
    - - - - - - - - - - - - - - - - -
    - - - - - - - - -
    - - - - - - - - -
    - - -   
    -
    -
    -
    - - List Fields - - List Fields - -
    - - -" /> - -
    -

    Enter a comma separated list of fields to print. You may include any Koha field or MARC subfield.

    -

    See online help for advanced options

    -

    ex: barcode, itemcallnumber, title, "050a 050b", 300a

    -
    -
    -
    -
  8. -
  9. 1" />
  10. - - -
  11. - - - - -
  12. - -
  13. - - - - -
  14. - -
  15. - -
  16. - -
-
-
- Cancel - saveadd_layout" /> - " /> -
-
- -
-
-
- -
-
- + + + +
+
+
+
+
+
+ EditCreate Label Layout +
    +
  1. + + " /> +
  2. +
  3. + + +
  4. +
  5. + + +
  6. +
  7. +
    + Bibliographic Data to Print + + Choose Order Of Text Fields to Print + + Choose Order Of Text Fields to Print + +
    +
    + + + + + + + + + + + + +
    +   + + + +
    +
    +
    +
    + + List Fields + + List Fields + +
    + + " /> +
    +

    Enter a comma separated list of fields to print. You may include any Koha field or MARC subfield.

    +

    See online help for advanced options

    +

    ex: barcode, itemcallnumber, title, "050a 050b", 300a

    +
    +
    +
    +
  8. +
  9. + + + + + + +
  10. +
  11. + + + + + + +
  12. +
  13. + + +
  14. +
  15. + + +
  16. +
  17. + + " /> +
  18. +
+
+
+ + + + " /> +
+
+
+
+
+ +
+
+ diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/labels/label-edit-profile.tmpl b/koha-tmpl/intranet-tmpl/prog/en/modules/labels/label-edit-profile.tmpl index c0ce14a211..f3e32b0389 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/labels/label-edit-profile.tmpl +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/labels/label-edit-profile.tmpl @@ -1,74 +1,99 @@ -Koha › Tools › Labels - + i + Koha › Tools › Labels + - - - - - -
- -
-
-
-
- -
-

Edit Printer Profile

-
-
Profile Settings - -
    -
  1. - -
  2. -
  3. - -
  4. -
  5. - -
  6. -
  7. - -
  8. -
  9. - " /> -
  10. -
  11. - " /> -
  12. -
  13. - -
  14. -
  15. - " /> -
  16. -
  17. - " /> -
  18. -
  19. -
  20. -" /> -
-
-
- -
-
-
- -
-
- -
-
- + + + +
+
+
+
+
+
+

Edit Printer Profile

+
+
Profile Settings +
    +
  1. + + + + + + +
  2. +
  3. + + + + + + +
  4. +
  5. + + + + + Profile Unassigned + +
  6. + +
  7. + +
  8. +
  9. + " /> +
  10. +
  11. + " /> +
  12. +
  13. + +
  14. +
  15. + " /> +
  16. +
  17. + " /> +
  18. +
  19. + + +
  20. +
+
+
+ + + + " /> +
+
+
+
+ +
+
+ +
+
+ diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/labels/label-edit-template.tmpl b/koha-tmpl/intranet-tmpl/prog/en/modules/labels/label-edit-template.tmpl index 1d4be5a053..367e1f545c 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/labels/label-edit-template.tmpl +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/labels/label-edit-template.tmpl @@ -1,126 +1,135 @@ -Koha › Tools › Labels - + + Koha › Tools › Labels › Templates + - - - - - -
- -
-
-
-
- -
-

Edit Label Template

-
-
Template Settings - -
    -
  1. Template ID:
  2. -
  3. " />
  4. -
  5. - -
  6. - " /> -
  7. -
  8. - " /> -
  9. -
  10. - " /> -
  11. -
  12. - " /> -
  13. -
  14. - " /> -
  15. -
  16. - " /> -
  17. -
-
-
-
-
-
    - -
  1. - " /> -
  2. -
  3. - " /> -
  4. -
  5. - " /> -
  6. -
  7. - " /> - -
  8. - -
  9. - -
  10. - - - - None Defined - -
  11. - -
  12. - -
  13. " />
  14. - -
  15. - - - - - - " />
  16. - -
-
-
-
- Cancel -
-
- -
-
-
- -
-
- + + + +
+
+
+
+
+
+

Edit Label Template

+
+
+
    +
  1. + Template ID:N/A +
  2. +
  3. + + " /> +
  4. +
  5. + + +
  6. +
  7. + + " /> +
  8. +
  9. + + " /> +
  10. +
  11. + + " /> +
  12. +
  13. + + " /> +
  14. +
  15. + + " /> +
  16. +
  17. + + " /> +
  18. +
+
+
+
+
+
    +
  1. + + " /> +
  2. +
  3. + + " /> +
  4. +
  5. + + " /> +
  6. +
  7. + + " /> +
  8. +
  9. + + " /> +
  10. +
  11. + + " /> +
  12. +
  13. + + +
  14. +
  15. + + + + + Click here to define a printer profile. + +
  16. +
+
+
+
+
+
+ + + + + " /> + +
+
+
+
+
+
+ +
+
+ diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/labels/label-home.tmpl b/koha-tmpl/intranet-tmpl/prog/en/modules/labels/label-home.tmpl index 931bde7299..6460e44352 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/labels/label-home.tmpl +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/labels/label-home.tmpl @@ -1,78 +1,51 @@ -Koha › Tools › Labels - + + Koha › Tools › Labels Home + + /css/label.css" /> - - - - - -
- -
-
-
- - - - -
-
-
-

Set Active Layout

- - - - - - - - - - - - - - - - - - - - - - - - - -
LayoutBarcode TypePrint TypeFields to PrintEditDeleteActive
- - - ">Edit - - ">Delete - -" checked="checked" /> - -" /> - -
-
- -
-
-
- -
-
- - - - -
-
-
- -
-
- + + + +
+
+
+
+
+ +
+
+
+
+
+

Welcome to Koha's Label Creator Module

+

The Label Creator allow you to use layouts and templates which you design to print a nearly unlimited variety of labels including barcodes. Here are some of the features of the Label Creator module:

+
    +
  • Customize label layouts
  • +
  • Design custom label templates for printed labels
  • +
  • Build and manage batches of labels
  • +
  • Export single or multiple batches
  • +
  • Export single or multiple labels from within a batch
  • +
  • Export label data in one of three formats:
  • +
      +
    • PDF - Readable by any standard PDF reader, making labels printable directly on a printer
    • +
    • CSV - Export label data after your chosen layout is applied allowing labels to be imported in to a variety of applications
    • +
    • XML - Included as an alternate export format
    • +
    +
+

At the top of each screen within the Label Creator, you will see a toolbar allowing quick access to relevant functions. The menu to the left of each screen also allows easy access to the different sections of the Label Creator. The breadcrumb trail near the top of each screen will give specific indication as to where you are within the Label Creator module and allow quick navigation to previously traversed sections. And finally, you can find more detailed information on each section of the Label Creator by clicking the online help link at the upper left-hand corner of every page.

+

The developers of the Label Creator module hope you will find this an extremely useful tool in the course of your cataloging work. You are encouraged to submit any enhancement requests as well as any bugs via Koha Project Bugzilla.

+
+
+
+
+
+
+ +
+
+ diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/labels/label-manage.tmpl b/koha-tmpl/intranet-tmpl/prog/en/modules/labels/label-manage.tmpl new file mode 100644 index 0000000000..754f8cc0f4 --- /dev/null +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/labels/label-manage.tmpl @@ -0,0 +1,152 @@ + + Koha › Tools › Labels › Manage Label Elements + + + + + + + + + + +
+
+
+
+ +
+
+
Current Branch:
+ +
+

Currently Available

+ + + + + + + + + + + + + + + + + + + + + + +
"> 
+
+ + + +
+
+ +

There Are No Currently Available.

+

Use the toolbar above to create a new .

+ +
+ +
+
+ WARNING: An error was encountered and was not deleted. Please have your system administrator check the error log for details. +
+
+ +
+
+
+
+ +
+
+ diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/labels/label-manager.tmpl b/koha-tmpl/intranet-tmpl/prog/en/modules/labels/label-manager.tmpl index f60bbd7742..aab84df48f 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/labels/label-manager.tmpl +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/labels/label-manager.tmpl @@ -18,7 +18,7 @@ - +
@@ -72,7 +72,7 @@
- +
diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/labels/label-print.tmpl b/koha-tmpl/intranet-tmpl/prog/en/modules/labels/label-print.tmpl index 8898b5fda4..840b7e6b70 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/labels/label-print.tmpl +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/labels/label-print.tmpl @@ -1,181 +1,164 @@ - - - - -Print Preview - - + + Koha › Tools › Labels › Label Printing/Exporting + + + + - -
-

Print Preview
- Barcodetype:
- Papertype:
- Field Options: Author - Itemtype - Title - ISBN - Dewey - Class - Subclass - Itemcallnumber - -

-
- - - - - - - - - - - - - - - -

- Back   - Print   -
- - - - +
+
+ +
+
+
+ Click on the following link(s) to download the exported batch(es). +
+
+
+ + + + + + + + + + + + + + + + + + + + + +
+ Single Labels + +

+ ?batch_id=&template_id=&layout_id=&start_label=">label_single_.pdf +

+
+

+ &template_id=&layout_id=">label_single_.csv +

+
+

+ &template_id=&layout_id=">label_single_.xml +

+
+ Single Labels + +

+ ?template_id=&layout_id=&start_label=">label_single_.pdf +

+
+

+ &template_id=&layout_id=">label_single_.csv +

+
+

+ &template_id=&layout_id=">label_single_.xml +

+
+ Label Batch Number + +

+ &template_id=&layout_id=&start_label=">label_batch_.pdf +

+
+

+ &template_id=&layout_id=">label_batch_.csv +

+
+

+ &template_id=&layout_id=">label_batch_.xml +

+
+
+
+
+ +
+
+
+ +
+
+ + Exporting label(s). + + Exporting label(s). + + batch(es) to export. + +
+
+
+ + " /> + + " /> + + + " /> + + + " /> + +
+ + + + + + + + + + + + + +
+ + + +
+ + + +
+ + + +
+
+
+
+ + +
+
+
+ +
+ diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/labels/label-profiles.tmpl b/koha-tmpl/intranet-tmpl/prog/en/modules/labels/label-profiles.tmpl deleted file mode 100644 index 59de2d5fc1..0000000000 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/labels/label-profiles.tmpl +++ /dev/null @@ -1,98 +0,0 @@ - -Koha › Tools › Labels - - - - - - - - - -
- -
-
-
- - - -
-
-

Printer Profiles

-
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Printer NamePaper BinTemplate NameOffset-HorizontalOffset-VerticalCreep-HorizontalCreep-VerticalEditDelete
- - - - - - - - - - - - - - - ">Edit - - ); return false;">Delete -
-
- -No Printer Profiles currently defined. - - -
-
- -
-
-
-
-
- -
-
- diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/labels/label-templates.tmpl b/koha-tmpl/intranet-tmpl/prog/en/modules/labels/label-templates.tmpl deleted file mode 100644 index 16ffa502c1..0000000000 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/labels/label-templates.tmpl +++ /dev/null @@ -1,72 +0,0 @@ -Koha › Tools › Labels - - - - - - - - -
- -
-
-
- -
-
- - -

Templates

-
- - - - - - - - - - - - - - - - - -
Template CodeDescriptionEditDeleteActive
- - - - - ">Edit - - ">Delete - - - " checked="checked" /> - - " /> - - -
-
- -
-
- -
-
- -
-
- -
-
-
- -
-
- diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/labels/result.tmpl b/koha-tmpl/intranet-tmpl/prog/en/modules/labels/result.tmpl index cae487c665..19db05c899 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/labels/result.tmpl +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/labels/result.tmpl @@ -1,143 +1,141 @@ -Koha › Barcodes and Labels › Search Results - - - + + //]]> + - -
-
-

Search results

- - - - - - -
,''); return false" />
- -" /> - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + +
- by
- [], , , ISBN: ,
+
+
+

Search results

+ + + +
+ ,''); return false" /> + +
+
+ + + + +
+
+ " /> + + + + - - - - - - - - - - - - - - - - - - - - -
+ + by
+ [], , , ISBN: ,
SelectItem Call NumberDate AccessionedBarcode


- ',, ''); return false" href="/cgi-bin/koha/barcodes/label-manager.pl?itemnumber=&batch_id=&op=add">Add
- - -
- +
"> + ',, ''); return false" href="/cgi-bin/koha/barcodes/label-edit-batch.pl?op=add&batch_id=&item_number=">Add +
+ +
+ +
- - - + diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/manage-marc-import.tmpl b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/manage-marc-import.tmpl index 933077538e..efc282718d 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/manage-marc-import.tmpl +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/manage-marc-import.tmpl @@ -37,9 +37,13 @@ › Batch - -
-

Label batch created, with id:

+ + +
+ +
+ +

diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/tools-home.tmpl b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/tools-home.tmpl index be817d9f78..e4229f3046 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/tools-home.tmpl +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/tools-home.tmpl @@ -20,13 +20,14 @@ -
Label and Patron Card Creator
-
Create printable labels and barcodes from catalog data and patron cards from patron data
+
Label Creator
+
Create printable labels and barcodes from catalog data
Quick Spine Label Creator
Enter a barcode to generate a printable spine label
+
For use with dedicated label printers
diff --git a/koha-tmpl/intranet-tmpl/prog/img/csv_icon.gif b/koha-tmpl/intranet-tmpl/prog/img/csv_icon.gif new file mode 100644 index 0000000000..ec17116e0a Binary files /dev/null and b/koha-tmpl/intranet-tmpl/prog/img/csv_icon.gif differ diff --git a/koha-tmpl/intranet-tmpl/prog/img/icon_xml.gif b/koha-tmpl/intranet-tmpl/prog/img/icon_xml.gif new file mode 100644 index 0000000000..779fc58d73 Binary files /dev/null and b/koha-tmpl/intranet-tmpl/prog/img/icon_xml.gif differ diff --git a/koha-tmpl/intranet-tmpl/prog/img/label-creator-image.png b/koha-tmpl/intranet-tmpl/prog/img/label-creator-image.png new file mode 100644 index 0000000000..ec693e731c Binary files /dev/null and b/koha-tmpl/intranet-tmpl/prog/img/label-creator-image.png differ diff --git a/koha-tmpl/intranet-tmpl/prog/img/pdficon_large.gif b/koha-tmpl/intranet-tmpl/prog/img/pdficon_large.gif new file mode 100644 index 0000000000..39673df7b4 Binary files /dev/null and b/koha-tmpl/intranet-tmpl/prog/img/pdficon_large.gif differ diff --git a/kohaversion.pl b/kohaversion.pl index a470909456..e45880ef2f 100644 --- a/kohaversion.pl +++ b/kohaversion.pl @@ -10,7 +10,7 @@ use strict; sub kohaversion { - our $VERSION = '3.01.00.052'; + our $VERSION = '3.01.00.053'; # version needs to be set this way # so that it can be picked up by Makefile.PL # during install diff --git a/labels/label-create-csv.pl b/labels/label-create-csv.pl new file mode 100755 index 0000000000..729cb88b4d --- /dev/null +++ b/labels/label-create-csv.pl @@ -0,0 +1,110 @@ +#!/usr/bin/perl + +use strict; +use warnings; + +use CGI; +use Text::CSV_XS; +use Data::Dumper; + +use C4::Debug; +use C4::Labels::Batch 1.000000; +use C4::Labels::Template 1.000000; +use C4::Labels::Layout 1.000000; +use C4::Labels::PDF 1.000000; +use C4::Labels::Label 1.000000; + +=head + +=cut + +my $cgi = new CGI; + +my $batch_id = $cgi->param('batch_id') if $cgi->param('batch_id'); +my $template_id = $cgi->param('template_id') || undef; +my $layout_id = $cgi->param('layout_id') || undef; +my @label_ids = $cgi->param('label_id') if $cgi->param('label_id'); +my @item_numbers = $cgi->param('item_number') if $cgi->param('item_number'); + +my $items = undef; + +my $csv_file = (@label_ids || @item_numbers ? "label_single_" . scalar(@label_ids || @item_numbers) : "label_batch_$batch_id"); +print $cgi->header(-type => 'application/vnd.sun.xml.calc', + -encoding => 'utf-8', + -attachment => "$csv_file.csv", + ); + + +my $batch = C4::Labels::Batch->retrieve(batch_id => $batch_id); +my $template = C4::Labels::Template->retrieve(template_id => $template_id, profile_id => 1); +my $layout = C4::Labels::Layout->retrieve(layout_id => $layout_id); + + +if (@label_ids) { + my $batch_items = $batch->get_attr('items'); + grep { + my $label_id = $_; + push(@{$items}, grep{$_->{'label_id'} == $label_id;} @{$batch_items}); + } @label_ids; +} +elsif (@item_numbers) { + grep { + push(@{$items}, {item_number => $_}); + } @item_numbers; +} +else { + $items = $batch->get_attr('items'); +} + +my $csv = Text::CSV_XS->new(); + +CSV_ITEMS: +foreach my $item (@$items) { + my $label = C4::Labels::Label->new( + batch_id => $batch_id, + item_number => $item->{'item_number'}, + format_string => $layout->get_attr('format_string'), + ); + my $csv_fields = $label->csv_data(); + if ($csv->combine(@$csv_fields)) { + print $csv->string() . "\n"; + } + else { + warn sprintf('Text::CSV_XS->combine() returned the following error: %s', $csv->error_input); + next CSV_ITEMS; + } +} + +exit(1); + +=head1 NAME + +labels/label-create-csv.pl - A script for creating a csv export of labels and label batches in Koha + +=head1 ABSTRACT + +This script provides the means of producing a csv of labels for items either individually, in groups, or in batches from within Koha. + +=head1 AUTHOR + +Chris Nighswonger + +=head1 COPYRIGHT + +Copyright 2009 Foundations Bible College. + +=head1 LICENSE + +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. + +You should have received a copy of the GNU General Public License along with Koha; if not, write to the Free Software Foundation, Inc., 59 Temple Place, +Suite 330, Boston, MA 02111-1307 USA + +=head1 DISCLAIMER OF WARRANTY + +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. + diff --git a/labels/label-create-layout.pl b/labels/label-create-layout.pl deleted file mode 100755 index 2f4a9f59ab..0000000000 --- a/labels/label-create-layout.pl +++ /dev/null @@ -1,73 +0,0 @@ -#!/usr/bin/perl - -use strict; -use CGI; -use C4::Auth; -use C4::Output; -use C4::Labels; -use C4::Context; -use HTML::Template::Pro; - -my $dbh = C4::Context->dbh; -my $query = new CGI; -my ( $template, $loggedinuser, $cookie ) = get_template_and_user( - { - template_name => "labels/label-create-layout.tmpl", - query => $query, - type => "intranet", - authnotrequired => 0, - flagsrequired => { catalogue => 1 }, - debug => 1, - } -); - -my $data = get_label_options(); -my $op = $query->param('op'); -my $layout_id = $query->param('layout_id'); - -my $active_template = GetActiveLabelTemplate(); -my @label_templates = GetAllLabelTemplates(); -my @printingtypes = get_printingtypes(); -my @layouts = get_layouts(); -my @barcode_types = get_barcode_types(); -my @batches = get_batches(); - -my @barcode_types = get_barcode_types($layout_id); -my @printingtypes = get_printingtypes($layout_id); -my $layout; -$layout = get_layout($layout_id) if($layout_id); - -$template->param( guidebox => 1 ) if ( $data->{'guidebox'} ); -$template->param( "papertype_$data->{'papertype'}" => 1 ); -$template->param( "$data->{'barcodetype'}_checked" => 1 ); -$template->param( "startrow" . $data->{'startrow'} . "_checked" => 1 ); - -$template->param( - op => $op, - active_template => $data->{'active_template'}, - label_templates => \@label_templates, - barcode_types => \@barcode_types, - printingtypes => \@printingtypes, - layout_loop => \@layouts, - batches => \@batches, - - id => $data->{'id'}, - barcodetype => $data->{'barcodetype'}, - papertype => $data->{'papertype'}, - tx_author => $data->{'author'}, - tx_barcode => $data->{'barcode'}, - tx_title => $data->{'title'}, - tx_subtitle => $data->{'subtitle'}, - tx_isbn => $data->{'isbn'}, - tx_issn => $data->{'issn'}, - tx_itemtype => $data->{'itemtype'}, - tx_dewey => $data->{'dewey'}, - tx_class => $data->{'class'}, - tx_subclass => $data->{'subclass'}, - tx_itemcallnumber => $data->{'itemcallnumber'}, - startlabel => $data->{'startlabel'}, - - fontsize => $active_template->{'fontsize'}, -); - -output_html_with_http_headers $query, $cookie, $template->output; diff --git a/labels/label-create-pdf.pl b/labels/label-create-pdf.pl new file mode 100755 index 0000000000..91dad00c77 --- /dev/null +++ b/labels/label-create-pdf.pl @@ -0,0 +1,225 @@ +#!/usr/bin/perl + +use strict; +use warnings; + +use CGI; + +use C4::Debug; +use C4::Labels::Batch 1.000000; +use C4::Labels::Template 1.000000; +use C4::Labels::Layout 1.000000; +use C4::Labels::PDF 1.000000; +use C4::Labels::Label 1.000000; + +my $cgi = new CGI; + +my $batch_id = $cgi->param('batch_id') if $cgi->param('batch_id'); +my $template_id = $cgi->param('template_id') || undef; +my $layout_id = $cgi->param('layout_id') || undef; +my $start_label = $cgi->param('start_label') || 1; +my @label_ids = $cgi->param('label_id') if $cgi->param('label_id'); +my @item_numbers = $cgi->param('item_number') if $cgi->param('item_number'); + +my $items = undef; + +my $pdf_file = (@label_ids || @item_numbers ? "label_single_" . scalar(@label_ids || @item_numbers) : "label_batch_$batch_id"); +print $cgi->header( -type => 'application/pdf', + -encoding => 'utf-8', + -attachment => "$pdf_file.pdf", + ); + +my $pdf = C4::Labels::PDF->new(InitVars => 0); +my $batch = C4::Labels::Batch->retrieve(batch_id => $batch_id); +my $template = C4::Labels::Template->retrieve(template_id => $template_id, profile_id => 1); +my $layout = C4::Labels::Layout->retrieve(layout_id => $layout_id); + +sub _calc_next_label_pos { + my ($row_count, $col_count, $llx, $lly) = @_; + if ($col_count lt $template->get_attr('cols')) { + $llx = ($llx + $template->get_attr('label_width') + $template->get_attr('col_gap')); + $col_count++; + } + else { + $llx = $template->get_attr('left_margin'); + if ($row_count eq $template->get_attr('rows')) { + $pdf->Page(); + $lly = ($template->get_attr('page_height') - $template->get_attr('top_margin') - $template->get_attr('label_height')); + $row_count = 1; + } + else { + $lly = ($lly - $template->get_attr('row_gap') - $template->get_attr('label_height')); + $row_count++; + } + $col_count = 1; + } + return ($row_count, $col_count, $llx, $lly); +} + +sub _print_text { + my $label_text = shift; + foreach my $text_line (@$label_text) { + my $pdf_font = $pdf->Font($text_line->{'font'}); + my $line = "BT /$pdf_font $text_line->{'font_size'} Tf $text_line->{'text_llx'} $text_line->{'text_lly'} Td ($text_line->{'line'}) Tj ET"; + $pdf->Add($line); + } +} + +$| = 1; + +# set the paper size +my $lowerLeftX = 0; +my $lowerLeftY = 0; +my $upperRightX = $template->get_attr('page_width'); +my $upperRightY = $template->get_attr('page_height'); + +$pdf->Compress(1); +$pdf->Mbox($lowerLeftX, $lowerLeftY, $upperRightX, $upperRightY); + +my ($row_count, $col_count, $llx, $lly) = $template->get_label_position($start_label); + +if (@label_ids) { + my $batch_items = $batch->get_attr('items'); + grep { + my $label_id = $_; + push(@{$items}, grep{$_->{'label_id'} == $label_id;} @{$batch_items}); + } @label_ids; +} +elsif (@item_numbers) { + grep { + push(@{$items}, {item_number => $_}); + } @item_numbers; +} +else { + $items = $batch->get_attr('items'); +} + +LABEL_ITEMS: +foreach my $item (@{$items}) { + my ($barcode_llx, $barcode_lly, $barcode_width, $barcode_y_scale_factor) = 0,0,0,0; + if ($layout->get_attr('printing_type') eq 'ALT') { # we process the ALT style printing type here because it is not an atomic printing type + my $label_a = C4::Labels::Label->new( + batch_id => $batch_id, + item_number => $item->{'item_number'}, + llx => $llx, + lly => $lly, + width => $template->get_attr('label_width'), + height => $template->get_attr('label_height'), + top_text_margin => $template->get_attr('top_text_margin'), + left_text_margin => $template->get_attr('left_text_margin'), + barcode_type => $layout->get_attr('barcode_type'), + printing_type => 'BIB', + guidebox => $layout->get_attr('guidebox'), + font => $layout->get_attr('font'), + font_size => $layout->get_attr('font_size'), + callnum_split => $layout->get_attr('callnum_split'), + justify => $layout->get_attr('text_justify'), + format_string => $layout->get_attr('format_string'), + text_wrap_cols => $layout->get_text_wrap_cols(label_width => $template->get_attr('label_width'), left_text_margin => $template->get_attr('left_text_margin')), + ); + my $label_a_text = $label_a->create_label(); + _print_text($label_a_text); + ($row_count, $col_count, $llx, $lly) = _calc_next_label_pos($row_count, $col_count, $llx, $lly); + my $label_b = C4::Labels::Label->new( + batch_id => $batch_id, + item_number => $item->{'item_number'}, + llx => $llx, + lly => $lly, + width => $template->get_attr('label_width'), + height => $template->get_attr('label_height'), + top_text_margin => $template->get_attr('top_text_margin'), + left_text_margin => $template->get_attr('left_text_margin'), + barcode_type => $layout->get_attr('barcode_type'), + printing_type => 'BAR', + guidebox => $layout->get_attr('guidebox'), + font => $layout->get_attr('font'), + font_size => $layout->get_attr('font_size'), + callnum_split => $layout->get_attr('callnum_split'), + justify => $layout->get_attr('text_justify'), + format_string => $layout->get_attr('format_string'), + text_wrap_cols => $layout->get_text_wrap_cols(label_width => $template->get_attr('label_width'), left_text_margin => $template->get_attr('left_text_margin')), + ); + my $label_b_text = $label_b->create_label(); + ($row_count, $col_count, $llx, $lly) = _calc_next_label_pos($row_count, $col_count, $llx, $lly); + next LABEL_ITEMS; + } + else { + } + my $label = C4::Labels::Label->new( + batch_id => $batch_id, + item_number => $item->{'item_number'}, + llx => $llx, + lly => $lly, + width => $template->get_attr('label_width'), + height => $template->get_attr('label_height'), + top_text_margin => $template->get_attr('top_text_margin'), + left_text_margin => $template->get_attr('left_text_margin'), + barcode_type => $layout->get_attr('barcode_type'), + printing_type => $layout->get_attr('printing_type'), + guidebox => $layout->get_attr('guidebox'), + font => $layout->get_attr('font'), + font_size => $layout->get_attr('font_size'), + callnum_split => $layout->get_attr('callnum_split'), + justify => $layout->get_attr('text_justify'), + format_string => $layout->get_attr('format_string'), + text_wrap_cols => $layout->get_text_wrap_cols(label_width => $template->get_attr('label_width'), left_text_margin => $template->get_attr('left_text_margin')), + ); + my $label_text = $label->create_label(); + _print_text($label_text) if $label_text; + ($row_count, $col_count, $llx, $lly) = _calc_next_label_pos($row_count, $col_count, $llx, $lly); + next LABEL_ITEMS; +} + +$pdf->End(); + +exit(1); + +=head1 NAME + +labels/label-create-pdf.pl - A script for creating a pdf export of labels and label batches in Koha + +=head1 ABSTRACT + +This script provides the means of producing a pdf of labels for items either individually, in groups, or in batches from within Koha. + +=head1 USAGE + +This script is intended to be called as a cgi script although it could be easily modified to accept command line parameters. The script accepts four single +parameters and two "multiple" parameters as follows: + + C A single valid batch id to export. + C A single valid template id to be applied to the current export. This parameter is manditory. + C A single valid layout id to be applied to the current export. This parameter is manditory. + C The number of the label on which to begin the export. This parameter is optional. + C A single valid label id to export. Multiple label ids may be submitted to export multiple labels. + C A single valid item number to export. Multiple item numbers may be submitted to export multiple items. + +B One of the C, C, or C parameters is manditory. However, do not pass a combination of them or bad things might result. + + example: + http://staff-client.kohadev.org/cgi-bin/koha/labels/label-create-pdf.pl?batch_id=1&template_id=1&layout_id=5&start_label=1 + +=head1 AUTHOR + +Chris Nighswonger + +=head1 COPYRIGHT + +Copyright 2009 Foundations Bible College. + +=head1 LICENSE + +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. + +You should have received a copy of the GNU General Public License along with Koha; if not, write to the Free Software Foundation, Inc., 59 Temple Place, +Suite 330, Boston, MA 02111-1307 USA + +=head1 DISCLAIMER OF WARRANTY + +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. + +=cut diff --git a/labels/label-create-profile.pl b/labels/label-create-profile.pl deleted file mode 100755 index f2eb49a89a..0000000000 --- a/labels/label-create-profile.pl +++ /dev/null @@ -1,103 +0,0 @@ -#!/usr/bin/perl - -use strict; -use CGI; -use C4::Auth; -use C4::Context; -use C4::Output; -use C4::Labels; -use HTML::Template::Pro; -use POSIX; - -use Data::Dumper; -#use Smart::Comments; - -my $dbh = C4::Context->dbh; -my $query = new CGI; -### $query - -my $op = $query->param('op'); - -my $prof_id = $query->param('prof_id'); -my $printername = $query->param('printername'); -my $paper_bin = $query->param('paper_bin'); -my $tmpl_id = $query->param('tmpl_id'); -my $offset_horz = $query->param('offset_horz'); -my $offset_vert = $query->param('offset_vert'); -my $creep_horz = $query->param('creep_horz'); -my $creep_vert = $query->param('creep_vert'); -my $units = $query->param('unit'); - -my @resultsloop; -my @tmpllist; - -my ( $template, $loggedinuser, $cookie ) = get_template_and_user( - { - template_name => "labels/label-create-profile.tmpl", - query => $query, - type => "intranet", - authnotrequired => 1, - flagsrequired => { catalogue => 1 }, - debug => 1, - } - ); - -if ( $op eq 'blank' || $op eq '' ) { - - my @units = ( - { unit => 'INCH', desc => 'Inches' }, - { unit => 'CM', desc => 'Centimeters' }, - { unit => 'MM', desc => 'Millimeters' }, - { unit => 'POINT', desc => 'Postscript Points' }, - ); - - my @tmpl = GetAllLabelTemplates(); - - foreach my $data (@tmpl) { - push ( @tmpllist, {tmpl_id => $data->{'tmpl_id'}, - tmpl_code => $data->{'tmpl_code'}} ); - } - - $template->param( - tmpllist => \@tmpllist, - unit => \@units, - ); - -} - -elsif ( $op eq 'Save' ) { - my $errmsg; - my $dberror = CreateProfile( - $prof_id, $printername, $paper_bin, $tmpl_id, $offset_horz, - $offset_vert, $creep_horz, $creep_vert, $units - ); - unless ( $dberror ) { - print $query->redirect("./label-profiles.pl"); - exit; - } - - # FIXME: This exposes all CGI vars. Surely there is a better way to do it? -fbcit - if ( $dberror =~ /Duplicate/ && $dberror =~ /$paper_bin/ ) { - $errmsg = "You cannot create duplicate profiles for $printername/$paper_bin. - Click the Back button on your browser and enter a different paper bin - for $printername."; - } - - else { - $errmsg = $dberror; - } - - $template->param ( - dberror => $dberror, - errmsg => $errmsg, - ); - - warn "DB error: $dberror"; -} - -elsif ( $op eq 'Cancel' ) { - print $query->redirect("./label-profiles.pl"); - exit; -} - -output_html_with_http_headers $query, $cookie, $template->output; diff --git a/labels/label-create-template.pl b/labels/label-create-template.pl deleted file mode 100755 index 1b7e5261ef..0000000000 --- a/labels/label-create-template.pl +++ /dev/null @@ -1,103 +0,0 @@ -#!/usr/bin/perl - -use strict; -use CGI; -use C4::Auth; -use C4::Context; -use C4::Output; -use C4::Labels; -use HTML::Template::Pro; -use POSIX; - -#use Data::Dumper; -#use Smart::Comments; - -my $dbh = C4::Context->dbh; -my $query = new CGI; -### $query - -my $tmpl_code = $query->param('tmpl_code'); -my $tmpl_desc = $query->param('tmpl_desc'); -my $page_height = $query->param('page_height'); -my $page_width = $query->param('page_width'); -my $label_height = $query->param('label_height'); -my $label_width = $query->param('label_width'); -my $topmargin = $query->param('topmargin'); -my $leftmargin = $query->param('leftmargin'); -my $cols = $query->param('cols'); -my $rows = $query->param('rows'); -my $colgap = $query->param('colgap'); -my $rowgap = $query->param('rowgap'); -my $units = $query->param('units'); -my $font = $query->param('fonts'); -my $fontsize = $query->param('fontsize'); - -my $batch_id = $query->param('batch_id'); - - -my $op = $query->param('op'); -my @resultsloop; - -my ( $template, $loggedinuser, $cookie ); - -if ( $op eq 'blank' ) { - - my @units = ( - { unit => 'INCH', desc => 'Inches' }, - { unit => 'CM', desc => 'Centimeters' }, - { unit => 'MM', desc => 'Millimeters' }, - { unit => 'POINT', desc => 'Postscript Points' }, - ); - - my @fonts = ( #FIXME: There is probably a way to discover what additional fonts are installed on a user's system and generate this list dynamically... - { font => 'TR', name => 'Times Roman' }, - { font => 'TB', name => 'Times Bold' }, - { font => 'TI', name => 'Times Italic' }, - { font => 'TBI', name => 'Times Bold Italic' }, - { font => 'C', name => 'Courier' }, - { font => 'CB', name => 'Courier Bold' }, - { font => 'CO', name => 'Courier Oblique' }, - { font => 'CBO', name => 'Courier Bold Oblique' }, - { font => 'H', name => 'Helvetica' }, - { font => 'HB', name => 'Helvetica Bold' }, - { font => 'HO', name => 'Helvetica Oblique' }, - { font => 'HBO', name => 'Helvetica Bold Oblique' }, - ); - - ( $template, $loggedinuser, $cookie ) = get_template_and_user( - { - template_name => "labels/label-create-template.tmpl", - query => $query, - type => "intranet", - authnotrequired => 1, - flagsrequired => { catalogue => 1 }, - debug => 1, - } - ); - - $template->param( - units => \@units, - fonts => \@fonts, - ); - -} - -elsif ( $op eq 'Create' ) { - CreateTemplate( - - $tmpl_code, $tmpl_desc, $page_width, - $page_height, $label_width, $label_height, $topmargin, - $leftmargin, $cols, $rows, $colgap, - $rowgap, $font, $fontsize, $units ); - - print $query->redirect("./label-templates.pl"); -exit; - -} - -elsif ( $op eq 'Cancel' ) { - print $query->redirect("./label-home.pl"); - exit; -} - -output_html_with_http_headers $query, $cookie, $template->output; diff --git a/labels/label-create-xml.pl b/labels/label-create-xml.pl new file mode 100755 index 0000000000..7e90b1f456 --- /dev/null +++ b/labels/label-create-xml.pl @@ -0,0 +1,119 @@ +#!/usr/bin/perl + +use strict; +use warnings; + +use CGI; +use XML::Simple; +use Data::Dumper; + +use C4::Debug; +use C4::Labels::Batch 1.000000; +use C4::Labels::Template 1.000000; +use C4::Labels::Layout 1.000000; +use C4::Labels::PDF 1.000000; +use C4::Labels::Label 1.000000; + +=head + +=cut + +my $cgi = new CGI; + +my $batch_id = $cgi->param('batch_id') if $cgi->param('batch_id'); +my $template_id = $cgi->param('template_id') || undef; +my $layout_id = $cgi->param('layout_id') || undef; +my @label_ids = $cgi->param('label_id') if $cgi->param('label_id'); +my @item_numbers = $cgi->param('item_number') if $cgi->param('item_number'); + +my $items = undef; + +my $xml_file = (@label_ids || @item_numbers ? "label_single_" . scalar(@label_ids || @item_numbers) : "label_batch_$batch_id"); +print $cgi->header(-type => 'text/xml', + -encoding => 'utf-8', + -attachment => "$xml_file.xml", + ); + +my $batch = C4::Labels::Batch->retrieve(batch_id => $batch_id); +my $template = C4::Labels::Template->retrieve(template_id => $template_id, profile_id => 1); +my $layout = C4::Labels::Layout->retrieve(layout_id => $layout_id); + + +if (@label_ids) { + my $batch_items = $batch->get_attr('items'); + grep { + my $label_id = $_; + push(@{$items}, grep{$_->{'label_id'} == $label_id;} @{$batch_items}); + } @label_ids; +} +elsif (@item_numbers) { + grep { + push(@{$items}, {item_number => $_}); + } @item_numbers; +} +else { + $items = $batch->get_attr('items'); +} + +my $xml = XML::Simple->new(); +my $xml_data = {'label' => []}; + +my $item_count = 0; + +XML_ITEMS: +foreach my $item (@$items) { + push(@{$xml_data->{'label'}}, {'item_number' => $item->{'item_number'}}); + my $label = C4::Labels::Label->new( + batch_id => $batch_id, + item_number => $item->{'item_number'}, + format_string => $layout->get_attr('format_string'), + ); + my $format_string = $layout->get_attr('format_string'); + my @data_fields = split(/, /, $format_string); + my $csv_data = $label->csv_data(); + for (my $i = 0; $i < (scalar(@data_fields) - 1); $i++) { + push(@{$xml_data->{'label'}[$item_count]->{$data_fields[$i]}}, $$csv_data[$i]); + } + $item_count++; +} + +#die "XML DATA:\n" . Dumper($xml_data); + +my $xml_out = $xml->XMLout($xml_data); +#die "XML OUT:\n" . Dumper($xml_out); +print $xml_out; + +exit(1); + +=head1 NAME + +labels/label-create-xml.pl - A script for creating a xml export of labels and label batches in Koha + +=head1 ABSTRACT + +This script provides the means of producing a xml of labels for items either individually, in groups, or in batches from within Koha. This particular script is provided more as +a demonstration of the multitude of formats Koha labels could be exported in based on the current Label Creator API. + +=head1 AUTHOR + +Chris Nighswonger + +=head1 COPYRIGHT + +Copyright 2009 Foundations Bible College. + +=head1 LICENSE + +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. + +You should have received a copy of the GNU General Public License along with Koha; if not, write to the Free Software Foundation, Inc., 59 Temple Place, +Suite 330, Boston, MA 02111-1307 USA + +=head1 DISCLAIMER OF WARRANTY + +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. + diff --git a/labels/label-edit-batch.pl b/labels/label-edit-batch.pl new file mode 100755 index 0000000000..35c38fb210 --- /dev/null +++ b/labels/label-edit-batch.pl @@ -0,0 +1,124 @@ +#!/usr/bin/perl +# +# Copyright 2006 Katipo Communications. +# Parts Copyright 2009 Foundations Bible College. +# +# This file is part of Koha. +# +# Koha is free software; you can redistribute it and/or modify it under the +# terms of the GNU General Public License as published by the Free Software +# Foundation; either version 2 of the License, or (at your option) any later +# version. +# +# Koha is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along with +# Koha; if not, write to the Free Software Foundation, Inc., 59 Temple Place, +# Suite 330, Boston, MA 02111-1307 USA + +use strict; +use warnings; +use vars qw($debug); + +use CGI; + +use C4::Auth qw(get_template_and_user); +use C4::Output qw(output_html_with_http_headers); +use C4::Branch qw(get_branch_code_from_name); +use C4::Labels::Lib 1.000000 qw(get_label_summary html_table); +use C4::Labels::Batch 1.000000; + +my $cgi = new CGI; +my ( $template, $loggedinuser, $cookie ) = get_template_and_user( + { + template_name => "labels/label-edit-batch.tmpl", + query => $cgi, + type => "intranet", + authnotrequired => 0, + flagsrequired => { catalogue => 1 }, + debug => 1, + } +); + +my $err = 0; +my $errstr = undef; +my $duplicate_count = undef; +my $duplicate_message = undef; +my $db_rows = {}; +my $batch = undef; +my $display_columns = [ {_label_number => {label => 'Label Number', link_field => 0}}, + {_summary => {label => 'Summary', link_field => 0}}, + {_item_type => {label => 'Item Type', link_field => 0}}, + {_barcode => {label => 'Barcode', link_field => 0}}, + {select => {label => 'Select', value => '_label_id'}}, + ]; +my $op = $cgi->param('op') || 'edit'; +my $batch_id = $cgi->param('element_id') || $cgi->param('batch_id') || undef; +my @label_ids = $cgi->param('label_id') if $cgi->param('label_id'); +my @item_numbers = $cgi->param('item_number') if $cgi->param('item_number'); + +my $branch_code = get_branch_code_from_name($template->param('LoginBranchname')); + +if ($op eq 'remove') { + $batch = C4::Labels::Batch->retrieve(batch_id => $batch_id); + foreach my $label_id (@label_ids) { + $err = $batch->remove_item($label_id); + } + $errstr = "item(s) not removed from batch $batch_id." if $err; +# Something like this would be nice to avoid problems with the browser's 'refresh' button, but it needs an error handling mechanism... +# print $cgi->redirect("label-edit-batch.pl?op=edit&batch_id=$batch_id"); +# exit; +} +elsif ($op eq 'delete') { + $err = C4::Labels::Batch::delete(batch_id => $batch_id, branch_code => $branch_code); + $errstr = "batch $batch_id was not deleted." if $err; +} +elsif ($op eq 'add') { + $batch = C4::Labels::Batch->retrieve(batch_id => $batch_id); + $batch = C4::Labels::Batch->new(branch_code => $branch_code) if $batch == -2; + if ($branch_code){ + foreach my $item_number (@item_numbers) { + $err = $batch->add_item($item_number); + } + $errstr = "item(s) not added to batch $batch_id." if $err; + } + else { + $err = 1; + $errstr = "items(s) not added, the error was: Branch is not set, you please set your branch before adding items to a batch"; + } +} +elsif ($op eq 'new') { + $batch = C4::Labels::Batch->new(branch_code => $branch_code); + $batch_id = $batch->get_attr('batch_id'); +} +elsif ($op eq 'de_duplicate') { + $batch = C4::Labels::Batch->retrieve(batch_id => $batch_id); + $duplicate_count = $batch->remove_duplicates(); + $duplicate_message = 1 if $duplicate_count != -1; + $errstr = "batch $batch_id not fully de-duplicated." if $duplicate_count == -1; +} +else { # edit + $batch = C4::Labels::Batch->retrieve(batch_id => $batch_id); +} + +my $items = $batch->get_attr('items'); +$db_rows = get_label_summary(items => $items, batch_id => $batch_id); + +my $table = html_table($display_columns, $db_rows); + +$template->param( + err => $err, + errstr => $errstr, + ) if ($err ne 0); + +$template->param( + op => $op, + batch_id => $batch_id, + table_loop => $table, + duplicate_message => $duplicate_message, + duplicate_count => $duplicate_count, + ); + +output_html_with_http_headers $cgi, $cookie, $template->output; diff --git a/labels/label-edit-layout.pl b/labels/label-edit-layout.pl index 17ecd7244e..f47e8e61d8 100755 --- a/labels/label-edit-layout.pl +++ b/labels/label-edit-layout.pl @@ -1,80 +1,169 @@ #!/usr/bin/perl +# +# Copyright 2006 Katipo Communications. +# Parts Copyright 2009 Foundations Bible College. +# +# This file is part of Koha. +# +# Koha is free software; you can redistribute it and/or modify it under the +# terms of the GNU General Public License as published by the Free Software +# Foundation; either version 2 of the License, or (at your option) any later +# version. +# +# Koha is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along with +# Koha; if not, write to the Free Software Foundation, Inc., 59 Temple Place, +# Suite 330, Boston, MA 02111-1307 USA use strict; +use warnings; + use CGI; -use C4::Auth; -use C4::Context; -use C4::Output; -use C4::Labels; -use HTML::Template::Pro; use POSIX; +use Text::CSV_XS; -#use Data::Dumper; -#use Smart::Comments; - -my $dbh = C4::Context->dbh; -my $query = new CGI; -my $layout_id = $query->param('layout_id'); - -### $query; +use C4::Auth qw(get_template_and_user); +use C4::Output qw(output_html_with_http_headers); +use C4::Labels::Lib 1.000000 qw(get_barcode_types get_label_types get_font_types get_text_justification_types); +use C4::Labels::Layout 1.000000; +my $cgi = new CGI; my ( $template, $loggedinuser, $cookie ) = get_template_and_user( { template_name => "labels/label-edit-layout.tmpl", - query => $query, + query => $cgi, type => "intranet", - authnotrequired => 1, + authnotrequired => 0, flagsrequired => { catalogue => 1 }, debug => 1, } ); -my $layout = get_layout($layout_id); -my @barcode_types = get_barcode_types($layout_id); -my @printingtypes = get_printingtypes($layout_id); -### @printingtypes -### $layout +my $op = $cgi->param('op') || $ARGV[0] || ''; +my $layout_id = $cgi->param('layout_id') || $cgi->param('element_id') || $ARGV[1] || ''; +my $layout = ''; - $layout_id = $layout->{'id'}; # has it changed since we set it above? --joe -my $layoutname = $layout->{'layoutname'}; -my $guidebox = $layout->{'guidebox'}; -my $startlabel = $layout->{'startlabel'}; +sub _set_selected { + my ($type_list, $object, $data_type) = @_; + SET_SELECTED: + foreach my $type (@$type_list) { + if ($layout->get_attr($data_type)) { + if ($type->{'type'} eq $layout->get_attr($data_type)) { + $type->{'selected'} = 1; + } + } + else { + $type->{'selected'} = 1; + last SET_SELECTED; + } + }; + return $type_list; +} -my @title = build_text_dropbox( $layout->{'title'} ); -my @subtitle = build_text_dropbox( $layout->{'subtitle'} ); -my @author = build_text_dropbox( $layout->{'author'} ); -my @barcode = build_text_dropbox( $layout->{'barcode'} ); -my @isbn = build_text_dropbox( $layout->{'isbn'} ); -my @issn = build_text_dropbox( $layout->{'issn'} ); -my @itemtype = build_text_dropbox( $layout->{'itemtype'} ); -my @dewey = build_text_dropbox( $layout->{'dewey'} ); -my @class = build_text_dropbox( $layout->{'class'} ); -my @subclass = build_text_dropbox( $layout->{'subclass'} ); -my @itemcallnumber = build_text_dropbox( $layout->{'itemcallnumber'} ); +sub _select_format_string { # generate field table based on format_string + my $format_string = shift; + $format_string =~ s/(?<=,) (?![A-Z][a-z][0-9])//g; # remove spaces between fields + my $table = []; + my $fields = []; + my ($row_index, $col_index, $field_index) = (0,0,0); + my $cols = 5; # number of columns to wrap on + my $csv = Text::CSV_XS->new({ allow_whitespace => 1 }); + my $status = $csv->parse($format_string); + my @text_fields = $csv->fields(); + warn sprintf('Error parsing format_string. Parser returned: %s', $csv->error_input()) if $csv->error_input(); + my $field_count = $#text_fields + 1; + POPULATE_TABLE: + foreach my $text_field (@text_fields) { + $$fields[$col_index] = {field_empty => 0, field_name => ($text_field . "_tbl"), field_label => $text_field, order => [{num => '', selected => 0}]}; + for (my $order_i = 1; $order_i <= $field_count; $order_i++) { + $$fields[$col_index]{'order'}[$order_i] = {num => $order_i, selected => ($field_index == $order_i-1 ? 1 : 0)}; + } + $col_index++; + $field_index++; + if ((($col_index > 0) && !($col_index % $cols)) || ($field_index == $field_count)) { # wrap to new row + if (($field_index == $field_count) && ($row_index > 0)) { # in this case fill out row with empty fields + while ($col_index < $cols) { + $$fields[$col_index] = {field_empty => 1, field_name => '', field_label => '', order => [{num => '', selected => 0}]}; + $col_index++; + } + $$table[$row_index] = {text_fields => $fields}; + last POPULATE_TABLE; + } + $$table[$row_index] = {text_fields => $fields}; + $row_index++; + $fields = []; + $col_index = 0; + } + } + return $table; +} -### @subclass +if ($op eq 'edit') { + warn sprintf("Error performing '%s': No 'layout_id' passed in.", $op) unless ($layout_id); + $layout = C4::Labels::Layout->retrieve(layout_id => $layout_id); + +} +elsif ($op eq 'save') { + my $format_string = ''; + if ($cgi->param('layout_choice') eq 'layout_table') { # translate the field table into a format_string + my @layout_table = (); + foreach my $cgi_param ($cgi->param()) { + if (($cgi_param =~ m/^(.*)_tbl$/) && ($cgi->param($cgi_param))) { + my $value = $cgi->param($cgi_param); + $layout_table[$value - 1] = $1; + } + } + @layout_table = grep {$_} @layout_table; # this removes numerically 'skipped' fields. ie. user omits a number in sequential order + $format_string = join ', ', @layout_table; + $cgi->param('format_string', $format_string); + } + my @params = ( + barcode_type => $cgi->param('barcode_type'), + printing_type => $cgi->param('printing_type'), + layout_name => $cgi->param('layout_name'), + guidebox => ($cgi->param('guidebox') ? 1 : 0), + font => $cgi->param('font'), + font_size => $cgi->param('font_size'), + callnum_split => ($cgi->param('callnum_split') ? 1 : 0), + text_justify => $cgi->param('text_justify'), + format_string => $cgi->param('format_string'), + ); + if ($layout_id) { # if a label_id was passed in, this is an update to an existing layout + $layout = C4::Labels::Layout->retrieve(layout_id => $layout_id); + $layout->set_attr(@params); + $layout->save(); + } + else { # if no label_id, this is a new layout so insert it + $layout = C4::Labels::Layout->new(@params); + $layout->save(); + } + print $cgi->redirect("label-manage.pl?label_element=layout"); + exit; +} +else { # if we get here, this is a new layout + $layout = C4::Labels::Layout->new(); +} + +my $barcode_types = _set_selected(get_barcode_types(), $layout, 'barcode_type'); +my $label_types = _set_selected(get_label_types(), $layout, 'printing_type'); +my $font_types = _set_selected(get_font_types(), $layout, 'font'); +my $text_justification_types = _set_selected(get_text_justification_types(), $layout, 'text_justify'); +my $select_text_fields = _select_format_string($layout->get_attr('format_string')); $template->param( - barcode_types => \@barcode_types, - printingtypes => \@printingtypes, - layoutname => $layoutname, - layout_id => $layout_id, - guidebox => $guidebox, - startlabel => $startlabel, - formatstring => $layout->{'formatstring'}, - callnum_split => $layout->{'callnum_split'}, - 'justify_' . $layout->{'text_justify'} => 1, - tx_title => \@title, - tx_subtitle => \@subtitle, - tx_author => \@author, - tx_isbn => \@isbn, - tx_issn => \@issn, - tx_itemtype => \@itemtype, - tx_dewey => \@dewey, - tx_barcode => \@barcode, - tx_classif => \@class, - tx_subclass => \@subclass, - tx_itemcallnumber => \@itemcallnumber, + barcode_types => $barcode_types, + label_types => $label_types, + font_types => $font_types, + text_justification_types => $text_justification_types, + field_table => $select_text_fields, + layout_id => $layout->get_attr('layout_id') > -1 ? $layout->get_attr('layout_id') : '', + layout_name => $layout->get_attr('layout_name'), + guidebox => $layout->get_attr('guidebox'), + font_size => $layout->get_attr('font_size'), + callnum_split => $layout->get_attr('callnum_split'), + format_string => $layout->get_attr('format_string'), ); - -output_html_with_http_headers $query, $cookie, $template->output; +output_html_with_http_headers $cgi, $cookie, $template->output; diff --git a/labels/label-edit-profile.pl b/labels/label-edit-profile.pl index 4643b1c9b2..ee99e32907 100755 --- a/labels/label-edit-profile.pl +++ b/labels/label-edit-profile.pl @@ -1,88 +1,105 @@ #!/usr/bin/perl +# +# Copyright 2006 Katipo Communications. +# Parts Copyright 2009 Foundations Bible College. +# +# This file is part of Koha. +# +# Koha is free software; you can redistribute it and/or modify it under the +# terms of the GNU General Public License as published by the Free Software +# Foundation; either version 2 of the License, or (at your option) any later +# version. +# +# Koha is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along with +# Koha; if not, write to the Free Software Foundation, Inc., 59 Temple Place, +# Suite 330, Boston, MA 02111-1307 USA use strict; +use warnings; + use CGI; -use C4::Auth; -use C4::Context; -use C4::Output; -use C4::Labels; -use HTML::Template::Pro; -use POSIX; -my $DEBUG = 0; -my $dbh = C4::Context->dbh; -my $query = new CGI; - -my $op = $query->param('op'); -my $prof_id = $query->param('prof_id'); -my $offset_horz = $query->param('offset_horz'); -my $offset_vert = $query->param('offset_vert'); -my $creep_horz = $query->param('creep_horz'); -my $creep_vert = $query->param('creep_vert'); -my $units = $query->param('unit'); +use C4::Auth qw(get_template_and_user); +use C4::Output qw(output_html_with_http_headers); +use C4::Labels::Lib 1.000000 qw(get_all_templates get_unit_values); +use C4::Labels::Profile 1.000000; +my $cgi = new CGI; my ( $template, $loggedinuser, $cookie ) = get_template_and_user( { template_name => "labels/label-edit-profile.tmpl", - query => $query, + query => $cgi, type => "intranet", - authnotrequired => 1, + authnotrequired => 0, flagsrequired => { catalogue => 1 }, debug => 1, } ); -if ($op eq '' || undef) { - my $prof = GetSinglePrinterProfile($prof_id); +my $op = $cgi->param('op'); +my $profile_id = $cgi->param('profile_id') || $cgi->param('element_id'); +my $profile = undef; +my $template_list = undef; +my @label_template = (); - my $tmpl = GetSingleLabelTemplate($prof->{'tmpl_id'}); +my $units = get_unit_values(); - if ( $DEBUG ) { - use Data::Dumper; - warn Dumper($prof); - warn Dumper($tmpl); - } - - my @units = ( - { unit => 'INCH', desc => 'Inches' }, - { unit => 'CM', desc => 'Centimeters' }, - { unit => 'MM', desc => 'Millimeters' }, - { unit => 'POINT', desc => 'Postscript Points' }, +if ($op eq 'edit') { + $profile = C4::Labels::Profile->retrieve(profile_id => $profile_id); + $template_list = get_all_templates(field_list => 'template_id,template_code, profile_id'); +} +elsif ($op eq 'save') { + my @params = ( + printer_name => $cgi->param('printer_name'), + paper_bin => $cgi->param('paper_bin'), + offset_horz => $cgi->param('offset_horz'), + offset_vert => $cgi->param('offset_vert'), + creep_horz => $cgi->param('creep_horz'), + creep_vert => $cgi->param('creep_vert'), + units => $cgi->param('units'), ); - - foreach my $unit (@units) { - if ( $unit->{'unit'} eq $prof->{'unit'} ) { - $unit->{'selected'} = 1; - } + if ($profile_id) { # if a label_id was passed in, this is an update to an existing layout + $profile = C4::Labels::Profile->retrieve(profile_id => $profile_id); + $profile->set_attr(@params); + $profile->save(); } - - $template->param( - - units => \@units, - - prof_id => $prof->{'prof_id'}, - printername => $prof->{'printername'}, - paper_bin => $prof->{'paper_bin'}, - tmpl_code => $tmpl->{'tmpl_code'}, - prof_code => $prof->{'prof_code'}, - offset_horz => $prof->{'offset_horz'}, - offset_vert => $prof->{'offset_vert'}, - creep_horz => $prof->{'creep_horz'}, - creep_vert => $prof->{'creep_vert'}, - ); -} - -elsif ($op eq 'Save') { - warn "Units are now $units"; - - SaveProfile( $prof_id, $offset_horz, $offset_vert, $creep_horz, $creep_vert, $units ); - print $query->redirect("./label-profiles.pl"); + else { # if no label_id, this is a new layout so insert it + $profile = C4::Labels::Profile->new(@params); + $profile->save(); + } + print $cgi->redirect("label-manage.pl?label_element=profile"); exit; } - -elsif ($op eq 'Cancel') { - print $query->redirect("./label-profiles.pl"); - exit; +else { # if we get here, this is a new layout + $profile = C4::Labels::Profile->new(); } -output_html_with_http_headers $query, $cookie, $template->output; +if ($profile_id) { + @label_template = grep{($_->{'profile_id'} == $profile->get_attr('profile_id')) && ($_->{'template_id'} == $profile->get_attr('template_id'))} @$template_list; +} + +foreach my $unit (@$units) { + if ($unit->{'type'} eq $profile->get_attr('units')) { + $unit->{'selected'} = 1; + } +} + +$template->param(profile_id => $profile->get_attr('profile_id')) if $profile->get_attr('profile_id') > 0; + +$template->param( + label_template => $label_template[0]->{'template_code'} || '', + printer_name => $profile->get_attr('printer_name'), + paper_bin => $profile->get_attr('paper_bin'), + offset_horz => $profile->get_attr('offset_horz'), + offset_vert => $profile->get_attr('offset_vert'), + creep_horz => $profile->get_attr('creep_horz'), + creep_vert => $profile->get_attr('creep_vert'), + units => $units, + op => $op, +); + +output_html_with_http_headers $cgi, $cookie, $template->output; diff --git a/labels/label-edit-template.pl b/labels/label-edit-template.pl index 47b6bd7246..038a164d34 100755 --- a/labels/label-edit-template.pl +++ b/labels/label-edit-template.pl @@ -1,123 +1,135 @@ #!/usr/bin/perl +# +# Copyright 2006 Katipo Communications. +# Parts Copyright 2009 Foundations Bible College. +# +# This file is part of Koha. +# +# Koha is free software; you can redistribute it and/or modify it under the +# terms of the GNU General Public License as published by the Free Software +# Foundation; either version 2 of the License, or (at your option) any later +# version. +# +# Koha is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along with +# Koha; if not, write to the Free Software Foundation, Inc., 59 Temple Place, +# Suite 330, Boston, MA 02111-1307 USA use strict; +use warnings; + use CGI; -use C4::Auth; -use C4::Context; -use C4::Output; -use C4::Labels; -use HTML::Template::Pro; -use POSIX; -# use Data::Dumper; - -my $dbh = C4::Context->dbh; -my $query = new CGI; - -my $tmpl_id = $query->param('tmpl_id'); - -my $width = $query->param('width'); -my $height = $query->param('height'); -my $topmargin = $query->param('topmargin'); -my $leftmargin = $query->param('leftmargin'); -my $columns = $query->param('columns'); -my $rows = $query->param('rows'); -my $colgap = $query->param('colgap'); -my $rowgap = $query->param('rowgap'); -my $prof_id = $query->param('prof_id'); +use C4::Auth qw(get_template_and_user); +use C4::Output qw(output_html_with_http_headers); +use C4::Labels::Lib 1.000000 qw(get_all_profiles get_unit_values); +use C4::Labels::Template 1.000000; +my $cgi = new CGI; my ( $template, $loggedinuser, $cookie ) = get_template_and_user( { template_name => "labels/label-edit-template.tmpl", - query => $query, + query => $cgi, type => "intranet", - authnotrequired => 1, + authnotrequired => 0, flagsrequired => { catalogue => 1 }, debug => 1, } ); -my $tmpl = GetSingleLabelTemplate($tmpl_id); -my $curprof = GetAssociatedProfile($tmpl_id); -my @prof = GetAllPrinterProfiles(); -my @proflist; +my $op = $cgi->param('op'); +my $template_id = $cgi->param('template_id') || $cgi->param('element_id'); +my $label_template = undef; +my $profile_list = undef; -# Generate an array of hashes containing possible profiles for given template and mark the currently associated one... +my $units = get_unit_values(); -foreach my $prof (@prof) { - if ( $prof->{'tmpl_id'} eq $tmpl->{'tmpl_id'} && $prof->{'prof_id'} eq $curprof->{'prof_id'} ) { - push ( @proflist, {prof_id => $prof->{'prof_id'}, - printername => $prof->{'printername'}, - paper_bin => $prof->{'paper_bin'}, - selected => 1} ); +if ($op eq 'edit') { + $label_template = C4::Labels::Template->retrieve(template_id => $template_id); + $profile_list = get_all_profiles(field_list => 'profile_id,printer_name,paper_bin',filter => "template_id=$template_id OR template_id=''"); +} +elsif ($op eq 'save') { + my @params = ( profile_id => $cgi->param('profile_id') || '', + template_code => $cgi->param('template_code'), + template_desc => $cgi->param('template_desc'), + page_width => $cgi->param('page_width'), + page_height => $cgi->param('page_height'), + label_width => $cgi->param('label_width'), + label_height => $cgi->param('label_height'), + top_text_margin => $cgi->param('top_text_margin'), + left_text_margin=> $cgi->param('left_text_margin'), + top_margin => $cgi->param('top_margin'), + left_margin => $cgi->param('left_margin'), + cols => $cgi->param('cols'), + rows => $cgi->param('rows'), + col_gap => $cgi->param('col_gap'), + row_gap => $cgi->param('row_gap'), + units => $cgi->param('units'), + ); + if ($template_id) { # if a label_id was passed in, this is an update to an existing layout + $label_template = C4::Labels::Template->retrieve(template_id => $template_id); + my $old_profile = C4::Labels::Profile->retrieve(profile_id => $label_template->get_attr('profile_id')); + my $new_profile = C4::Labels::Profile->retrieve(profile_id => $cgi->param('profile_id')); + if ($label_template->get_attr('template_id') != $new_profile->get_attr('template_id')) { + $new_profile->set_attr(template_id => $label_template->get_attr('template_id')); + $old_profile->set_attr(template_id => 0); + $new_profile->save(); + $old_profile->save(); + } + $label_template->set_attr(@params); + $label_template->save(); } - - elsif ( $prof->{'tmpl_id'} eq $tmpl->{'tmpl_id'} ) { - push ( @proflist, {prof_id => $prof->{'prof_id'}, - printername => $prof->{'printername'}, - paper_bin => $prof->{'paper_bin'}} ); + else { # if no label_id, this is a new layout so insert it + $label_template = C4::Labels::Template->new(@params); + my $template_id = $label_template->save(); + my $profile = C4::Labels::Profile->retrieve(profile_id => $cgi->param('profile_id')); + $profile->set_attr(template_id => $template_id) if $template_id != $profile->get_attr('template_id'); + $profile->save(); } - - elsif ( !$prof ) { - undef @proflist; + print $cgi->redirect("label-manage.pl?label_element=template"); + exit; +} +else { # if we get here, this is a new layout + $label_template = C4::Labels::Template->new(); +} +if ($template_id) { + foreach my $profile (@$profile_list) { + if ($profile->{'profile_id'} == $label_template->get_attr('profile_id')) { + $profile->{'selected'} = 1; + } + else { + $profile->{'selected'} = 0; + } } } -my @units = ( - { unit => 'INCH', desc => 'Inches' }, - { unit => 'CM', desc => 'Centimeters' }, - { unit => 'MM', desc => 'Millimeters' }, - { unit => 'POINT', desc => 'Postscript Points' }, -); - -foreach my $unit (@units) { - if ( $unit->{'unit'} eq $tmpl->{'units'} ) { +foreach my $unit (@$units) { + if ($unit->{'type'} eq $label_template->get_attr('units')) { $unit->{'selected'} = 1; } } -my @fonts = ( #FIXME: There is probably a way to discover what additional fonts are installed on a user's system and generate this list dynamically... - { font => 'TR', name => 'Times Roman' }, - { font => 'TB', name => 'Times Bold' }, - { font => 'TI', name => 'Times Italic' }, - { font => 'TBI', name => 'Times Bold Italic' }, - { font => 'C', name => 'Courier' }, - { font => 'CB', name => 'Courier Bold' }, - { font => 'CO', name => 'Courier Oblique' }, - { font => 'CBO', name => 'Courier Bold Oblique' }, - { font => 'H', name => 'Helvetica' }, - { font => 'HB', name => 'Helvetica Bold' }, - { font => 'HO', name => 'Helvetica Oblique' }, - { font => 'HBO', name => 'Helvetica Bold Oblique' }, -); - -foreach my $font (@fonts) { - if ( $font->{'font'} eq $tmpl->{'font'} ) { - $font->{'selected'} = 1; - } -} - $template->param( - - proflist => \@proflist, - units => \@units, - fonts => \@fonts, - - tmpl_id => $tmpl->{'tmpl_id'}, - tmpl_code => $tmpl->{'tmpl_code'}, - tmpl_desc => $tmpl->{'tmpl_desc'}, - page_width => $tmpl->{'page_width'}, - page_height => $tmpl->{'page_height'}, - label_width => $tmpl->{'label_width'}, - label_height => $tmpl->{'label_height'}, - topmargin => $tmpl->{'topmargin'}, - leftmargin => $tmpl->{'leftmargin'}, - cols => $tmpl->{'cols'}, - rows => $tmpl->{'rows'}, - colgap => $tmpl->{'colgap'}, - rowgap => $tmpl->{'rowgap'}, - fontsize => $tmpl->{'fontsize'}, - active => $tmpl->{'active'}, + profile_list => $profile_list, + template_id => ($label_template->get_attr('template_id') > 0) ? $label_template->get_attr('template_id') : '', + template_code => $label_template->get_attr('template_code'), + template_desc => $label_template->get_attr('template_desc'), + page_width => $label_template->get_attr('page_width'), + page_height => $label_template->get_attr('page_height'), + label_width => $label_template->get_attr('label_width'), + label_height => $label_template->get_attr('label_height'), + top_text_margin => $label_template->get_attr('top_text_margin'), + left_text_margin => $label_template->get_attr('left_text_margin'), + top_margin => $label_template->get_attr('top_margin'), + left_margin => $label_template->get_attr('left_margin'), + cols => $label_template->get_attr('cols'), + rows => $label_template->get_attr('rows'), + col_gap => $label_template->get_attr('col_gap'), + row_gap => $label_template->get_attr('row_gap'), + units => $units, ); -output_html_with_http_headers $query, $cookie, $template->output; +output_html_with_http_headers $cgi, $cookie, $template->output; diff --git a/labels/label-home.pl b/labels/label-home.pl index 76d55cd30c..e7563f164e 100755 --- a/labels/label-home.pl +++ b/labels/label-home.pl @@ -1,21 +1,36 @@ #!/usr/bin/perl +# +# Copyright 2006 Katipo Communications. +# Parts Copyright 2009 Foundations Bible College. +# +# This file is part of Koha. +# +# Koha is free software; you can redistribute it and/or modify it under the +# terms of the GNU General Public License as published by the Free Software +# Foundation; either version 2 of the License, or (at your option) any later +# version. +# +# Koha is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along with +# Koha; if not, write to the Free Software Foundation, Inc., 59 Temple Place, +# Suite 330, Boston, MA 02111-1307 USA use strict; +use warnings; + use CGI; -use C4::Auth; -use C4::Output; -use C4::Labels; -use C4::Output; -use C4::Context; -use HTML::Template::Pro; -# use Smart::Comments; +use C4::Auth qw(get_template_and_user); +use C4::Output qw(output_html_with_http_headers); -my $query = new CGI; +my $cgi = new CGI; my ( $template, $loggedinuser, $cookie ) = get_template_and_user( { template_name => "labels/label-home.tmpl", - query => $query, + query => $cgi, type => "intranet", authnotrequired => 0, flagsrequired => { catalogue => 1 }, @@ -23,64 +38,4 @@ my ( $template, $loggedinuser, $cookie ) = get_template_and_user( } ); -# little block for displaying active layout/template/batch in templates -# ---------- -my $batch_id = $query->param('batch_id'); -my $active_layout = get_active_layout(); -my $active_template = GetActiveLabelTemplate(); -my $active_layout_name = $active_layout->{'layoutname'}; -my $active_template_name = $active_template->{'tmpl_code'}; -# ---------- - -my $data = get_label_options(); -my $op = $query->param('op'); -my $layout_id = $query->param('layout_id'); - -my @label_templates = GetAllLabelTemplates(); -my @printingtypes = get_printingtypes(); -my @layouts = get_layouts(); -my @barcode_types = get_barcode_types(); -#my @batches = get_batches(); #This is not used afaics -fbcit - -if ($op eq 'delete_layout') { # had been assignment! serious error! - delete_layout($layout_id); -} - -### $data - -$template->param( guidebox => 1 ) if ( $data->{'guidebox'} ); -$template->param( "papertype_$data->{'papertype'}" => 1 ); -$template->param( "$data->{'barcodetype'}_checked" => 1 ); -$template->param( "startrow" . $data->{'startrow'} . "_checked" => 1 ); -$template->param( - op => $op, - active_layout_name => $active_layout_name, - active_template_name => $active_template_name, - - label_templates => \@label_templates, - barcode_types => \@barcode_types, - printingtypes => \@printingtypes, -layout_loop => \@layouts, - -#batches => \@batches, #This is not used afaics -fbcit - id => $data->{'id'}, - barcodetype => $data->{'barcodetype'}, - papertype => $data->{'papertype'}, - - tx_author => $data->{'author'}, - tx_barcode => $data->{'barcode'}, - tx_title => $data->{'title'}, - tx_isbn => $data->{'isbn'}, - tx_issn => $data->{'issn'}, - tx_itemtype => $data->{'itemtype'}, - tx_dewey => $data->{'dewey'}, - tx_class => $data->{'class'}, - tx_subclass => $data->{'subclass'}, - tx_itemcallnumber => $data->{'itemcallnumber'}, - - startlabel => $data->{'startlabel'}, - fontsize => $active_template->{'fontsize'}, - -); - -output_html_with_http_headers $query, $cookie, $template->output; +output_html_with_http_headers $cgi, $cookie, $template->output; diff --git a/labels/label-item-search.pl b/labels/label-item-search.pl index a04a9dc03a..633209d67b 100755 --- a/labels/label-item-search.pl +++ b/labels/label-item-search.pl @@ -1,5 +1,5 @@ #!/usr/bin/perl - +# # Copyright 2000-2002 Katipo Communications # # This file is part of Koha. @@ -19,26 +19,22 @@ use strict; use warnings; +use vars qw($debug $cgi_debug); use CGI; -use C4::Auth; -use HTML::Template::Pro; -use C4::Context; -use C4::Search; -use C4::Auth; -use C4::Output; -use C4::Biblio; -use C4::Items; -use C4::Acquisition; -use C4::Search; -use C4::Dates; -use C4::Koha; # XXX subfield_is_koha_internal_p -use C4::Debug; use List::Util qw( max min ); -use POSIX; +use POSIX qw(ceil); -#use Smart::Comments; -#use Data::Dumper; +use C4::Auth qw(get_template_and_user); +use C4::Output qw(output_html_with_http_headers); +use C4::Context; +use C4::Dates; +use C4::Search qw(SimpleSearch); +use C4::Biblio qw(TransformMarcToKoha); +use C4::Items qw(GetItemInfosOf get_itemnumbers_of); +use C4::Koha qw(GetItemTypes); # XXX subfield_is_koha_internal_p +use C4::Labels::Lib qw(html_table); +use C4::Debug; BEGIN { $debug = $debug || $cgi_debug; @@ -48,29 +44,26 @@ BEGIN { } } -# Creates a scrolling list with the associated default value. -# Using more than one scrolling list in a CGI assigns the same default value to all the -# scrolling lists on the page !?!? That's why this function was written. - my $query = new CGI; my $type = $query->param('type'); my $op = $query->param('op') || ''; my $batch_id = $query->param('batch_id'); my $ccl_query = $query->param('ccl_query'); - -my $dbh = C4::Context->dbh; - my $startfrom = $query->param('startfrom') || 1; -my ( $template, $loggedinuser, $cookie ); +my ($template, $loggedinuser, $cookie) = (undef, undef, undef); my ( $total_hits, $orderby, $results, $total, $error, $marcresults, $idx, $datefrom, $dateto, $ccl_textbox ); - my $resultsperpage = C4::Context->preference('numSearchResults') || '20'; - my $show_results = 0; +my $display_columns = [ {_add => {label => "Add Item", link_field => 1}}, + {_item_call_number => {label => "Call Number", link_field => 0}}, + {_date_accessioned => {label => "Accession Date", link_field => 0}}, + {_barcode => {label => "Barcode", link_field => 0}}, + {select => {label => "Select", value => "_item_number"}}, + ]; if ( $op eq "do_search" ) { $idx = $query->param('idx'); @@ -82,18 +75,6 @@ if ( $op eq "do_search" ) { $datefrom = $query->param('datefrom'); $dateto = $query->param('dateto'); - ( $template, $loggedinuser, $cookie ) = get_template_and_user( - { - template_name => "labels/result.tmpl", - query => $query, - type => "intranet", - authnotrequired => 0, - flagsrequired => { borrowers => 1 }, - flagsrequired => { catalogue => 1 }, - debug => 1, - } - ); - if ($datefrom) { $datefrom = C4::Dates->new($datefrom); $ccl_query .= ' and ' if $ccl_textbox; @@ -111,7 +92,7 @@ if ( $op eq "do_search" ) { ( $error, $marcresults, $total_hits ) = SimpleSearch( $ccl_query, $offset, $resultsperpage ); - if ($marcresults) { + if (scalar($marcresults) > 0) { $show_results = scalar @$marcresults; } else { @@ -123,71 +104,55 @@ if ( $op eq "do_search" ) { if ($show_results) { my $hits = $show_results; - my ( @results, @items ); - + my @results_set = (); + my @items =(); # This code needs to be refactored using these subs... #my @items = &GetItemsInfo( $biblio->{biblionumber}, 'intra' ); #my $dat = &GetBiblioData( $biblio->{biblionumber} ); for ( my $i = 0 ; $i < $hits ; $i++ ) { - + my @row_data= (); #DEBUG Notes: Decode the MARC record from each resulting MARC record... my $marcrecord = MARC::File::USMARC::decode( $marcresults->[$i] ); - #DEBUG Notes: Transform it to Koha form... my $biblio = TransformMarcToKoha( C4::Context->dbh, $marcrecord, '' ); - -# Begin building the hash for the template... -# I don't think we need this with the current template design, but I'm leaving it in place. -fbcit -#$biblio->{highlight} = ($i % 2)?(1):(0); -#DEBUG Notes: Stuff the bib into @results... - push @results, $biblio; + #DEBUG Notes: Stuff the bib into @biblio_data... + push (@results_set, $biblio); my $biblionumber = $biblio->{'biblionumber'}; - #DEBUG Notes: Grab the item numbers associated with this MARC record... my $itemnums = get_itemnumbers_of($biblionumber); - #DEBUG Notes: Retrieve the item data for each number... - my $iii = $itemnums->{$biblionumber}; - if ($iii) { + if (my $iii = $itemnums->{$biblionumber}) { my $item_results = GetItemInfosOf(@$iii); foreach my $item ( keys %$item_results ) { - -#DEBUG Notes: Build an array element 'item' of the correct bib (results) hash which contains item-specific data... - if ( $item_results->{$item}->{'biblionumber'} eq - $results[$i]->{'biblionumber'} ) - { - -# NOTE: The order of the elements in this array must be preserved or the table dependent on it will be incorrectly rendered. -# This is a real hack, but I can't think of a better way right now. -fbcit -# It is conceivable that itemcallnumber and/or barcode fields might be empty so the trinaries cover this possibility. - push @{ $results[$i]->{'item'} }, { i_itemnumber1 => - $item_results->{$item}->{'itemnumber'} }; - push @{ $results[$i]->{'item'} }, - { - i_itemcallnumber => ( - $item_results->{$item}->{'itemcallnumber'} - ? $item_results->{$item}->{'itemcallnumber'} - : 'NA' - ) - }; - push @{ $results[$i]->{'item'} }, { i_dateaccessioned => - $item_results->{$item}->{'dateaccessioned'} }; - push @{ $results[$i]->{'item'} }, - { - i_barcode => ( - $item_results->{$item}->{'barcode'} - ? $item_results->{$item}->{'barcode'} - : 'NA' - ) - }; - push @{ $results[$i]->{'item'} }, { i_itemnumber2 => - $item_results->{$item}->{'itemnumber'} }; + #DEBUG Notes: Build an array element 'item' of the correct bib (results) hash which contains item-specific data... + if ($item_results->{$item}->{'biblionumber'} eq $results_set[$i]->{'biblionumber'}) { + my $item_data->{'_item_number'} = $item_results->{$item}->{'itemnumber'}; + $item_data->{'_item_call_number'} = ($item_results->{$item}->{'itemcallnumber'} ? $item_results->{$item}->{'itemcallnumber'} : 'NA'); + $item_data->{'_date_accessioned'} = $item_results->{$item}->{'dateaccessioned'}; + $item_data->{'_barcode'} = ( $item_results->{$item}->{'barcode'} ? $item_results->{$item}->{'barcode'} : 'NA'); + $item_data->{'_add'} = $item_results->{$item}->{'itemnumber'}; + unshift (@row_data, $item_data); # item numbers are given to us in descending order by get_itemnumbers_of()... } } + $results_set[$i]->{'item_table'} = html_table($display_columns, \@row_data); + } + else { + # FIXME: Some error trapping code needed + warn sprintf('No item numbers retrieved for biblio number: %s', $biblionumber); } } - $debug and warn "**********\@results**********\n"; - $debug and warn Dumper(@results); + + ( $template, $loggedinuser, $cookie ) = get_template_and_user( + { + template_name => "labels/result.tmpl", + query => $query, + type => "intranet", + authnotrequired => 0, + flagsrequired => { borrowers => 1 }, + flagsrequired => { catalogue => 1 }, + debug => 1, + } + ); # build page nav stuff. my ( @field_data, @numbers ); @@ -242,7 +207,8 @@ if ($show_results) { ); $template->param( - result => \@results, + results => ($show_results ? 1 : 0), + result_set=> \@results_set, batch_id => $batch_id, type => $type, idx => $idx, diff --git a/labels/label-manage.pl b/labels/label-manage.pl new file mode 100755 index 0000000000..3ad95b3205 --- /dev/null +++ b/labels/label-manage.pl @@ -0,0 +1,113 @@ +#!/usr/bin/perl +# +# Copyright 2006 Katipo Communications. +# Parts Copyright 2009 Foundations Bible College. +# +# This file is part of Koha. +# +# Koha is free software; you can redistribute it and/or modify it under the +# terms of the GNU General Public License as published by the Free Software +# Foundation; either version 2 of the License, or (at your option) any later +# version. +# +# Koha is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along with +# Koha; if not, write to the Free Software Foundation, Inc., 59 Temple Place, +# Suite 330, Boston, MA 02111-1307 USA + +use strict; +use warnings; +use vars qw($debug); + +use CGI; +use Data::Dumper; + +use C4::Auth qw(get_template_and_user); +use C4::Output qw(output_html_with_http_headers); +use autouse 'C4::Branch' => qw(get_branch_code_from_name); +use C4::Labels::Lib 1.000000 qw(get_all_templates get_all_layouts get_all_profiles get_batch_summary html_table); +use C4::Labels::Layout 1.000000; +use C4::Labels::Template 1.000000; +use C4::Labels::Profile 1.000000; +use C4::Labels::Batch 1.000000; + +my $cgi = new CGI; +my ( $template, $loggedinuser, $cookie ) = get_template_and_user( + { + template_name => "labels/label-manage.tmpl", + query => $cgi, + type => "intranet", + authnotrequired => 0, + flagsrequired => { catalogue => 1 }, + debug => 1, + } +); + +my $error = 0; +my $db_rows = {}; +my $display_columns = { layout => [ # db column => {col label is link? + {layout_id => {label => 'Layout ID', link_field => 0}}, + {layout_name => {label => 'Layout', link_field => 0}}, + {barcode_type => {label => 'Barcode Type', link_field => 0}}, + {printing_type => {label => 'Print Type', link_field => 0}}, + {format_string => {label => 'Fields to Print',link_field => 0}}, + {select => {label => 'Select', value => 'layout_id'}}, + ], + template => [ {template_id => {label => 'Template ID', link_field => 0}}, + {template_code => {label => 'Template Name', link_field => 0}}, + {template_desc => {label => 'Description', link_field => 0}}, + {select => {label => 'Select', value => 'template_id'}}, + ], + profile => [ {profile_id => {label => 'Profile ID', link_field => 0}}, + {printer_name => {label => 'Printer Name', link_field => 0}}, + {paper_bin => {label => 'Paper Bin', link_field => 0}}, + {_template_code => {label => 'Template Name', link_field => 0}}, # this display column does not have a corrisponding db column in the profile table, hence the underscore + {select => {label => 'Select', value => 'profile_id'}}, + ], + batch => [ {batch_id => {label => 'Batch ID', link_field => 0}}, + {_item_count => {label => 'Item Count', link_field => 0}}, + {select => {label => 'Select', value => 'batch_id'}}, + ], +}; + +my $label_element = $cgi->param('label_element') || undef; +my $op = $cgi->param('op') || 'none'; +my $element_id = $cgi->param('element_id') || undef; + +my $branch_code = ($label_element eq 'batch' ? get_branch_code_from_name($template->param('LoginBranchname')) : ''); + +if ($op eq 'delete') { + if ($label_element eq 'layout') {$error = C4::Labels::Layout::delete(layout_id => $element_id);} + elsif ($label_element eq 'template') {$error = C4::Labels::Template::delete(template_id => $element_id);} + elsif ($label_element eq 'profile') {$error = C4::Labels::Profile::delete(profile_id => $element_id);} + elsif ($label_element eq 'batch') {$error = C4::Labels::Batch::delete(batch_id => $element_id, branch_code => $branch_code);} + else {} # FIXME: Some error trapping code +} + +if ($label_element eq 'layout') {$db_rows = get_all_layouts();} +elsif ($label_element eq 'template') {$db_rows = get_all_templates();} +elsif ($label_element eq 'profile') {$db_rows = get_all_profiles();} +elsif ($label_element eq 'batch') {$db_rows = get_batch_summary(filter => "branch_code=\'$branch_code\' OR branch_code=\'NB\'");} +else {} # FIXME: Some error trapping code + +my $table = html_table($display_columns->{$label_element}, $db_rows); + +$template->param(error => $error) if ($error ne 0); +$template->param(print => 1) if ($label_element eq 'batch'); +$template->param( + op => $op, + element_id => $element_id, + table_loop => $table, + label_element => $label_element, + label_element_title => ($label_element eq 'layout' ? 'Layouts' : + $label_element eq 'template' ? 'Templates' : + $label_element eq 'profile' ? 'Profiles' : + $label_element eq 'batch' ? 'Batches' : + '' + ), +); + +output_html_with_http_headers $cgi, $cookie, $template->output; diff --git a/labels/label-manager.pl b/labels/label-manager.pl deleted file mode 100755 index 08432caa8c..0000000000 --- a/labels/label-manager.pl +++ /dev/null @@ -1,192 +0,0 @@ -#!/usr/bin/perl - -use strict; -use CGI; -use C4::Auth; -use C4::Labels; -use C4::Output; -use HTML::Template::Pro; -#use POSIX qw(ceil); -#use Data::Dumper; -#use Smart::Comments; - -use vars qw($debug); - -BEGIN { - $debug = $ENV{DEBUG} || 0; -} - -my $dbh = C4::Context->dbh; -my $query = new CGI; -$query->param('debug') and $debug = $query->param('debug'); -my $op = $query->param('op'); -my $layout_id = $query->param('layout_id'); -my $layoutname = $query->param('layoutname'); -my $barcodetype = $query->param('barcodetype'); -my $bcn = $query->param('tx_barcode'); -my $title = $query->param('tx_title'); -my $subtitle = $query->param('tx_subtitle'); -my $isbn = $query->param('tx_isbn'); -my $issn = $query->param('tx_issn'); -my $itemtype = $query->param('tx_itemtype'); -my $itemcallnumber = $query->param('tx_itemcallnumber'); -my $author = $query->param('tx_author'); -my $tmpl_id = $query->param('tmpl_id'); -my $summary = $query->param('summary'); -my $startlabel = $query->param('startlabel'); -my $printingtype = $query->param('printingtype'); -my $guidebox = $query->param('guidebox'); -my $fontsize = $query->param('fontsize'); -my $callnum_split = $query->param('callnum_split'); -my $text_justify = $query->param('text_justify'); -my $formatstring = $query->param('formatstring'); -my $batch_type = $query->param('type'); -($batch_type and $batch_type eq 'patroncards') or $batch_type = 'labels'; -my @itemnumber; -($batch_type eq 'labels') ? (@itemnumber = $query->param('itemnumber')) : (@itemnumber = $query->param('borrowernumber')); - -# little block for displaying active layout/template/batch in templates -# ---------- -my $batch_id = $query->param('batch_id'); -my $active_layout = get_active_layout(); -my $active_template = GetActiveLabelTemplate(); -my $active_layout_name = $active_layout->{'layoutname'}; -my $active_template_name = $active_template->{'tmpl_code'}; -# ---------- - -#if (!$batch_id ) { -# $batch_id = get_highest_batch(); -#} - -#my $batch_type = "labels"; #FIXME: Hardcoded for testing/development... -my @messages; -my ($itemnumber) = @itemnumber if (scalar(@itemnumber) == 1); - -my ( $template, $loggedinuser, $cookie ) = get_template_and_user( - { - template_name => "labels/label-manager.tmpl", - query => $query, - type => "intranet", - authnotrequired => 0, - flagsrequired => { catalogue => 1 }, - debug => 1, - } -); - -if ( $op eq 'save_layout' ) { - save_layout( - $barcodetype, $title, $subtitle, $isbn, - $issn, $itemtype, $bcn, $text_justify, - $callnum_split, $itemcallnumber, $author, - $tmpl_id, $printingtype, $guidebox, $startlabel, $layoutname, - , $formatstring , $layout_id - ); - ### $layoutname - print $query->redirect("label-home.pl"); - exit; -} -elsif ( $op eq 'add_layout' ) { - add_layout( - $barcodetype, $title, $subtitle, $isbn, - $issn, $itemtype, $bcn, $text_justify, - $callnum_split, $itemcallnumber, $author, - $tmpl_id, $printingtype, $guidebox, $startlabel, $layoutname, - $formatstring , $layout_id - ); - ### $layoutname - print $query->redirect("label-home.pl"); - exit; -} - -# FIXME: The trinary conditionals here really need to be replaced with a more robust form of db abstraction -fbcit - -elsif ( $op eq 'add' ) { # add item - my $query2 = ($batch_type eq 'patroncards') ? - "INSERT INTO patroncards (borrowernumber, batch_id) values (?,?)" : - "INSERT INTO labels (itemnumber, batch_id) values (?,?)" ; - my $sth2 = $dbh->prepare($query2); - for my $inum (@itemnumber) { - # warn "INSERTing " . (($batch_type eq 'labels') ? 'itemnumber' : 'borrowernumber') . ":$inum for batch $batch_id"; - $sth2->execute($inum, $batch_id); - } -} -elsif ( $op eq 'deleteall' ) { - my $query2 = "DELETE FROM $batch_type"; - my $sth2 = $dbh->prepare($query2); - $sth2->execute(); -} -elsif ( $op eq 'delete' ) { - my @labelids = $query->param((($batch_type eq 'labels') ? 'labelid' : 'cardid')); - scalar @labelids or push @messages, (($batch_type eq 'labels') ? "ERROR: No labelid(s) supplied for deletion." : "ERROR: No cardid(s) supplied for deletion."); - my $ins = "?," x (scalar @labelids); - $ins =~ s/\,$//; - my $query2 = "DELETE FROM $batch_type WHERE " . (($batch_type eq 'labels') ? 'labelid' : 'cardid') ." IN ($ins) "; - $debug and push @messages, "query2: $query2 -- (@labelids)"; - my $sth2 = $dbh->prepare($query2); - $sth2->execute(@labelids); -} -elsif ( $op eq 'delete_batch' ) { - delete_batch($batch_id, $batch_type); - print $query->redirect("label-manager.pl?type=$batch_type"); - exit; -} -elsif ( $op eq 'add_batch' ) { - $batch_id= add_batch($batch_type); -} -elsif ( $op eq 'set_active_layout' ) { - set_active_layout($layout_id); - print $query->redirect("label-home.pl"); - exit; -} -elsif ( $op eq 'deduplicate' ) { - warn "\$batch_id=$batch_id and \$batch_type=$batch_type"; - my ($return, $dberror) = deduplicate_batch($batch_id, $batch_type); - my $msg = (($return) ? "Removed $return" : "Error removing") . " duplicate items from Batch $batch_id." . (($dberror) ? " Database returned: $dberror" : ""); - push @messages, $msg; -} - -# first lets do a read of the labels table , to get the a list of the -# currently entered items to be prinited -my @batches = get_batches($batch_type); -my @resultsloop = ($batch_type eq 'labels') ? GetLabelItems($batch_id) : GetPatronCardItems($batch_id); -#warn "$batches[0] (id $batch_id)"; -#warn Dumper(@resultsloop); - -#calc-ing number of sheets -#my $number_of_results = scalar @resultsloop; -#my $sheets_needed = ceil( ( --$number_of_results + $startrow ) / 8 ); # rounding up -#my $tot_labels = ( $sheets_needed * 8 ); -#my $start_results = ( $number_of_results + $startrow ); -#my $labels_remaining = ( $tot_labels - $start_results ); - -if (scalar @messages) { - $template->param(message => 1); - my @complex = (); - foreach (@messages) { - my %hash = (message_text => $_); - push @complex, \%hash; - } - $template->param(message_loop => \@complex); -} -if ($batch_type eq 'labels' or $batch_type eq 'patroncards') { - $template->param("batch_is_$batch_type" => 1); -} -$template->param( - batch_type => $batch_type, - batch_id => $batch_id, - batch_count => scalar @resultsloop, - active_layout_name => $active_layout_name, - active_template_name => $active_template_name, - outputformat => ( $active_layout->{'printingtype'} eq 'CSV' ) ? 'csv' : 'pdf' , - layout_tx => ( $active_layout->{'formatstring'}) ? 0 : 1 , - layout_string => ( $active_layout->{'formatstring'}) ? 1 : 0 , - - resultsloop => \@resultsloop, - batches => \@batches, - tmpl_desc => $active_template->{'tmpl_desc'}, - - # startrow => $startrow, - # sheets => $sheets_needed, - # labels_remaining => $labels_remaining, -); -output_html_with_http_headers $query, $cookie, $template->output; diff --git a/labels/label-print-csv.pl b/labels/label-print-csv.pl deleted file mode 100755 index be29afa5a5..0000000000 --- a/labels/label-print-csv.pl +++ /dev/null @@ -1,55 +0,0 @@ -#!/usr/bin/perl - -use strict; -use CGI; -use C4::Labels; -use C4::Auth; -use C4::Output; -use C4::Context; -use C4::Biblio; -use Text::CSV_XS; - -my $DEBUG = 0; -my $DEBUG_LPT = 0; - -my $htdocs_path = C4::Context->config('intrahtdocs'); -my $cgi = new CGI; - - -# get the printing settings -my $template = GetActiveLabelTemplate(); -my $conf_data = get_label_options(); - -my $batch_id = $cgi->param('batch_id'); -my $exportname = 'koha_label_' . $batch_id . '.csv'; - -print $cgi->header(-type => 'application/vnd.sun.xml.calc', - -encoding => 'utf-8', - -attachment => $exportname, - -filename => $exportname ); - -my $batch_type = $conf_data->{'type'}; -my $barcodetype = $conf_data->{'barcodetype'}; -my $printingtype = $conf_data->{'printingtype'}; - -my @resultsloop = GetLabelItems($batch_id); -my $csv = Text::CSV_XS->new(); -my @str_fields = get_text_fields($conf_data->{'id'}, 'codes' ); -for my $item (@resultsloop) { - my $record = GetMarcBiblio($item->{biblionumber}); - my @datafields = map { C4::Labels::GetBarcodeData($_->{'code'},$item,$record) } @str_fields ; - my $csvout ; - if($csv->combine(@datafields)) { - $csvout = $csv->string(); - print "$csvout\n"; - } else { - warn "CSV ERROR: " . $csv->error_input; - } - -} # end for item loop - -exit(1); -# is that the right way to do this ? - - - diff --git a/labels/label-print-pdf.pl b/labels/label-print-pdf.pl deleted file mode 100755 index 3534af2f30..0000000000 --- a/labels/label-print-pdf.pl +++ /dev/null @@ -1,260 +0,0 @@ -#!/usr/bin/perl - -use strict; -use warnings; - -use CGI; -use C4::Labels; # GetActiveLabelTemplate get_label_options GetAssociatedProfile -# GetPatronCardItems GetLabelItems GetUnitsValue... -use C4::Auth; -use C4::Output; -use C4::Context; -use C4::Members; -use C4::Branch; -use HTML::Template::Pro; -use PDF::Reuse; -use PDF::Reuse::Barcode; -use POSIX; # ceil -use Data::Dumper; - -my $DEBUG = 0; -my $DEBUG_LPT = 0; - -my $cgi = new CGI; - -#### Tons of Initialization #### -# get the printing settings -my $template = GetActiveLabelTemplate(); -my $conf_data = get_label_options() or die "get_label_options failed"; -my $profile = GetAssociatedProfile($template->{'tmpl_id'}); - -my $batch_id = $cgi->param('batch_id'); -my @resultsloop; - -my $batch_type = $conf_data->{'type'}; -my $barcodetype = $conf_data->{'barcodetype'}; -my $printingtype = $conf_data->{'printingtype'} or die "No printingtype in conf_data"; -my $guidebox = $conf_data->{'guidebox'}; -my $start_label = $conf_data->{'startlabel'}; -if ($cgi->param('startlabel')) { - $start_label = $cgi->param('startlabel'); # A bit of a hack to allow setting the starting label from the address bar... -fbcit -} -warn "Starting on label #$start_label" if $DEBUG; -my $units = $template->{'units'}; - -if ($printingtype eq 'PATCRD') { - @resultsloop = GetPatronCardItems($batch_id); -} else { - @resultsloop = GetLabelItems($batch_id); -} - -#warn "UNITS $units"; -#warn "fontsize = $fontsize"; -#warn Dumper $template; - -my $unitvalue = GetUnitsValue($units); -my $prof_unitvalue = GetUnitsValue($profile->{'unit'}); - -warn "Template units: $units which converts to $unitvalue PostScript Points" if $DEBUG; -warn "Profile units: $profile->{'unit'} which converts to $prof_unitvalue PostScript Points" if $DEBUG; - -my $tmpl_code = $template->{'tmpl_code'}; -my $tmpl_desc = $template->{'tmpl_desc'}; - -my $page_height = ( $template->{'page_height'} * $unitvalue ); -my $page_width = ( $template->{'page_width'} * $unitvalue ); -my $label_height = ( $template->{'label_height'} * $unitvalue ); -my $label_width = ( $template->{'label_width'} * $unitvalue ); -my $spine_width = ( $template->{'label_width'} * $unitvalue ); -my $circ_width = ( $template->{'label_width'} * $unitvalue ); -my $top_margin = ( $template->{'topmargin'} * $unitvalue ); -my $left_margin = ( $template->{'leftmargin'} * $unitvalue ); -my $colspace = ( $template->{'colgap'} * $unitvalue ); -my $rowspace = ( $template->{'rowgap'} * $unitvalue ); - -warn "Converted dimensions are:" if $DEBUG; -warn "pghth=$page_height, pgwth=$page_width, lblhth=$label_height, lblwth=$label_width, spinwth=$spine_width, circwth=$circ_width, tpmar=$top_margin, lmar=$left_margin, colsp=$colspace, rowsp=$rowspace" if $DEBUG; - -my $label_cols = $template->{'cols'}; -my $label_rows = $template->{'rows'}; - -my $margin = $top_margin; -my $left_text_margin = 3; # FIXME: This value should not be hardcoded -my $str; - -# Some peritent notes from PDF::Reuse regarding prFont()... -# If a font wasn't found, Helvetica will be set. -# These names are always recognized: Times-Roman, Times-Bold, Times-Italic, Times-BoldItalic, Courier, Courier-Bold, -# Courier-Oblique, Courier-BoldOblique, Helvetica, Helvetica-Bold, Helvetica-Oblique, Helvetica-BoldOblique -# They can be abbreviated: TR, TB, TI, TBI, C, CB, CO, CBO, H, HB, HO, HBO - -my $fontsize = $template->{'fontsize'}; -my $fontname = $template->{'font'}; - -my $text_wrap_cols = GetTextWrapCols( $fontname, $fontsize, $label_width, $left_text_margin ); - -#warn $label_cols, $label_rows; - -# set the paper size -my $lowerLeftX = 0; -my $lowerLeftY = 0; -my $upperRightX = $page_width; -my $upperRightY = $page_height; -my $codetype; # = 'Code39'; - -warn "Active profile: " . ($profile->{prof_id} || "None") if $DEBUG; - -#### PRINT PRELIMINARY DATA #### -print $cgi->header( -type => 'application/pdf', -attachment => 'barcode.pdf' ); - # Don't print header until very last possible moment - # That way if error or die occurs, fatals_to_browser will still work. - # After we print this header, there is no way back to HTML. All we can do is deliver PDF. -prInitVars(); -$| = 1; -prFile(); # No args means to STDOUT -prCompress(1); # turn on zip compression which dramatically reduces file size -prMbox( $lowerLeftX, $lowerLeftY, $upperRightX, $upperRightY ); - -# drawbox( $lowerLeftX, $lowerLeftY, $upperRightX, $upperRightY ); #do page border -# draw margin box for alignment page -drawbox($left_margin, $top_margin, $page_width-(2*$left_margin), $page_height-(2*$top_margin)) if $DEBUG_LPT; - - -#### TWEAKS and DEBUGGING ### -# Adjustments for image position and creep -fbcit -# NOTE: *All* of these factor in to image position and creep. Keep this in mind when makeing adjustments. -# Suggested proceedure: Adjust margins until both top and left margins are correct. Then adjust the label -# height and width to correct label creep across and down page. Units are PostScript Points (72 per inch). - -sub debug_drop { - my $title = @_ || ""; - warn "-------------------------$title-----------------------------\n" - . " top margin = $top_margin points\n" - . " left margin = $left_margin points\n" - . "label height = $label_height points\n" - . "label width = $label_width points\n"; -} - -debug_drop('INITIAL VALUES') if ($DEBUG); - -if ( $profile->{'prof_id'} ) { - $top_margin += ($profile->{'offset_vert'} * $prof_unitvalue); # controls vertical offset - $label_height += ($profile->{'creep_vert'} * $prof_unitvalue); # controls vertical creep - $left_margin += ($profile->{'offset_horz'} * $prof_unitvalue); # controls horizontal offset - $label_width += ($profile->{'creep_horz'} * $prof_unitvalue); # controls horizontal creep -} - -if ($DEBUG) { - if ($profile->{'prof_id'}) { - debug_drop('ADJUSTED VALUES'); - } else { - warn "No profile associated so no adjustment applied."; - } -} - -#warn " $lowerLeftX, $lowerLeftY, $upperRightX, $upperRightY"; -#warn "$label_rows, $label_cols\n"; -#warn "$label_height, $label_width\n"; -#warn "$page_height, $page_width\n"; - -my ($rowcount, $colcount, $x_pos, $y_pos, $rowtemp, $coltemp); - -if ( $start_label and $start_label == 1 ) { - $rowcount = 1; - $colcount = 1; - $x_pos = $left_margin; - $y_pos = ( $page_height - $top_margin - $label_height ); -} else { - $rowcount = ceil( $start_label / $label_cols ); - $colcount = ( $start_label - ( ( $rowcount - 1 ) * $label_cols ) ); - $x_pos = $left_margin + ( $label_width * ( $colcount - 1 ) ) + - ( $colspace * ( $colcount - 1 ) ); - $y_pos = $page_height - $top_margin - ( $label_height * $rowcount ) - - ( $rowspace * ( $rowcount - 1 ) ); - $DEBUG and warn "Start label: $start_label. Beginning in row $rowcount, column $colcount\n" - . "(X,Y) positions = ($x_pos,$y_pos)\n" - . "Rowspace = $rowspace, Label height = $label_height"; -} - -# -#### main foreach loop #### -# - -foreach my $item (@resultsloop) { - warn "Label parameters: xpos=$x_pos, ypos=$y_pos, lblwid=$label_width, lblhig=$label_height" if $DEBUG; - - drawbox($x_pos, $y_pos, $label_width, $label_height) if $guidebox; # regardless of printingtype - - if ( $printingtype eq 'BAR' ) { - DrawBarcode( $x_pos, $y_pos, $label_height, $label_width, $item->{'barcode'}, $barcodetype ); - } - elsif ( $printingtype eq 'BARBIB' ) { - # reposoitioning barcode up the top of label - my $barcode_height = ($label_height / 1.5 ); ## scaling voodoo - my $text_height = $label_height / 2; - my $barcode_y = $y_pos + ( $label_height / 2.5 ); ## scaling voodoo - - DrawBarcode( $x_pos, $barcode_y, $barcode_height, $label_width, $item->{'barcode'}, $barcodetype ); - DrawSpineText( $x_pos, $y_pos, $label_height, $label_width, $fontname, $fontsize, - $left_text_margin, $text_wrap_cols, \$item, \$conf_data, $printingtype ); - } # correct - elsif ( $printingtype eq 'BIBBAR' ) { - my $barcode_height = $label_height / 2; - DrawBarcode( $x_pos, $y_pos, $barcode_height, $label_width, $item->{'barcode'}, $barcodetype ); - DrawSpineText( $x_pos, $y_pos, $label_height, $label_width, $fontname, $fontsize, - $left_text_margin, $text_wrap_cols, \$item, \$conf_data, $printingtype ); - } - elsif ( $printingtype eq 'ALT' ) { - DrawBarcode( $x_pos, $y_pos, $label_height, $label_width, $item->{'barcode'}, $barcodetype ); - CalcNextLabelPos(); - drawbox( $x_pos, $y_pos, $label_width, $label_height ) if $guidebox; - DrawSpineText( $x_pos, $y_pos, $label_height, $label_width, $fontname, $fontsize, - $left_text_margin, $text_wrap_cols, \$item, \$conf_data, $printingtype ); - } - elsif ( $printingtype eq 'BIB' ) { - DrawSpineText( $x_pos, $y_pos, $label_height, $label_width, $fontname, $fontsize, - $left_text_margin, $text_wrap_cols, \$item, \$conf_data, $printingtype ); - } - elsif ( $printingtype eq 'PATCRD' ) { - my $patron_data = $item; - #FIXME: This needs to be paramatized and passed in from the user... - #Each element of this hash is a separate line on the patron card. Keys are the text to print and the associated data is the point size. - my $text = { - $patron_data->{'description'} => $fontsize, - $patron_data->{'branchname'} => ($fontsize + 3), - }; - $DEBUG and warn "Generating patron card for cardnumber $patron_data->{'cardnumber'}"; - my $barcode_height = $label_height / 2.75; #FIXME: Scaling barcode height; this needs to be a user parameter. - DrawBarcode( $x_pos, $y_pos, $barcode_height, $label_width, $patron_data->{'cardnumber'}, $barcodetype ); - DrawPatronCardText( $x_pos, $y_pos, $label_height, $label_width, $fontname, $fontsize, - $left_text_margin, $text_wrap_cols, $text, $printingtype ); - } - else { - die "CANNOT PRINT: Unknown printingtype '$printingtype'"; - } - - CalcNextLabelPos(); # regardless of printingtype -} # end for item loop -prEnd(); - -sub CalcNextLabelPos { - if ($colcount < $label_cols) { - # warn "new col"; - $x_pos = ( $x_pos + $label_width + $colspace ); - $colcount++; - } else { - $x_pos = $left_margin; - if ($rowcount == $label_rows) { - # warn "new page"; - prPage(); - $y_pos = ( $page_height - $top_margin - $label_height ); - $rowcount = 1; - } else { - # warn "new row"; - $y_pos = ( $y_pos - $rowspace - $label_height ); - $rowcount++; - } - $colcount = 1; - } -} - diff --git a/labels/label-print.pl b/labels/label-print.pl new file mode 100755 index 0000000000..0168e4a05d --- /dev/null +++ b/labels/label-print.pl @@ -0,0 +1,131 @@ +#!/usr/bin/perl +# +# Copyright 2009 Foundations Bible College. +# +# This file is part of Koha. +# +# Koha is free software; you can redistribute it and/or modify it under the +# terms of the GNU General Public License as published by the Free Software +# Foundation; either version 2 of the License, or (at your option) any later +# version. +# +# Koha is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along with +# Koha; if not, write to the Free Software Foundation, Inc., 59 Temple Place, +# Suite 330, Boston, MA 02111-1307 USA + +use strict; +use warnings; + +use CGI; +use Data::Dumper; + +use C4::Auth qw(get_template_and_user); +use C4::Output qw(output_html_with_http_headers); +use C4::Labels::Lib 1.000000 qw(get_all_templates get_all_layouts get_label_output_formats); +use C4::Labels::Batch 1.000000; + +my $cgi = new CGI; +my ( $template, $loggedinuser, $cookie ) = get_template_and_user( + { + template_name => "labels/label-print.tmpl", + query => $cgi, + type => "intranet", + authnotrequired => 0, + flagsrequired => { catalogue => 1 }, + debug => 1, + } +); + +my $op = $cgi->param('op') || 'none'; +my @label_ids = $cgi->param('label_id') if $cgi->param('label_id'); # this will handle individual label printing +my @batch_ids = $cgi->param('batch_id') if $cgi->param('batch_id'); +my $layout_id = $cgi->param('layout_id') || undef; +my $template_id = $cgi->param('template_id') || undef; +my $start_label = $cgi->param('start_label') || 1; +my @item_numbers = $cgi->param('item_number') if $cgi->param('item_number'); +my $output_format = $cgi->param('output_format') || 'pdf'; +my $referer = $cgi->param('referer') || undef; + +my $layouts = undef; +my $templates = undef; +my $label_output_formats = undef; +my @batches = (); +my $multi_batch_count = scalar(@batch_ids); +my $label_count = scalar(@label_ids); +my $item_count = scalar(@item_numbers); + +if ($op eq 'export') { + if (@label_ids) { + my $label_id_param = '&label_id='; + $label_id_param .= join ('&label_id=',@label_ids); + push (@batches, {create_script => ($output_format eq 'pdf' ? 'label-create-pdf.pl' : 'label-create-csv.pl'), + batch_id => $batch_ids[0], + template_id => $template_id, + layout_id => $layout_id, + start_label => $start_label, + label_ids => $label_id_param, + label_count => scalar(@label_ids), + }); + $template->param( + batches => \@batches, + referer => $referer, + ); + } + elsif (@item_numbers) { + my $item_number_param = '&item_number='; + $item_number_param .= join ('&item_number=',@item_numbers); + push (@batches, {create_script => ($output_format eq 'pdf' ? 'label-create-pdf.pl' : 'label-create-csv.pl'), + template_id => $template_id, + layout_id => $layout_id, + start_label => $start_label, + item_numbers => $item_number_param, + label_count => scalar(@item_numbers), + }); + $template->param( + batches => \@batches, + referer => $referer, + ); + } + elsif (@batch_ids) { + foreach my $batch_id (@batch_ids) { + push (@batches, {create_script => ($output_format eq 'pdf' ? 'label-create-pdf.pl' : 'label-create-csv.pl'), + batch_id => $batch_id, + template_id => $template_id, + layout_id => $layout_id, + start_label => $start_label, + }); + } + $template->param( + batches => \@batches, + referer => $referer, + ); + } +} +elsif ($op eq 'none') { + # setup select menus for selecting layout and template for this run... + $referer = $ENV{'HTTP_REFERER'}; + $referer =~ s/^.*?:\/\/.*?(\/.*)$/$1/m; + @batch_ids = grep{$_ = {batch_id => $_}} @batch_ids; + @label_ids = grep{$_ = {label_id => $_}} @label_ids; + @item_numbers = grep{$_ = {item_number => $_}} @item_numbers; + $templates = get_all_templates(field_list => 'template_id, template_code'); + $layouts = get_all_layouts(field_list => 'layout_id, layout_name'); + $label_output_formats = get_label_output_formats(); + $template->param( + batch_ids => \@batch_ids, + label_ids => \@label_ids, + item_numbers => \@item_numbers, + templates => $templates, + layouts => $layouts, + label_output_formats => $label_output_formats, + multi_batch_count => $multi_batch_count, + label_count => $label_count, + item_count => $item_count, + referer => $referer, + ); +} +output_html_with_http_headers $cgi, $cookie, $template->output; diff --git a/labels/label-profiles.pl b/labels/label-profiles.pl deleted file mode 100755 index cc4c9036cb..0000000000 --- a/labels/label-profiles.pl +++ /dev/null @@ -1,63 +0,0 @@ -#!/usr/bin/perl - -use strict; -use CGI; -use C4::Auth; -use C4::Context; -use C4::Output; -use C4::Labels; -use HTML::Template::Pro; -use POSIX; - - -my $dbh = C4::Context->dbh; -my $query = new CGI; -my $op = $query->param('op'); -#my $prof_code = $query->param('prof_code'); -my $prof_id = $query->param('prof_id'); -#my $printername = $query->param('printername'); -#my $tmpl_id = $query->param('tmpl_id'); -#my $paper_bin = $query->param('paper_bin'); -#my $offset_horz = $query->param('offset_horz'); -#my $offset_vert = $query->param('offset_vert'); -#my $creep_horz = $query->param('creep_horz'); -#my $creep_vert = $query->param('creep_vert'); - -# little block for displaying active layout/template/batch in templates -# ---------- -my $batch_id = $query->param('batch_id'); -my $active_layout = get_active_layout(); -my $active_template = GetActiveLabelTemplate(); -my $active_layout_name = $active_layout->{'layoutname'}; -my $active_template_name = $active_template->{'tmpl_code'}; -# ---------- - -my ( $template, $loggedinuser, $cookie ) = get_template_and_user( - { - template_name => "labels/label-profiles.tmpl", - query => $query, - type => "intranet", - authnotrequired => 1, - flagsrequired => { catalogue => 1 }, - debug => 1, - } -); - -my @resultsloop; - -if ( $op eq 'delete' ) { - my $dberror = DeleteProfile($prof_id); - warn "DB returned error: $dberror" if $dberror; -} - -@resultsloop = GetAllPrinterProfiles(); - -$template->param( - batch_id => $batch_id, - active_layout_name => $active_layout_name, - active_template_name => $active_template_name, - - resultsloop => \@resultsloop, -); - -output_html_with_http_headers $query, $cookie, $template->output; diff --git a/labels/label-save-template.pl b/labels/label-save-template.pl deleted file mode 100755 index 492379023c..0000000000 --- a/labels/label-save-template.pl +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/perl - -use strict; -use CGI; -use C4::Auth; -use C4::Context; -use C4::Output; -use C4::Labels; -use HTML::Template::Pro; -use POSIX; - -#use Data::Dumper; -#use Smart::Comments; - - -my $dbh = C4::Context->dbh; -my $query = new CGI; - -my $tmpl_id = $query->param('tmpl_id'); -my $tmpl_code = $query->param('tmpl_code'); -my $tmpl_desc = $query->param('tmpl_desc'); -my $page_height = $query->param('page_height'); -my $page_width = $query->param('page_width'); -my $label_height = $query->param('label_height'); -my $label_width = $query->param('label_width'); -my $topmargin = $query->param('topmargin'); -my $leftmargin = $query->param('leftmargin'); -my $cols = $query->param('cols'); -my $rows = $query->param('rows'); -my $colgap = $query->param('colgap'); -my $rowgap = $query->param('rowgap'); -my $font = $query->param('fonts'); -my $fontsize = $query->param('fontsize'); -my $units = $query->param('units'); -my $active = $query->param('active'); -my $prof_id = $query->param('prof_id'); - -my $dberror = SaveTemplate( - - $tmpl_id, $tmpl_code, $tmpl_desc, $page_width, - $page_height, $label_width, $label_height, $topmargin, - $leftmargin, $cols, $rows, $colgap, - $rowgap, $font, $fontsize, $units - -); - -SetAssociatedProfile( $prof_id, $tmpl_id ) if $prof_id; - -warn "Database returned the following error: $dberror" if $dberror; - -print $query->redirect("./label-templates.pl"); - - diff --git a/labels/label-templates.pl b/labels/label-templates.pl deleted file mode 100755 index 04570fdc9b..0000000000 --- a/labels/label-templates.pl +++ /dev/null @@ -1,77 +0,0 @@ -#!/usr/bin/perl - -use strict; -use CGI; -use C4::Auth; -use C4::Context; -use C4::Output; -use C4::Labels; -use HTML::Template::Pro; -use POSIX; - -#use Data::Dumper; - -my $dbh = C4::Context->dbh; -my $query = new CGI; -my $op = $query->param('op'); -my $tmpl_code = $query->param('tmpl_code'); -my $tmpl_id = $query->param('tmpl_id'); - - -my $width = $query->param('width'); -my $height = $query->param('height'); -my $topmargin = $query->param('topmargin'); -my $leftmargin = $query->param('leftmargin'); -my $columns = $query->param('columns'); -my $rows = $query->param('rows'); -my $colgap = $query->param('colgap'); -my $rowgap = $query->param('rowgap'); - -my ( $template, $loggedinuser, $cookie ) = get_template_and_user( - { - template_name => "labels/label-templates.tmpl", - query => $query, - type => "intranet", - authnotrequired => 1, - flagsrequired => { catalogue => 1 }, - debug => 1, - } -); - - -my @resultsloop; - - -if ( $op eq 'set_active_template' ) { - SetActiveTemplate($tmpl_id); -} - -elsif ( $op eq 'delete' ) { - DeleteTemplate($tmpl_id); -} - -elsif ( $op eq 'save' ) { - SaveTemplate($tmpl_code); -} - - @resultsloop = GetAllLabelTemplates(); - -# little block for displaying active layout/template/batch in templates -# ---------- -my $batch_id = $query->param('batch_id'); -my $active_layout = get_active_layout(); -my $active_template = GetActiveLabelTemplate(); -my $active_layout_name = $active_layout->{'layoutname'}; -my $active_template_name = $active_template->{'tmpl_code'}; -# ---------- - -$template->param( - - batch_id => $batch_id, - active_layout_name => $active_layout_name, - active_template_name => $active_template_name, - - resultsloop => \@resultsloop, -); - -output_html_with_http_headers $query, $cookie, $template->output; diff --git a/t/db_dependent/Labels/t_Batch.t b/t/db_dependent/Labels/t_Batch.t new file mode 100644 index 0000000000..9fb4a84148 --- /dev/null +++ b/t/db_dependent/Labels/t_Batch.t @@ -0,0 +1,82 @@ +#!/usr/bin/perl +# +# Copyright 2007 Foundations Bible College. +# +# This file is part of Koha. +# +# Koha is free software; you can redistribute it and/or modify it under the +# terms of the GNU General Public License as published by the Free Software +# Foundation; either version 2 of the License, or (at your option) any later +# version. +# +# Koha is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along with +# Koha; if not, write to the Free Software Foundation, Inc., 59 Temple Place, +# Suite 330, Boston, MA 02111-1307 USA + +use strict; +use warnings; + +use Test::More tests => 22; +use C4::Context; +use Data::Dumper; + +BEGIN { + use_ok('C4::Labels::Batch'); +} + +my $sth = C4::Context->dbh->prepare('SELECT branchcode FROM branches b LIMIT 0,1'); +$sth->execute(); +my $branch_code = $sth->fetchrow_hashref()->{'branchcode'}; +diag sprintf('Database returned the following error: %s', $sth->errstr) if $sth->errstr; +my $expected_batch = { + items => [], + branch_code => $branch_code, + batch_stat => 0, # False if any data has changed and the db has not been updated + }; + +my $batch = 0; +my $item_number = 0; + +diag "Testing Batch->new() method."; +ok($batch = C4::Labels::Batch->new(branch_code => $branch_code)) || diag "Batch->new() FAILED."; +my $batch_id = $batch->get_attr('batch_id'); +$expected_batch->{'batch_id'} = $batch_id; +is_deeply($batch, $expected_batch) || diag "New batch object FAILED to verify."; + +diag "Testing Batch->get_attr() method."; +foreach my $key (keys %{$expected_batch}) { + if (ref($expected_batch->{$key}) eq 'ARRAY') { + ok(ref($expected_batch->{$key}) eq ref($batch->get_attr($key))) || diag "Batch->get_attr() FAILED on attribute $key."; + } + else { + ok($expected_batch->{$key} eq $batch->get_attr($key)) || diag "Batch->get_attr() FAILED on attribute $key."; + } +} + +diag "Testing Batch->add_item() method."; +my $sth1 = C4::Context->dbh->prepare('SELECT itemnumber FROM items LIMIT 0,10'); +$sth1->execute(); +while (my $row = $sth1->fetchrow_hashref()) { + diag sprintf('Database returned the following error: %s', $sth1->errstr) if $sth1->errstr; + ok($batch->add_item($row->{'itemnumber'}) eq 0 ) || diag "Batch->add_item() FAILED."; + $item_number = $row->{'itemnumber'}; +} + +diag "Testing Batch->retrieve() method."; +ok(my $saved_batch = C4::Labels::Batch->retrieve(batch_id => $batch_id)) || diag "Batch->retrieve() FAILED."; +is_deeply($saved_batch, $batch) || diag "Retrieved batch object FAILED to verify."; + +diag "Testing Batch->remove_item() method."; + +ok($batch->remove_item($item_number) eq 0) || diag "Batch->remove_item() FAILED."; +my $updated_batch = C4::Labels::Batch->retrieve(batch_id => $batch_id); +is_deeply($updated_batch, $batch) || diag "Updated batch object FAILED to verify."; + +diag "Testing Batch->delete() method."; + +my $del_results = $batch->delete(); +ok($del_results eq 0) || diag "Batch->delete() FAILED."; diff --git a/t/db_dependent/Labels/t_Layout.t b/t/db_dependent/Labels/t_Layout.t new file mode 100644 index 0000000000..dce4f95f51 --- /dev/null +++ b/t/db_dependent/Labels/t_Layout.t @@ -0,0 +1,100 @@ +#!/usr/bin/perl +# +# Copyright 2007 Foundations Bible College. +# +# This file is part of Koha. +# +# Koha is free software; you can redistribute it and/or modify it under the +# terms of the GNU General Public License as published by the Free Software +# Foundation; either version 2 of the License, or (at your option) any later +# version. +# +# Koha is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along with +# Koha; if not, write to the Free Software Foundation, Inc., 59 Temple Place, +# Suite 330, Boston, MA 02111-1307 USA + +use strict; +use warnings; + +use Test::More tests => 28; +use C4::Context; +use Data::Dumper; + +BEGIN { + use_ok('C4::Labels::Layout'); +} + +my $default_layout = { + barcode_type => 'CODE39', + printing_type => 'BAR', + layout_name => 'TEST', + guidebox => 0, + font => 'TR', + font_size => 3, + callnum_split => 0, + text_justify => 'L', + format_string => 'title, author, isbn, issn, itemtype, barcode, callnumber', + }; + +my $layout; + +diag "Testing Layout->new() method."; +ok($layout = C4::Labels::Layout->new(layout_name => 'TEST')) || diag "Layout->new() FAILED"; +is_deeply($layout, $default_layout) || diag "New layout object FAILED to verify."; + +diag "Testing Layout->get_attr() method."; +foreach my $key (keys %{$default_layout}) { + ok($default_layout->{$key} eq $layout->get_attr($key)) || diag "Layout->get_attr() FAILED on attribute $key."; +} + +diag "Testing Layout->set_attr() method."; +my $new_attr = { + barcode_type => 'CODE39', + printing_type => 'BIBBAR', + layout_name => 'TEST', + guidebox => 1, + font => 'TR', + font_size => 10, + callnum_split => 1, + text_justify => 'L', + format_string => 'callnumber, title, author, barcode', + }; + +foreach my $key (keys %{$new_attr}) { + $layout->set_attr($key => $new_attr->{$key}); + ok($new_attr->{$key} eq $layout->get_attr($key)) || diag "Layout->set_attr() FAILED on attribute $key."; +} + +diag "Testing Layout->save() method with a new object."; + +my $sav_results = $layout->save(); +ok($sav_results ne -1) || diag "Layout->save() FAILED"; + +my $saved_layout; +if ($sav_results ne -1) { + diag "Testing Layout->retrieve() method."; + $new_attr->{'layout_id'} = $sav_results; + ok($saved_layout = C4::Labels::Layout->retrieve(layout_id => $sav_results)) || diag "Layout->retrieve() FAILED"; + is_deeply($saved_layout, $new_attr) || diag "Retrieved layout object FAILED to verify."; +} + +diag "Testing Layout->save() method with an updated object."; + +$saved_layout->set_attr(font => 'C'); +my $upd_results = $saved_layout->save(); +ok($upd_results ne -1) || diag "Layout->save() FAILED"; +my $updated_layout = C4::Labels::Layout->retrieve(layout_id => $sav_results); +is_deeply($updated_layout, $saved_layout) || diag "Updated layout object FAILED to verify."; + +diag "Testing Layout->get_text_wrap_cols() method."; + +ok($updated_layout->get_text_wrap_cols(label_width => 180, left_text_margin => 18) eq 21) || diag "Layout->get_text_wrap_cols() FAILED."; + +diag "Testing Layout->delete() method."; + +my $del_results = $updated_layout->delete(); +ok($del_results eq 0) || diag "Layout->delete() FAILED"; diff --git a/t/db_dependent/Labels/t_Profile.t b/t/db_dependent/Labels/t_Profile.t new file mode 100644 index 0000000000..110e9eb356 --- /dev/null +++ b/t/db_dependent/Labels/t_Profile.t @@ -0,0 +1,95 @@ +#!/usr/bin/perl +# +# Copyright 2007 Foundations Bible College. +# +# This file is part of Koha. +# +# Koha is free software; you can redistribute it and/or modify it under the +# terms of the GNU General Public License as published by the Free Software +# Foundation; either version 2 of the License, or (at your option) any later +# version. +# +# Koha is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along with +# Koha; if not, write to the Free Software Foundation, Inc., 59 Temple Place, +# Suite 330, Boston, MA 02111-1307 USA + +use strict; +use warnings; + +use Test::More tests => 25; +use C4::Context; +use Data::Dumper; + +BEGIN { + use_ok('C4::Labels::Profile'); +} + +my $expected_profile = { + printer_name => 'Circulation Desk', + template_id => '', + paper_bin => 'bypass', + offset_horz => 0, + offset_vert => 0, + creep_horz => 0, + creep_vert => 0, + units => 'POINT', +}; + +my $err = 0; + +diag "Testing Profile->new() method."; +ok(my $profile = C4::Labels::Profile->new(printer_name => 'Circulation Desk',paper_bin => 'bypass')) || diag"Profile->new() FAILED."; +is_deeply($profile, $expected_profile) || diag "New profile object FAILED to verify."; + +diag "Testing Profile->get_attr() method."; +foreach my $key (keys %{$expected_profile}) { + ok($expected_profile->{$key} eq $profile->get_attr($key)) || diag "Profile->get_attr() FAILED on attribute $key."; +} + +diag "Testing Profile->set_attr() method."; +my $new_attr = { + printer_name => 'Cataloging Desk', + template_id => '1', + paper_bin => 'tray 1', + offset_horz => 0.3, + offset_vert => 0.85, + creep_horz => 0.156, + creep_vert => 0.67, + units => 'INCH', +}; + +foreach my $key (keys %{$new_attr}) { + $err = $profile->set_attr($key, $new_attr->{$key}); + ok(($new_attr->{$key} eq $profile->get_attr($key)) && ($err lt 1)) || diag "Profile->set_attr() FAILED on attribute $key."; +} + +diag "Testing Profile->save() method with a new object."; + +my $sav_results = $profile->save(); +ok($sav_results ne -1) || diag "Profile->save() FAILED."; + +my $saved_profile; +if ($sav_results ne -1) { + diag "Testing Profile->retrieve() method."; + $new_attr->{'profile_id'} = $sav_results; + ok($saved_profile = C4::Labels::Profile->retrieve(profile_id => $sav_results)) || diag "Profile->retrieve() FAILED."; + is_deeply($saved_profile, $new_attr) || diag "Retrieved profile object FAILED to verify."; +} + +diag "Testing Profile->save() method with an updated object."; + +$err = 0; # Reset error code +$err = $saved_profile->set_attr(units => 'CM'); +my $upd_results = $saved_profile->save(); +ok(($upd_results ne -1) && ($err lt 1)) || diag "Profile->save() FAILED."; +my $updated_profile = C4::Labels::Profile->retrieve(profile_id => $sav_results); +is_deeply($updated_profile, $saved_profile) || diag "Updated layout object FAILED to verify."; + +diag "Testing Profile->delete() method."; + +my $del_results = $updated_profile->delete(); +ok($del_results ne -1) || diag "Profile->delete() FAILED."; diff --git a/t/db_dependent/Labels/t_Template.t b/t/db_dependent/Labels/t_Template.t new file mode 100644 index 0000000000..3a7af280b2 --- /dev/null +++ b/t/db_dependent/Labels/t_Template.t @@ -0,0 +1,133 @@ +#!/usr/bin/perl +# +# Copyright 2007 Foundations Bible College. +# +# This file is part of Koha. +# +# Koha is free software; you can redistribute it and/or modify it under the +# terms of the GNU General Public License as published by the Free Software +# Foundation; either version 2 of the License, or (at your option) any later +# version. +# +# Koha is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along with +# Koha; if not, write to the Free Software Foundation, Inc., 59 Temple Place, +# Suite 330, Boston, MA 02111-1307 USA + +use strict; +use warnings; + +use Test::More tests => 52; +use C4::Context; +use Data::Dumper; + +BEGIN { + use_ok('C4::Labels::Template'); +} + +my $expect_template = { + profile_id => 0, + template_code => 'DEFAULT TEMPLATE', + template_desc => 'Default description', + page_width => 8.5, + page_height => 0, + label_width => 0, + label_height => 0, + top_text_margin => 0, + left_text_margin => 0, + top_margin => 0, + left_margin => 0, + cols => 3, + rows => 0, + col_gap => 0, + row_gap => 0, + units => 'POINT', + template_stat => 0, +}; + +my $template; + +diag "Testing Template->new() method."; +ok($template = C4::Labels::Template->new(page_width => 8.5,cols => 3)) || diag "Template->new() FAILED."; +is_deeply($template, $expect_template) || diag "New template object FAILED to verify."; + +diag "Testing Template->get_attr() method."; +foreach my $key (keys %{$expect_template}) { + ok($expect_template->{$key} eq $template->get_attr($key)) || diag "Template->get_attr() FAILED on attribute $key."; +} + +diag "Testing Template->set_attr() method."; +my $new_attr = { + profile_id => 0, + template_code => 'Avery 5160 | 1 x 2-5/8', + template_desc => '3 columns, 10 rows of labels', + page_width => 8.5, + page_height => 11, + label_width => 2.63, + label_height => 1, + top_text_margin => 0.139, + left_text_margin => 0.0417, + top_margin => 0.35, + left_margin => 0.23, + cols => 3, + rows => 10, + col_gap => 0.13, + row_gap => 0, + units => 'INCH', + template_stat => 1, +}; + +foreach my $key (keys %{$new_attr}) { + next if ($key eq 'template_stat'); + $template->set_attr($key, $new_attr->{$key}); + ok($new_attr->{$key} eq $template->get_attr($key)) || diag "Template->set_attr() FAILED on attribute $key."; +} + +diag "Testing Template->save() method with a new object."; + +my $sav_results = $template->save(); +ok($sav_results ne -1) || diag "Template->save() FAILED."; + +my $saved_template; +if ($sav_results ne -1) { + diag "Testing Template->retrieve() method."; + $new_attr->{'template_id'} = $sav_results; + ok($saved_template = C4::Labels::Template->retrieve(template_id => $sav_results)) || diag "Template->retrieve() FAILED."; + is_deeply($saved_template, $new_attr) || diag "Retrieved template object FAILED to verify."; +} + +diag "Testing Template->save method with an updated object."; + +$saved_template->set_attr(template_desc => 'A test template'); +my $upd_results = $saved_template->save(); +ok($upd_results ne -1) || diag "Template->save() FAILED."; +my $updated_template = C4::Labels::Template->retrieve(template_id => $sav_results); +is_deeply($updated_template, $saved_template) || diag "Updated template object FAILED to verify."; + +diag "Testing Template->retrieve() convert points option."; + +my $conv_template = C4::Labels::Template->retrieve(template_id => $sav_results, convert => 1); +my $expect_conv = { + page_width => 612, + page_height => 792, + label_width => 189.36, + label_height => 72, + top_text_margin => 10.008, + left_text_margin => 3.0024, + top_margin => 25.2, + left_margin => 16.56, + col_gap => 9.36, + row_gap => 0, +}; + +foreach my $key (keys %{$expect_conv}) { + ok($expect_conv->{$key} eq $conv_template->get_attr($key)) || diag "Template->retrieve() convert points option FAILED. Expected " . $expect_conv->{$key} . " but got " . $conv_template->get_attr($key) . "."; +} + +diag "Testing Template->delete() method."; + +my $del_results = $updated_template->delete(); +ok($del_results ne -1) || diag "Template->delete() FAILED."; diff --git a/tools/manage-marc-import.pl b/tools/manage-marc-import.pl index 43fed13c8d..ccf4e79b79 100755 --- a/tools/manage-marc-import.pl +++ b/tools/manage-marc-import.pl @@ -33,7 +33,8 @@ use C4::Biblio; use C4::ImportBatch; use C4::Matcher; use C4::BackgroundJob; -use C4::Labels qw(add_batch); +use C4::Labels::Batch 1.000000; +use C4::Branch qw(get_branch_code_from_name); my $script_name = "/cgi-bin/koha/tools/manage-marc-import.pl"; @@ -63,7 +64,16 @@ my $dbh = C4::Context->dbh; if ($op eq "create_labels") { #create a batch of labels, then lose $op & $import_batch_id so we get back to import batch list. my $label_batch_id = create_labelbatch_from_importbatch($import_batch_id); - $template->param( label_batch => $label_batch_id ); + if ($label_batch_id == -1) { + $template->param( label_batch_msg => "Error attempting to create label batch. Please ask your system administrator to check the log for more details.", + message_type => 'alert', + ); + } + else { + $template->param( label_batch_msg => "Label batch #$label_batch_id created.", + message_type => 'dialog', + ); + } $op=''; $import_batch_id=''; } @@ -166,9 +176,22 @@ sub redo_matching { sub create_labelbatch_from_importbatch { my ($batch_id) = @_; + my $err = undef; + my $branch_code = get_branch_code_from_name($template->param('LoginBranchname')); + my $batch = C4::Labels::Batch->new(branch_code => $branch_code); my @items = GetItemNumbersFromImportBatch($batch_id); - my $labelbatch = add_batch('labels',\@items); - return $labelbatch; + if (grep{$_ == 0} @items) { + warn sprintf('create_labelbatch_from_importbatch() : Call to C4::ImportBatch::GetItemNumbersFromImportBatch returned no item number(s) from import batch #%s.', $batch_id); + return -1; + } + foreach my $item_number (@items) { + $err = $batch->add_item($item_number); + if ($err == -1) { + warn sprintf('create_labelbatch_from_importbatch() : Error attempting to add item #%s of import batch #%s to label batch.', $item_number, $batch_id); + return -1; + } + } + return $batch->get_attr('batch_id'); } sub import_batches_list {