From 29f1940dcb35013536daacff3e50d01ca9787c1a Mon Sep 17 00:00:00 2001 From: Andrew McMillan Date: Fri, 19 Oct 2007 11:18:03 +1300 Subject: [PATCH] Changes for PDF support. --- Manual/PDF_Reference.odt | Bin 0 -> 16080 bytes inc/method/m-hpgl.i | 6 +- inc/method/m-txtrep.i | 27 ++++++ process/report/orderfrm.p | 12 +-- process/report/schdppg.p | 2 +- support/linux/pdf/apms-pdf-generator | 54 +++++++++++ support/linux/pdf/pdf-generator | 168 +++++++++++++++++++++++++++++------ support/linux/pdf/pdfgen.conf | 12 +++ support/linux/pdf/process-daemon | 97 +++++++++++++++++--- support/linux/pdf/process-pdf-spool | 26 ------ support/linux/pdf/test-email | 68 ++++++++++++++ vwr/drl/b-ivoice.w | 33 +++++-- 12 files changed, 429 insertions(+), 76 deletions(-) create mode 100644 Manual/PDF_Reference.odt mode change 100755 => 100644 inc/method/m-txtrep.i mode change 100755 => 100644 process/report/orderfrm.p create mode 100755 support/linux/pdf/apms-pdf-generator create mode 100644 support/linux/pdf/pdfgen.conf rewrite support/linux/pdf/process-daemon (99%) delete mode 100644 support/linux/pdf/process-pdf-spool create mode 100755 support/linux/pdf/test-email diff --git a/Manual/PDF_Reference.odt b/Manual/PDF_Reference.odt new file mode 100644 index 0000000000000000000000000000000000000000..dac4f22d640a2e96d6960d2ad0dfa19ee6abf1c2 GIT binary patch literal 16080 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 literal 0 HcwPel00001 diff --git a/inc/method/m-hpgl.i b/inc/method/m-hpgl.i index 3b441b8..95ec153 100644 --- a/inc/method/m-hpgl.i +++ b/inc/method/m-hpgl.i @@ -203,7 +203,11 @@ PROCEDURE client-address : ------------------------------------------------------------------------------*/ DEF INPUT PARAMETER client-code LIKE Client.ClientCode NO-UNDO. -IF hpgl-output-mode <> "pdf" THEN +IF hpgl-output-mode = "pdf" THEN DO: + IF NOT do-an-image-logo THEN + RUN client-routine( client-code, "Address":U ). +END. +ELSE RUN client-routine( client-code, "Address":U ). RUN hpgl-moveto( 0, 250 ). diff --git a/inc/method/m-txtrep.i b/inc/method/m-txtrep.i old mode 100755 new mode 100644 index 65fbbb0..e6ccc0e --- a/inc/method/m-txtrep.i +++ b/inc/method/m-txtrep.i @@ -16,6 +16,7 @@ DEF VAR txtrep-preview-window AS HANDLE NO-UNDO. DEF VAR txtrep-printer AS CHAR NO-UNDO. DEF VAR txtrep-delim AS CHAR INITIAL "~\" NO-UNDO. DEF VAR txtrep-output-mode AS CHAR INITIAL "txtrep" NO-UNDO. +DEF VAR txtrep-email-address AS CHAR NO-UNDO. DEF VAR pclrep-delimiter AS CHAR NO-UNDO INITIAL "|". DEF VAR pclrep-font-text AS CHAR NO-UNDO. @@ -1050,6 +1051,32 @@ END PROCEDURE. &ENDIF +&IF DEFINED(EXCLUDE-txtrep-do-email) = 0 &THEN + +&ANALYZE-SUSPEND _UIB-CODE-BLOCK _PROCEDURE txtrep-do-email Method-Library +PROCEDURE txtrep-do-email : +/*------------------------------------------------------------------------------ + Purpose: +------------------------------------------------------------------------------*/ +DEF INPUT PARAMETER email-string AS CHAR NO-UNDO. +DEF INPUT PARAMETER email-subject AS CHAR NO-UNDO. +DEF INPUT PARAMETER email-template AS CHAR NO-UNDO. + +IF email-string <> "" AND email-template <> "" THEN DO: + IF txtrep-output-mode = "pdf" THEN + PUT CONTROL "[-pdf-]>EMAIL:" + email-string + "|" + email-subject + "|" + email-template + "[-pdf-]". +END. +ELSE + MESSAGE "Email and email template parameters required" + VIEW-AS ALERT-BOX ERROR TITLE "Email or template blank". + +END PROCEDURE. + +/* _UIB-CODE-BLOCK-END */ +&ANALYZE-RESUME + +&ENDIF + &IF DEFINED(EXCLUDE-txtrep-pdf-filename) = 0 &THEN &ANALYZE-SUSPEND _UIB-CODE-BLOCK _PROCEDURE txtrep-pdf-filename Method-Library diff --git a/process/report/orderfrm.p b/process/report/orderfrm.p old mode 100755 new mode 100644 index b8e331a..f436345 --- a/process/report/orderfrm.p +++ b/process/report/orderfrm.p @@ -13,6 +13,7 @@ DEF VAR order-list AS CHAR NO-UNDO. DEF VAR no-of-copies AS INT NO-UNDO INITIAL 0. DEF VAR supplier-copy AS LOGI NO-UNDO INITIAL No. DEF VAR output-to-pdf AS LOGI NO-UNDO INITIAL NO. +DEF VAR email-address AS CHAR NO-UNDO. RUN parse-parameters. /* Report counters */ @@ -125,11 +126,6 @@ IF output-to-pdf THEN DO: RUN hpgl-output-mode( "pdf" ). END. -IF output-to-pdf THEN DO: - RUN txtrep-output-mode( "pdf" ). - RUN hpgl-output-mode( "pdf" ). -END. - RUN get-control-strings. /* @@ -393,6 +389,7 @@ PROCEDURE get-order-details : client-code = get-entity-client( entity-type, entity-code). account-name = get-entity-account( entity-type, entity-code, Order.AccountCode ). + RUN hpgl-initialize. RUN client-logo( client-code ). RUN client-address( client-code ). RUN hpgl-get-codes( yes, yes, OUTPUT logo-codes ). @@ -631,6 +628,7 @@ DEF VAR i AS INT NO-UNDO. WHEN "SupplierCopy" THEN supplier-copy = Yes. WHEN "InternalCopies" THEN no-of-copies = INT( ENTRY(2,token) ). WHEN "OutputPDF" THEN output-to-pdf = YES. + WHEN "EmailAddress" THEN email-address = ENTRY( 2, token ). WHEN "Entity" THEN ASSIGN entity-type = ENTRY(2,token) entity-code = INT( ENTRY(3,token) ) . @@ -851,6 +849,10 @@ DEF VAR i AS INT NO-UNDO. IF output-to-pdf THEN DO: RUN txtrep-pdf-filename( 'Order-' + ENTRY( i, order-list ) ). OUTPUT TO VALUE(txtrep-print-file) KEEP-MESSAGES PAGE-SIZE 0. + + /* Inject the email control sequence if this is to be emailed */ + IF email-address <> "" THEN + RUN txtrep-do-email( email-address, 'Purchase Order', 'templates/email/orderfrm.txt' ). END. FOR EACH Order WHERE Order.EntityType = entity-type diff --git a/process/report/schdppg.p b/process/report/schdppg.p index c316fdd..9643a3e 100644 --- a/process/report/schdppg.p +++ b/process/report/schdppg.p @@ -254,7 +254,7 @@ DEF VAR yield AS DEC NO-UNDO. FIND FIRST valuation NO-LOCK WHERE valuation.propertycode = property.propertycode AND valuation.valuationtype = 'CVAL' - USE-INDEX xpkvaluation. + USE-INDEX xpkvaluation NO-ERROR. IF AVAILABLE valuation THEN prop-value = valuation.amount. ELSE prop-value = 0. yield = (net-income / prop-value) * 100. diff --git a/support/linux/pdf/apms-pdf-generator b/support/linux/pdf/apms-pdf-generator new file mode 100755 index 0000000..abc4da5 --- /dev/null +++ b/support/linux/pdf/apms-pdf-generator @@ -0,0 +1,54 @@ +#!/bin/sh + +### BEGIN INIT INFO +# Provides: process-daemon +# Required-Start: $network $remote_fs $syslog +# Required-Stop: $network $remote_fs $syslog +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: Start the APMS PDF generator demo +### END INIT INFO + +. /lib/lsb/init-functions + +DAEMON=/home/apms/shared/code/support/linux/pdf/process-daemon +PIDFILE=/var/lock/apmspdfgen.pid + +test -x $DAEMON || exit 5 + +RUNASUSER=apms +UGID=$(getent passwd $RUNASUSER | cut -f 3,4 -d:) || true + +case $1 in + start) + log_daemon_msg "Starting APMS PDF generator" "process-daemon" + start-stop-daemon --start --quiet --oknodo --pidfile $PIDFILE --startas $DAEMON -c $UGID + log_end_msg $? + ;; + stop) + log_daemon_msg "Stopping APMS PDF generator" "process-daemon" + start-stop-daemon --stop --quiet --oknodo --pidfile $PIDFILE + log_end_msg $? + rm -f $PIDFILE + ;; + restart|force-reload) + $0 stop && sleep 2 && $0 start + ;; + reload) + exit 3 + ;; + status) + pidofproc -p $PIDFILE $DAEMON >/dev/null + status=$? + if [ $status -eq 0 ]; then + log_success_msg "APMS PDF generator is running." + else + log_failure_msg "APMS PDF generator is not running." + fi + exit $status + ;; + *) + echo "Usage: $0 {start|stop|restart|try-restart|force-reload|status}" + exit 2 + ;; +esac diff --git a/support/linux/pdf/pdf-generator b/support/linux/pdf/pdf-generator index 57d1a0e..00caf72 100644 --- a/support/linux/pdf/pdf-generator +++ b/support/linux/pdf/pdf-generator @@ -8,15 +8,27 @@ APMS PDF generator use strict; use warnings; -# use Data::Dumper; +use FindBin; +use MIME::Lite; +use Net::SMTP; use PDF::API2; +use POSIX qw( strftime ); # Location, no trailing slashes my $basedir = '.', -my $fontdir = './support/linux/pdf/fonts'; +my $fontdir = $FindBin::Bin . '/fonts'; +my $config = $FindBin::Bin . '/pdfgen.conf'; $basedir =~ s/\/$//; $fontdir =~ s/\/$//; +# Parse the configuration +$/ = undef; +open( CONF, "<", $config ) || debug_message( "Could not open configuration file" ); +my $configtext = ; +close CONF; +$/ = "\n"; +my %config = $configtext =~ /^([a-zA-Z0-9\_]+)\s*=\s*(.+)$/mg; + my $filename = $ARGV[0]; my $outputfl = $ARGV[1]; @@ -95,8 +107,9 @@ char for setting while rendering the text. =cut my $spacehacks = { - 'times-bold-16' => 150, - 'helvetica-10' => 125, + 'times-bold-16' => 120, + 'helvetica-bold-14' => 130, + 'helvetica-10' => 120, }; # Create the PDF document object @@ -149,7 +162,6 @@ foreach my $chunk ( @chunks ) { # Does this chunk contain a control sequence? if ( $chunk =~ /^>([A-Z]+):(.*)$/ ) { - debug_message( $1 ); process_command( $1, $2 ); } else { @@ -275,18 +287,24 @@ foreach my $command ( @{ $data->{commands} } ) { } } + # Look for an email command and remember for later + if ( $command->{action} eq 'email' ) { + $state->{email}->{template} = $command->{template}; + $state->{email}->{subject} = $command->{subject}; + $state->{email}->{address} = $command->{address}; + } + # Check for commands to initiate a new page if ( $command->{action} eq 'control' ) { # New page if ( exists $command->{newpage} ) { - unless ( $commandcount + 1 >= $numbercommands ) { + unless ( $commandcount + 3 >= $numbercommands ) { debug_message( "Adding a new page: $commandcount : $numbercommands" ); $state->add_page(); $state->add_gfx(); } else { - $pdf->save; - exit 0; + $state->finish; } } @@ -368,8 +386,15 @@ foreach my $command ( @{ $data->{commands} } ) { } my $imagefile = $basedir . '/' . $command->{image}; debug_message( "Adding image $imagefile at $command->{x}, $command->{y}" ); - my $image = $pdf->image_jpeg( $imagefile ); - $state->{currentgfx}->image( $image, ( $command->{x} / mm ), ( $command->{y} / mm ) ); + my $image; + if ( $imagefile =~ /\.jpe?g$/i ) { + $image = $pdf->image_jpeg( $imagefile ); + } + elsif ( $imagefile =~ /\.png$/i ) { + $image = $pdf->image_png( $imagefile ); + } + # Always scale the image logo by 0.3. Means the image looks reasonable when viewed in acrobat + $state->{currentgfx}->image( $image, ( $command->{x} / mm ), ( $command->{y} / mm ), 0.3 ); } # Look for text output @@ -421,34 +446,40 @@ foreach my $command ( @{ $data->{commands} } ) { debug_message( "Changing hspace from $hspace to " . $spacehacks->{"$fontident"} ); $state->{currenttext}->hspace( $spacehacks->{"$fontident"} ); $spacewidth = $state->{currenttext}->advancewidth( $spaces ); + debug_message( "The width of the spaces was $spacewidth" ); } - # Print the spaces regardless of adjustments to hspace. - $state->{currenttext}->text( $spaces ); - debug_message( "Printed " . length( $spaces ) . " spaces" ); - # If the hspace was adjusted then use the calculated width to move the cursor and # set hspace back. if ( exists $spacehacks->{"$fontident"} ) { + ( $xpos, $ypos ) = $state->get_currentpos(); + debug_message( "Simulating spaces $xpos + $spacewidth" ); $state->set_currentpos( $xpos + $spacewidth, $ypos ); $state->move_text_cursor; $state->{currenttext}->hspace( 100 ); } + else { + # No adjustment of spaces, so just print the spaces. + $state->{currenttext}->text( $spaces ); + debug_message( "Printed " . length( $spaces ) . " spaces" ); + } $part =~ s/^\s+//; } - # Check if this text will overflow the page, and if so chop it - my $width = $state->{currenttext}->advancewidth( $part ); - debug_message( "Calculated a text width of $width" ); - if ( ( $state->{leftmargin} - 5 ) + $width + $state->{currpos}->{x} >= 595 ) { - my $lettercount = length( $part ); - my $allowedchars = ( 595 - ( $state->{currpos}->{x} + 40 ) ) / ( $width / $lettercount ); - $part = substr( $part, 0, $allowedchars ); - debug_message( "Chopped text" ); - } + unless ( $part eq '' ) { + # Check if this text will overflow the page, and if so chop it + my $width = $state->{currenttext}->advancewidth( $part ); + debug_message( "Calculated a text width of $width" ); + if ( ( $state->{leftmargin} - 5 ) + $width + $state->{currpos}->{x} >= 599 ) { + my $lettercount = length( $part ); + my $allowedchars = ( 595 - ( $state->{currpos}->{x} + 40 ) ) / ( $width / $lettercount ); + $part = substr( $part, 0, $allowedchars ); + debug_message( "Chopped text" ); + } - $state->{currenttext}->text( $part ); - debug_message( "Printed \'$part\'" ); + $state->{currenttext}->text( $part ); + debug_message( "Printed \'$part\'" ); + } # Only do a carriage return _inbetween_ the parts, not after the last one if ( $morethan1part && $part_count != $part_number ) { @@ -551,8 +582,7 @@ This code has been removed due to issues with making the COPY text transparent. $commandcount++; } -$pdf->save; - +$state->finish; exit 0; @@ -628,7 +658,7 @@ sub convert_coords { } } elsif ( $move->{units} eq 'lines' ) { - $xpos = $move->{x} * ( $state->{hmi} / 1.5 ); # Seems to require 1.5 to actually work correctly + $xpos = $move->{x} * $state->{hmi}; #( $state->{hmi} / 1.5 ); # Seems to require 1.5 to actually work correctly $ypos = $move->{y} * ( $state->{vmi} / 1.01 ); # Slightly less debug_message( "Just used the VMI $state->{vmi} to calculate vertical cursor motion in lines" ); @@ -861,6 +891,75 @@ sub set_landscape { $state->{pages}[$state->{pagecount}]->rotate( 90 ); } +=item finish + +Do all the things that need to be done to finish + +=cut + +sub finish { + my $state = shift; + $pdf->save; + + # Generate a timestamp ISO 8601 + my $timestamp = strftime( "%Y-%m-%dT%H:%M:%S", localtime ); + + # Should this PDF be emailed + if ( exists $state->{email} ) { + # Prepare to write to the log + open( LOG, ">>", "mail.log" ) || exit 1; + + # Check the template exists + my $template = $state->{email}->{template}; + unless ( -e $template ) { + print LOG "$timestamp\tTemplate \'$template\' not found\n"; + } + + # Slurp in the template + local $/, undef; + open( TMPL, $template ) || exit 1; + my $templatetext = ; + close TMPL; + + # Create the new message + my $email = MIME::Lite->new( + From => $config{FromAddress}, + To => $state->{email}->{address}, + Subject => $state->{email}->{subject}, + Type =>'multipart/mixed', + ) || print LOG "$timestamp\tUnable to create the multipart object\n"; + + # Put the template into the message + $email->attach( + Type => 'TEXT', + Data => $templatetext, + ) || print LOG "$timestamp\tUnable to attach the text body\n"; + + # Attach the PDF + $email->attach( + Type => 'application/pdf', + Path => $outputfl, + Disposition => 'attachment', + ) || print LOG "$timestamp\tUnable to attach the PDF file\n"; + + my $smtp = Net::SMTP->new( $config{MailServer} ); + $smtp->auth( $config{SMTPUser}, $config{SMTPPass} ); + $smtp->mail( $config{FromAddress} ); + $smtp->to( $state->{email}->{address} ); + + $smtp->data(); + $smtp->datasend( $email->as_string() ); + $smtp->dataend(); + + $smtp->quit; + + print LOG "$timestamp\tSent file \'$outputfl\' to \'$state->{email}->{address}\'\n"; + close LOG; + } + + exit 0; +} + =item process_control Process a control (or font) string. See the encoding form in apms:inc/method/m-txtrep.i @@ -948,9 +1047,13 @@ sub process_control { if ( $commands->{fontfamily} eq 'antiqueolive' ) { $commands->{fontpoint} += 2; } + unless ( exists $commands->{hmi} ) { + $commands->{hmi} = 0.38 * $commands->{fontpoint}; + } } if ( $item eq 'cpi' ) { $commands->{hmi} = ( 1 / $control_parts[$next] ) / in; + #$commands->{hmi} = ( 1 / $control_parts[$next] ) / in; #unless ( exists $commands->{fontpoint} ) { # $commands->{fontpoint} = ( 1 / $control_parts[$next] ) / in; #} @@ -1086,6 +1189,15 @@ sub process_command { elsif ( $command_key eq 'PF' ) { push @{ $data->{commands} }, { action => 'control', newpage => 1 }; } + elsif ( $command_key eq 'EMAIL' ) { + my ( $address, $subject, $template ) = split /\|/, $command_args; + push @{ $data->{commands} }, { + action => 'email', + address => $address, + subject => $subject, + template => $template, + }; + } elsif ( $command_key eq 'LT' ) { debug_message( "$command_key currently unsupported" ); } diff --git a/support/linux/pdf/pdfgen.conf b/support/linux/pdf/pdfgen.conf new file mode 100644 index 0000000..cd3cb6f --- /dev/null +++ b/support/linux/pdf/pdfgen.conf @@ -0,0 +1,12 @@ +# Email settings for the PDF generator and emailer +MailServer = smtp.primeproperty.co.nz +SMTPUser = XXXXXX +SMTPPass = XXXXXX +FromAddress = accounts@primeproperty.co.nz + +# Path settings for the daemon +BasePath = /home/apms/capital-apms +SpoolPath = /home/apms/shared/pdf/spool +OutputPath = /home/apms/shared/pdf/output +DonePath = /home/apms/shared/pdf/spool/done +LogFile = /home/apms/capital-apms/pdfgen.log diff --git a/support/linux/pdf/process-daemon b/support/linux/pdf/process-daemon dissimilarity index 99% index a93fdad..101690e 100644 --- a/support/linux/pdf/process-daemon +++ b/support/linux/pdf/process-daemon @@ -1,10 +1,87 @@ -#!/bin/sh - -while ( [ 1 ] ); do - if ls -1 /home/apms/shared/pdf/spool/*.protopdf >/dev/null 2>&1; then - sleep 1 - /home/apms/shared/code/support/linux/pdf/process-pdf-spool >/dev/null 2>&1 - else - sleep 5 - fi -done +#!/usr/bin/perl + +=head2 process-daemon + +Daemon process to execute the pdf generator + +=cut + +use strict; +use FindBin; +use POSIX qw( setsid ); +use Fcntl ':flock'; + +# The name of the lock file and find where things are +my $lock_file = '/var/lock/apmspdfgen.pid'; +my $basename = 'apmspdfgen'; +my $basedir = $FindBin::Bin; +my $configfl = $basedir . '/pdfgen.conf'; + +# Parse the configuration +$/ = undef; +open( CONF, "<", $configfl ) || die "Could not open configuration file \'$configfl\'"; +my $configtext = ; +close CONF; +$/ = "\n"; +my %config = $configtext =~ /^([a-zA-Z0-9\_]+)\s*=\s*(.+)$/mg; + +# Strip potential trailing slashes +$config{BasePath} =~ s/\/$//; +$config{SpoolPath} =~ s/\/$//; +$config{OutputPath} =~ s/\/$//; +$config{DonePath} =~ s/\/$//; + +# Check everything exists +die "Invalid BasePath option" unless -e "$config{BasePath}"; +die "Invalid SpoolPath option" unless -e "$config{SpoolPath}"; +die "Invalid OutputPath option" unless -e "$config{OutputPath}"; +die "Invalid DonePath option" unless -e "$config{DonePath}"; + +start_daemon(); + +sub start_daemon { + # Redirect output away + open( LOG, ">>", "$config{LogFile}" ) || die "Could not open log file \'$config{LogFile}\': $!"; + open( STDOUT, ">&LOG" ) || die "Could not send STDOUT to the log file: $!"; + open( STDERR, ">&LOG" ) || die "Could not send STDERR to the log file: $!"; + select STDOUT; + + # Switch to a background process and detatch from the terminal + fork && exit 0; + POSIX::setsid(); + + # Write the PID to the lock file + open( LOCK, '>>', $lock_file ) || die "Could not open lock file \'$lock_file\': $!"; + if ( not flock( LOCK, LOCK_EX | LOCK_NB ) ) { + warn "The $basename daemon is already running\n"; + exit 0; + } + + truncate( LOCK, 0 ); + syswrite( LOCK, "$$\n" ); + + daemon_loop(); +} + +sub daemon_loop { + while ( 1 ) { + sleep 5; + my @files = glob( "$config{SpoolPath}/*.protopdf" ) || next; + foreach my $file ( @files ) { + if ( $file =~ /^$config{SpoolPath}\/([a-zA-Z0-9\-\_]+)\.protopdf/ ) { + my $filename = $1; + + # Set destinations + my $in = "$config{SpoolPath}/$filename.protopdf"; + my $out = "$config{OutputPath}/$filename.pdf"; + my $log = "$config{DonePath}/lastrun.log"; + + # Run the generator + `cd $config{BasePath}; $basedir/pdf-generator $in $out > $log`; + + # Move the file + `mv $in $config{DonePath}/`; + } + } + } +} diff --git a/support/linux/pdf/process-pdf-spool b/support/linux/pdf/process-pdf-spool deleted file mode 100644 index 38972e3..0000000 --- a/support/linux/pdf/process-pdf-spool +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/sh - -# Config -PROCDIR="/home/apms/shared" -BASEDIR="${PROCDIR}/code" -EXECDIR="${PROCDIR}/code/support/linux/pdf" - -# For relative access to the process/logo/*.jpg files -cd ${PROCDIR}/pdf/spool/ - -# Get the list of files -PPLIST=`ls -1 *.protopdf` - -# For relative access to the process/logo/*.jpg files -cd ${BASEDIR} - -# Process all the files in the spool directory -for PPFILE in $PPLIST; do - PPOUT=`echo $PPFILE | sed 's/.protopdf/.pdf/'` - ${EXECDIR}/pdf-generator "${PROCDIR}/pdf/spool/$PPFILE" "${PROCDIR}/pdf/output/$PPOUT" > ${PROCDIR}/pdf/spool/done/lastrun.log -done - -# Move the processed files into the done directory -for PPFILE in $PPLIST; do - mv "${PROCDIR}/pdf/spool/$PPFILE" "${PROCDIR}/pdf/spool/done/" -done diff --git a/support/linux/pdf/test-email b/support/linux/pdf/test-email new file mode 100755 index 0000000..a125dc6 --- /dev/null +++ b/support/linux/pdf/test-email @@ -0,0 +1,68 @@ +#!/usr/bin/perl + +=head1 NAME + +Test the ability to send email using the pdfgen.conf configuration +file in this directory. + +=cut + +use strict; +use warnings; +use FindBin; +use MIME::Lite; +use Net::SMTP; + +die "Usage: $0
\n\nSend a test message to
\n" + unless $ARGV[0]; + +# Location, no trailing slashes +my $basedir = '.', +my $config = $FindBin::Bin . '/pdfgen.conf'; +$basedir =~ s/\/$//; + +# Parse the configuration +$/ = undef; +open( CONF, "<", $config ) || debug_message( "Could not open configuration file" ); +my $configtext = ; +close CONF; +$/ = "\n"; +my %config = $configtext =~ /^([a-zA-Z0-9\_]+)\s*=\s*(.+)$/mg; + +unless ( -d "/home/apms/shared/code/templates/email" ) { + print "Warning: The directory \'/home/apms/shared/code/templates/email\' does not exist.\n"; + print "This could be because your APMS is not installed in /home/apms/shared/code/, but"; + print " it could also mean that something is wrong.\n"; +} + +# Create the new message +print "Creating a multipart/mixed message\n"; +my $email = MIME::Lite->new( + From => 'test@test.com', + To => $ARGV[0], + Subject => 'Test message from APMS', + Type =>'multipart/mixed', +) || print "Unable to create the multipart object\n"; + +print "Attaching text to the message\n"; +$email->attach( + Type => 'TEXT', + Data => "Test message", +) || print "Unable to attach the text body\n"; + +print "Setting the send options:\n"; +print "\tHost: $config{MailServer}\n"; +print "\tUser: $config{SMTPUser}\n"; +print "\tPass: $config{SMTPPass}\n"; + +my $smtp = Net::SMTP->new( $config{MailServer} ); +$smtp->auth( $config{SMTPUser}, $config{SMTPPass} ); +$smtp->mail( 'test@test.com' ); +$smtp->to( $ARGV[0] ); + +print "Sending the message\n"; +$smtp->data(); +$smtp->datasend( $email->as_string() ); +$smtp->dataend(); + +$smtp->quit; diff --git a/vwr/drl/b-ivoice.w b/vwr/drl/b-ivoice.w index 3133cac..0548907 100644 --- a/vwr/drl/b-ivoice.w +++ b/vwr/drl/b-ivoice.w @@ -521,6 +521,8 @@ PROCEDURE inst-value-changed : RUN set-link-attributes IN sys-mgr( THIS-PROCEDURE, "reprint-invoice", "SENSITIVE = " + IF AVAILABLE Invoice THEN "Yes" ELSE "No" ). + RUN set-link-attributes IN sys-mgr( THIS-PROCEDURE, "reprint-pdfinvoice", + "SENSITIVE = " + IF AVAILABLE Invoice AND pdf-support THEN "Yes" ELSE "No" ). RUN set-link-attributes IN sys-mgr( THIS-PROCEDURE, "maintain", "SENSITIVE = " + IF AVAILABLE Invoice AND Invoice.InvoiceStatus = "U" THEN "Yes" ELSE "No" ). @@ -613,7 +615,7 @@ END PROCEDURE. &ANALYZE-SUSPEND _UIB-CODE-BLOCK _PROCEDURE reprint-invoice B-table-Win PROCEDURE reprint-invoice : /*------------------------------------------------------------------------------ - Purpose: + Purpose: Reprint the invoice to the printer ------------------------------------------------------------------------------*/ IF NOT AVAILABLE Invoice THEN RETURN. @@ -623,15 +625,36 @@ PROCEDURE reprint-invoice : ELSE IF Invoice.InvoiceStatus = "U" THEN RUN process/report/invcappr.p( Invoice.InvoiceNo, Invoice.InvoiceNo, ? ). ELSE DO: - IF pdf-support THEN - MESSAGE "Reprint to PDF?" VIEW-AS ALERT-BOX QUESTION BUTTONS YES-NO - TITLE "PDF Printing ?" UPDATE pdf-printing. + RUN process/report/taxinvce.p( + "InvoiceRange," + + STRING(Invoice.InvoiceNo) + + "," + STRING( Invoice.InvoiceNo ) + ). + END. + +END PROCEDURE. + +/* _UIB-CODE-BLOCK-END */ +&ANALYZE-RESUME + +&ANALYZE-SUSPEND _UIB-CODE-BLOCK _PROCEDURE reprint-pdfinvoice B-table-Win +PROCEDURE reprint-pdfinvoice : +/*------------------------------------------------------------------------------ + Purpose: Reprint the invoice in PDF format +------------------------------------------------------------------------------*/ + IF NOT AVAILABLE Invoice THEN RETURN. + IF advice-of-charge = Yes THEN DO: + RUN process/report/advice-of-charge.p( "InvoiceList," + STRING(Invoice.InvoiceNo) ). + END. + ELSE IF Invoice.InvoiceStatus = "U" THEN + RUN process/report/invcappr.p( Invoice.InvoiceNo, Invoice.InvoiceNo, ? ). + ELSE DO: RUN process/report/taxinvce.p( "InvoiceRange," + STRING(Invoice.InvoiceNo) + "," + STRING( Invoice.InvoiceNo ) - + (IF pdf-printing THEN "~nOutputPDF" ELSE "") + + "~nOutputPDF" ). END. -- 2.11.4.GIT