#!/usr/bin/perl
#
#  LMS version 1.11.13 Dira
#
#  Copyright (C) 2001-2011 LMS Developers
#
#  Please, see the doc/AUTHORS for more information about authors!
#
#  This program is free software; you can redistribute it and/or modify
#  it under the terms of the GNU General Public License Version 2 as
#  published by the Free Software Foundation.
#
#  This program 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 this program; if not, write to the Free Software
#  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
#  USA.
#
#  $Id: lms-sendinvoiceswithpostivo,v 1.00 2011/10/28 22:30:23 alec Exp $

use strict;
use DBI;
use Config::IniFiles;
use Getopt::Long;
use vars qw($configfile $help $version $quiet $fakedate);
use POSIX qw(strftime);
use LWP::UserAgent;
use Time::Local;
use SOAP::Lite;
use MIME::Base64;

binmode(STDOUT, ":utf8");
binmode(STDERR, ":utf8");

my $_version = '1.11.13 Dira';

my %options = (
	"--config-file|C=s"     =>      \$configfile,
	"--quiet|q"     	=>      \$quiet,
	"--help|h"              =>      \$help,
	"--version|v"           =>      \$version,
	"--fakedate|f=s"	=>	\$fakedate,
);

Getopt::Long::config("no_ignore_case");
GetOptions(%options);

if($help)
{
	print STDERR <<EOF;
lms-sendinvoiceswithpostivo, version $_version
(C) 2001-2011 LMS Developers

-C, --config-file=/etc/lms/lms.ini    alternate config file 
			    (default: /etc/lms/lms.ini);
-q, --quiet		    suppress any output, except errors;
-h, --help		    print this help and exit;
-v, --version		    print version info and exit;
-f, --fakedate=YYYY/MM/DD   override system date;

EOF
	exit 0;
}

if($version)
{
	print STDERR <<EOF;
lms-sendinvoiceswithpostivo, version $_version
(C) 2001-2011 LMS Developers

EOF
	exit 0;
}

if(!$configfile)
{
	$configfile = "/etc/lms/lms.ini";
}

if(! -r $configfile)
{
	print STDERR "Fatal error: Unable to read configuration file $configfile, exiting.\n";
	exit 1;
}

if(!$quiet)
{
	print STDOUT "lms-sendinvoiceswithpostivo, version $_version\n";
	print STDOUT "(C) 2001-2011 LMS Developers\n";
	print STDOUT "Using file $configfile as config.\n";
}

my $ini = new Config::IniFiles -file => $configfile;
print @Config::IniFiles::errors;

my $dbtype = $ini->val('database', 'type') || 'mysql';
my $dbhost = $ini->val('database', 'host') || 'localhost';
my $dbuser = $ini->val('database', 'user') || 'root';
my $dbpasswd = $ini->val('database', 'password') || '';
my $dbname = $ini->val('database', 'database') || 'lms';

my $lms_url = $ini->val('sendinvoiceswithpostivo', 'lms_url') || 'http://localhost/lms/';
my $lms_user = $ini->val('sendinvoiceswithpostivo', 'lms_user') || '';
my $lms_password = $ini->val('sendinvoiceswithpostivo', 'lms_password') || '';
my $postivo_user = $ini->val('sendinvoiceswithpostivo', 'postivo_user') || '';
my $postivo_password = $ini->val('sendinvoiceswithpostivo', 'postivo_api_password') || '';
my $config_id = $ini->val('sendinvoiceswithpostivo', 'config_id') || '';
my $sender_id = $ini->val('sendinvoiceswithpostivo', 'sender_id') || '';
my $sandbox = $ini->val('sendinvoiceswithpostivo', 'sandbox') || '';

my $filetype = $ini->val('invoices', 'type') || '';
my $customergroups = $ini->val('sendinvoiceswithpostivo', 'customergroups') || '';

my $dbase;
my $utsfmt;

if($dbtype =~ /mysql/)
{
	$dbase = DBI->connect("DBI:mysql:database=$dbname;host=$dbhost","$dbuser","$dbpasswd", { RaiseError => 1 });
	$dbase->do("SET NAMES utf8");
	$utsfmt = "UNIX_TIMESTAMP()";
}
elsif($dbtype eq "postgres")
{
	$dbase = DBI->connect("DBI:Pg:dbname=$dbname;host=$dbhost","$dbuser","$dbpasswd", { RaiseError => 1 });
	$utsfmt = "EXTRACT(EPOCH FROM CURRENT_TIMESTAMP(0))";
}
else
{
	print STDERR "Fatal error: unsupported database type: $dbtype, exiting.\n";
	exit 1;
}

sub localtime2()
{
	if($fakedate)
	{
		my @fakedate = split(/\//, $fakedate);
		return localtime(timelocal(0,0,0,$fakedate[2],$fakedate[1]-1,$fakedate[0]));
	}
	else
	{
		return localtime();
	}
}

# get/set invoice file type
my $dbq = $dbase->prepare("SELECT value FROM uiconfig WHERE section='invoices' AND var='type' AND disabled=0");
$dbq->execute();
if(my $row = $dbq->fetchrow_hashref())
{
	$filetype = $row->{'value'};
}

if ($filetype ne "pdf")
{
	print STDERR "Fatal error: unsupported file type: $filetype, exiting.\n";
        exit 1;

}

my $wsdl_url = 'http://api.postivo.pl/webservices.php?wsdl';

if ($sandbox)
{
   $wsdl_url =  'http://api.postivo.pl/webservices-sandbox.php?wsdl';
}

my $month =  int strftime("%m",localtime2());
my $day = int strftime("%d",localtime2());
my $year = strftime("%Y",localtime2());
my $daystart = strftime("%s", 0, 0, 0, $day, $month - 1, $year - 1900);
my $dayend = strftime("%s", 59, 59, 23, $day, $month - 1, $year - 1900);

my $groupwhere = '';
my $groupjoin = '';
if($customergroups)
{
	$customergroups = "UPPER('$customergroups')";
	$customergroups =~ s/[ \t]+/\'\),UPPER\(\'/g;
	$groupwhere = " AND UPPER(customergroups.name) IN ($customergroups)";  
	$groupjoin = "LEFT JOIN customerassignments ON (d.customerid = customerassignments.customerid) 
			LEFT JOIN customergroups ON (customerassignments.customergroupid = customergroups.id) ";
}
$dbq = $dbase->prepare("SELECT d.id, d.number, d.cdate, d.name, d.customerid, n.template, c.post_name, c.post_address,
			c.post_zip, c.post_city, c.name, c.lastname, c.address, c.zip, c.city
			FROM documents d 
			LEFT JOIN customers c ON (c.id = d.customerid) 
			LEFT JOIN numberplans n ON (n.id = d.numberplanid)
			$groupjoin
			WHERE c.deleted = 0 AND d.type = 1 
				AND d.cdate >= $daystart AND d.cdate <= $dayend
				$groupwhere GROUP BY d.id");
$dbq->execute();

while(my $row = $dbq->fetchrow_hashref())
{
	my $ua = LWP::UserAgent->new;
	my $response = $ua->get($lms_url.'/?m=invoice&override=1&original=1&id='.$row->{'id'}.'&loginform[login]='.$lms_user.'&loginform[pwd]='.$lms_password);

	if ($response->is_success)
	{
		my $invoice_number = $row->{'template'} || '%N/LMS/%Y';
		
		$invoice_number =~ s/%(\d*)N/sprintf"%0${1}d",$row->{'number'}/e;
		$invoice_number = strftime($invoice_number, localtime($row->{'cdate'}));
		
		
		my $client = SOAP::Lite
			-> proxy($wsdl_url)
			-> uri('http://api.postivo.pl/webservices.php')
			-> on_fault(sub { my($soap, $res) = @_; 
				print STDERR "Error: ".(ref $res ? $res->faultstring : $soap->transport->status)."   (Invoice No. $invoice_number for $row->{'name'} $row->{'lastname'})\n";
				next;
				});

		my @doc_files = (\SOAP::Data->value(
                                     \SOAP::Data->value(
					SOAP::Data->name(file_stream => encode_base64($response->content)),
			                SOAP::Data->name(file_name => $invoice_number)
                                      )
                                )

               	);

		my @recipients = (\SOAP::Data->value(
                                     \SOAP::Data->value(
                                        SOAP::Data->name(id => 0),
                                        SOAP::Data->name(source => "inline"),
                                        SOAP::Data->name(recipient_name => $row->{'name'}." ".$row->{'lastname'}) ,
                                        SOAP::Data->name(recipient_address_prefix => ""),
                                        SOAP::Data->name(recipient_address => $row->{'address'}),
                                        SOAP::Data->name(recipient_home_number => " "),
                                        SOAP::Data->name(recipient_flat_number => ""),
                                        SOAP::Data->name(recipient_post_code => $row->{'zip'}),
                                        SOAP::Data->name(recipient_city => $row->{'city'})
                                      )
                                )
                        );
		
		if ($row->{'post_name'} && $row->{'post_address'} && $row->{'post_zip'} && $row->{'post_city'}){
			 @recipients = (\SOAP::Data->value(
                                     \SOAP::Data->value(
                                        SOAP::Data->name(id => 0),
                                        SOAP::Data->name(source => "inline"),
                                        SOAP::Data->name(recipient_name => $row->{'post_name'}),
                                        SOAP::Data->name(recipient_address_prefix => ""),
                                        SOAP::Data->name(recipient_address => $row->{'post_address'}),
                                        SOAP::Data->name(recipient_home_number => " "),
                                        SOAP::Data->name(recipient_flat_number => ""),
                                        SOAP::Data->name(recipient_post_code => $row->{'post_zip'}),
                                        SOAP::Data->name(recipient_city => $row->{'post_city'})
                                      )
                                )
               		);
		}

		my @dispatch_options = (
			\SOAP::Data->value(
	                      	\SOAP::Data->value(
	                                SOAP::Data->name("name" => "sender_id"),
                                        SOAP::Data->name("value" => $sender_id)
             	              ),
				\SOAP::Data->value(
                                        SOAP::Data->name("name" => "config_id"),
                                        SOAP::Data->name("value" => $config_id)
                              )
                      	)
		);
		my $result = $client->dispatch(
			SOAP::Data->name(login => $postivo_user), 
			SOAP::Data->name(api_pass => $postivo_password),
			SOAP::Data->name(msg_type => 1),
			SOAP::Data->name(document_files => @doc_files),
			SOAP::Data->name(recipients => @recipients),
			SOAP::Data->name(options => @dispatch_options)
			)->result;

		if ($result->{'shipments'}[0]->{'status'} eq "ERR" || $result->{'result'} eq "ERR")
		{
			print STDERR "Error: Invoice No. $invoice_number for $row->{'name'} $row->{'lastname'} Status: ".(($result->{'result'} eq "ERR") ? $result->{'result_description'} : $result->{'shipments'}[0]->{'status_description'})."\n";
			next;
		}

		my $dbqi = $dbase->prepare("INSERT INTO syslog (cdate, uid, cid, module, event ,msg ,oid  ) VALUES ( $utsfmt, 1, $row->{'customerid'}, 1,1,  'Wyslano list postivo ID: $result->{'shipments'}[0]->{'id'}  ' , 1  ) " );
                $dbqi->execute();

		if(!$quiet)
                {
                        print "Invoice No. $invoice_number for $row->{'name'} $row->{'lastname'} Status: $result->{'shipments'}[0]->{'status_description'} ID: $result->{'shipments'}[0]->{'id'}\n";
                }
	}
	else
	{
		print STDERR "Error: ".$response->status_line."\n";
	}
}

$dbq->finish();
$dbase->disconnect();
