#!/usr/bin/perl -w

use strict;
use POSIX qw( strftime);
use Time::Local;
use Pg;
use CGI;

my $query=new CGI;

print "Content-type:text/html\n\n";

#=============================
#
#      SUB's

sub usage {
    print "usage:\n
recupRglt.pl [-o <output file>] -h DBHOST -u USER -p PWD [-c]
genère la liste des rapprochements obtenus par 3 méthodes successives, et le SQL associé ;
renvoie les stats sur STDERR et les SQL sur STDIN si -o n'est pas spécifié ;
l'option -c tente un calcul sans certaines contraintes de dates (hasardeux).

";
} 

sub getArgs {
    my @args=@_;
    my $oldKey="";
    my %opts=();
	my $el;
    for $el (@args) {
		if ($el=~/^-/) {
			$el=~s/-+//g;
			$opts{$el}="";
			$oldKey=$el;
		}
		else {
			$opts{$oldKey}=$el;
		}
    }
    return %opts;
}

sub connectPg {
    my ($DBHOST,$DBNAME,$DBUSER,$DBPWD)=@_;
	my $debug=0;
    # Ouverture connexion postgres
    my $req={};
    my $conn = Pg::connectdb("dbname=$DBNAME user=$DBUSER host=$DBHOST password=$DBPWD");
    print "dbname=$DBNAME user=$DBUSER password=$DBPWD host=$DBHOST\n" if $debug;
    if (PGRES_CONNECTION_OK ne $conn->status) {
		print STDERR "dbname=$DBNAME user=$DBUSER password=$DBPWD host=$DBHOST";
    }
	return $conn;
}

sub round{
	my($l_arg1,$l_scale)=@_;
	my $sign=1;
	if ($l_arg1<0) { $l_arg1=-$l_arg1; $sign=-1 ;}
	return 0 if ($l_arg1 == 0);
	my($l_num1,$l_num2) = 0;
	$l_num1 = 10**$l_scale * $l_arg1;
	$l_num2 = int($l_num1);
	$l_num2 = $l_num2 +1 if ($l_num1 - $l_num2 >= 0.5);
	$l_num1 =  $l_num2/10**$l_scale;
	return $l_num1*$sign; 
}

#=============================


my $sql;
my $output;
my $conn;
my %opts=();
my $complete=0;
my @lrglt;
my @lachat;
my @lsalaire;
my @lcharge;
my @lchargesoc;
my @lmvt;  # mvt positifs
my @lmvtn; # mvt négatifs
my %lclient;
my %client=();
my $result;
my @merge=();

%opts=getArgs(@ARGV);

if (!$query->param('p')) {
	print "Manque p !";
	&usage();
	exit;
}
if (!$query->param('u')) {
	print "Manque u !";
	&usage();
	exit;
}
if (!$query->param('h')) {
	print "Manque h !";
	&usage();
	exit;
}

if ($query->param('c')) {
	$complete=1;
}


my ($USER,$DBNAME,$DBPWD,$DBHOST);
$USER=$query->param('u');
$DBNAME=$query->param('n');
$DBPWD=$query->param('p');
$DBHOST=$query->param('h');

$conn=connectPg("$DBHOST","$DBNAME","$USER","$DBPWD");

# Recup des clients/fournisseur/intervenant/organisme (map pour affichage) #
#========================================#
$sql=" 
set datestyle to 'SQL,EURO';
SELECT uid,nom from client union select uid,nom from fournisseur union select uid,nom from intervenant union select uid,nom from organisme;";

$result=$conn->exec($sql); 
if (PGRES_TUPLES_OK ne $result->resultStatus) {
	print STDERR "ERREUR  : $sql failed : ".$conn->errorMessage;
	exit 0;
}

while (my @row = $result->fetchrow) {
	#print join($sep,@row)."\n";
	$lclient{$row[0]}=$row[1];
}

# Recup des reglements #
#======================#
#        0 -> date + 1e9 , 1 -> montant_euro , 2 -> client , 3 -> text , 4 -> float 
$sql=" 
set datestyle to 'SQL,EURO';
SELECT 1000000000 + date_part('epoch',datepaye),sum(montant*devise.nbeuros),client.uid,'reglement',0 from reglement,client,devise where devise.uid=devise and client.uid=client group by client.uid,datepaye,devise.uid order by datepaye ASC ";

$result=$conn->exec($sql); 
if (PGRES_TUPLES_OK ne $result->resultStatus) {
	print STDERR "ERREUR  : $sql failed : ".$conn->errorMessage;
	exit 0;
}

while (my @row = $result->fetchrow) {
	push (@lrglt,\@row);
	push (@merge,\@row);
}

# Recup des achats négatifs (remboursements) #
#======================#
#        0 -> date + 1e9 , 1 -> montant_euro , 2 -> client , 3 -> text , 4 -> float 
$sql=" 
set datestyle to 'SQL,EURO';
SELECT 1000000000 + date_part('epoch',datepaye),-sum(montanttc*devise.nbeuros),fournisseur.uid,'achat',0 from achat,fournisseur,devise where devise.uid=devise and fournisseur.uid=fournisseur group by fournisseur.uid,datepaye,devise.uid having  sum(montanttc*devise.nbeuros)<0 order by datepaye ASC ";

$result=$conn->exec($sql); 
if (PGRES_TUPLES_OK ne $result->resultStatus) {
	print STDERR "ERREUR  : $sql failed : ".$conn->errorMessage;
	exit 0;
}

while (my @row = $result->fetchrow) {
	push (@lrglt,\@row); # on met les achats négatifs dans les rglts pour rapprocher
}

# Recup des achats (déboursements) #
#======================#
#        0 -> date + 1e9 , 1 -> montant_euro , 2 -> client , 3 -> text , 4 -> float , 5 -> no chèque , 6 -> uid
$sql=" 
set datestyle to 'SQL,EURO';
SELECT 1000000000 + date_part('epoch',datepaye),montanttc*devise.nbeuros,fournisseur.uid,'achat',0,nocheque,achat.uid from achat,fournisseur,devise where devise.uid=devise and fournisseur.uid=fournisseur and montanttc>0 order by datepaye ASC ";

$result=$conn->exec($sql); 
if (PGRES_TUPLES_OK ne $result->resultStatus) {
	print STDERR "ERREUR  : $sql failed : ".$conn->errorMessage;
	exit 0;
}

while (my @row = $result->fetchrow) {
	push (@lachat,\@row); # on met les achats négatifs dans les rglts pour rapprocher
}

# Recup des salaires #
#======================#
#        0 -> date + 1e9 , 1 -> montant_euro , 2 -> intervenant , 3 -> text , 4 -> float , 5 -> comment , 6 -> uid
$sql=" 
set datestyle to 'SQL,EURO';
SELECT 1000000000 + date_part('epoch',timestamp(date('1/' || mois || '/' || annee))),net*devise.nbeuros,intervenant.uid,'salaire',0,comment,salaire.uid from salaire,intervenant,devise where devise.uid=devise and intervenant.uid=intervenant order by annee,mois ASC ";

$result=$conn->exec($sql); 
if (PGRES_TUPLES_OK ne $result->resultStatus) {
	print STDERR "ERREUR  : $sql failed : ".$conn->errorMessage;
	exit 0;
}

while (my @row = $result->fetchrow) {
	push (@lsalaire,\@row);
}

# Recup des charges #
#======================#
#        0 -> date + 1e9 , 1 -> montant_euro , 2 -> organisme , 3 -> text , 4 -> float , 5 -> cheque , 6 -> uid
$sql=" 
set datestyle to 'SQL,EURO';
SELECT 1000000000 + date_part('epoch',timestamp(datepaye)),montant*devise.nbeuros,organisme.uid,'charges',0,cheque,charges.uid from charges,organisme,devise where devise.uid=devise and organisme.uid=organisme order by datepaye ASC ";

$result=$conn->exec($sql); 
if (PGRES_TUPLES_OK ne $result->resultStatus) {
	print STDERR "ERREUR  : $sql failed : ".$conn->errorMessage;
	exit 0;
}

while (my @row = $result->fetchrow) {
	push (@lcharge,\@row);
}

# Recup des charges sociales #
#======================#
#        0 -> date + 1e9 , 1 -> montant_euro , 2 -> organisme , 3 -> text , 4 -> float , 5 -> cheque , 6 -> uid
$sql=" 
set datestyle to 'SQL,EURO';
SELECT 1000000000 + date_part('epoch',timestamp(datepaye)),montant*devise.nbeuros,organisme.uid,'ch_sociales',0,cheque,ch_sociales.uid from ch_sociales,organisme,devise where devise.uid=devise and organisme.uid=organisme order by datepaye ASC ";

$result=$conn->exec($sql); 
if (PGRES_TUPLES_OK ne $result->resultStatus) {
	print STDERR "ERREUR  : $sql failed : ".$conn->errorMessage;
	exit 0;
}

while (my @row = $result->fetchrow) {
	push (@lchargesoc,\@row);
}

# Recup des mouvements négatifs #
#======================#
#        0 -> date + 1e9 , 1 -> montant_euro , 2 -> uid , 3 -> text , 4 -> float , 5 -> libellé 
$sql=" 
set datestyle to 'SQL,EURO';
select 1000000000 + date_part('epoch',date),montant_euro,uid,'MVTN',0,libelle from mouvement_banque where montant_euro<0 order by date ASC;
";
$result=$conn->exec($sql); 
if (PGRES_TUPLES_OK ne $result->resultStatus) {
	print STDERR "ERREUR  : $sql failed : ".$conn->errorMessage;
	exit 0;
}
while (my @row = $result->fetchrow) {
	#print join($sep,@row)."\n";
	push (@lmvtn,\@row);
}

# Recup des mouvements positifs #
#======================#
#        0 -> date + 1e9 , 1 -> montant_euro , 2 -> uid , 3 -> text , 4 -> float , 5 -> libelle
$sql=" 
set datestyle to 'SQL,EURO';
select 1000000000 + date_part('epoch',date),montant_euro,uid,'MVT',0,libelle from mouvement_banque where montant_euro>0 order by date ASC;
";
$result=$conn->exec($sql); 
if (PGRES_TUPLES_OK ne $result->resultStatus) {
	print STDERR "ERREUR  : $sql failed : ".$conn->errorMessage;
	exit 0;
}
while (my @row = $result->fetchrow) {
	#print join($sep,@row)."\n";
	push (@lmvt,\@row);
	push (@merge,\@row);
}


## On trie les entrées MVT et RGLT par date ##
@lachat= sort {$::a->[0] <=> $::b->[0]} @lachat;
@lsalaire= sort {$::a->[0] <=> $::b->[0]} @lsalaire;
@lcharge= sort {$::a->[0] <=> $::b->[0]} @lcharge;
@lchargesoc= sort {$::a->[0] <=> $::b->[0]} @lchargesoc;
@lrglt= sort {$::b->[0] <=> $::a->[0]} @lrglt;




#=================================================================================#
#=================================================================================#


#=================================================================================#
## Calcul des rapprochements des entrées ##
#=============================#
my $i=0;
my %rapp=();
my %suspect=();
my $debug=0;

# Combinig sums... (down only)

# Methode no 1 : 
# pour chaque rglt, on teste sa somme avec tous les autres en descendant par date
# 
print STDERR " Combinig sums... (down only) 1st Method\n" if ($debug);
for my $r_mvt (@lmvt) {
	next if $r_mvt->[4]==1;
	my $success=0;
	my $montantCherche=$r_mvt->[1];
	my $start_idx=0;
	print STDERR "\n==================\nMontant : $montantCherche" if ($debug);

	while (!$success && $start_idx<$#lrglt) {
	    my @tmpRglt;
		my $sum=0;
		#print STDERR "\n\t ---- starting at $start_idx (".$lrglt[$start_idx]->[1].")\n" if ($debug);
		for my $idx ($start_idx .. $#lrglt) {
			# On jette si trop vieux...
			my $timeStop=1e9+timelocal(0,0,0,1,2,2000);
			next if ($lrglt[$idx]->[0]<$timeStop && !$complete);
			# On jette si deja utilisé...
			next if ($lrglt[$idx]->[4]==1 || $lrglt[$idx]->[0]>$r_mvt->[0]);

			$sum+=$lrglt[$idx]->[1];
			push (@tmpRglt,$lrglt[$idx]);

			if (round($sum,2)==round($montantCherche,2)) {
				print STDERR " \n\t\t SUCCESS" if ($debug);
				$success=1;
				last;
			}
			
			if (round($sum,2)>round($montantCherche,2)) {
				$success=0;
				last;
			}
			print STDERR "." if ($debug);
		}

		if ($success) {
			unshift @tmpRglt,$r_mvt;
			foreach (@tmpRglt) { $_->[4]=1; }
			$i++;
			$rapp{$i}=\@tmpRglt;
		} 
		# On passe à l'élément suivant de la liste :
		$start_idx++;
	}
	if (!$success) { 
		print STDERR "\n\n\t\t FAILED \n\n" if ($debug);
	}
}


# Methode no 2 :
# On fixe un rglt, et on teste la somme avec les suivants 
# 
#print STDERR "\n". "="x30  ." Combinig sums... 2nd method\n" if ($debug);
PR:for my $r_mvt (@lmvt) {
    next if $r_mvt->[4]==1;
    my $success=0;
    my $montantCherche=$r_mvt->[1];
    #print STDERR "\n==================\nMontant : $montantCherche" if ($debug);
    
    IDX1:for my $start_idx (0 .. $#lrglt) {
		my @tmpRglt;
		my $sum=0;
		my $suspect=0;
		my $start_rglt=$lrglt[$start_idx];
		my $second_start=$start_idx+1;
		my $sous_idx=$second_start;
		# On jette si trop grand...
		next if ($start_rglt->[1]>$montantCherche);
		# On jette si deja utilisé...
		next if ($start_rglt->[4]==1);
		# On jette si trop recent...
		next if ($start_rglt->[0]>$r_mvt->[0]);
		
		push @tmpRglt,$start_rglt;
		$sum=$start_rglt->[1];
		
		#print STDERR "\t ---- starting at $start_idx (".$lrglt[$start_idx]->[1].")\n" if ($debug);
		
		IDX2:while ($sum<$montantCherche && $sous_idx<$#lrglt) {

			# On jette si trop vieux...
			my $timeStop=1e9+timelocal(0,0,0,1,2,2000);
			if ($lrglt[$sous_idx]->[0]<$timeStop && !$complete) { 
				$sous_idx++;
				#print STDERR "Trop vieux...\n" if ($debug);
				next;
			}
			# On jette si deja utilisé, si trop vieux, etc...
			if (
				$lrglt[$sous_idx]->[4]==1 
				|| $lrglt[$sous_idx]->[0]>$r_mvt->[0] 
				|| (($r_mvt->[0]-$lrglt[$sous_idx]->[0])>60*60*24*50 && !$complete)
				) { 
				$sous_idx++;
				#print STDERR "Pas cool...".$lrglt[$sous_idx]->[0]." ".$r_mvt->[0]."\n" if ($debug);
				next;}
			
			$sum+=$lrglt[$sous_idx]->[1];
			push (@tmpRglt,$lrglt[$sous_idx]);
			#print STDERR "($sous_idx)  + ".round($lrglt[$sous_idx]->[1],2)." = $sum\n" if ($debug);
			
			if (round($sum,2)==round($montantCherche,2)) {
				#print STDERR " \n\n\t\t SUCCESS \n\n" if ($debug);
				$success=1;
				last;
			}
			
			# =====Recherche suspicion============
			if (abs($montantCherche/$sum -1)<1e-5) {
				#print STDERR "\n\t\t ======SUSPICION SIMPLE======\n" if ($debug);
				#print STDERR "\t\t pour le montant ".round($montantCherche,2)."\n" if ($debug);
				my @tmpSusp;
				@tmpSusp=@tmpRglt;
				foreach (@tmpSusp) { $_->[4]=2; }
				unshift @tmpSusp,$r_mvt;
				$i++;
				$suspect{$i}=\@tmpSusp;
			}
			# ====================================
			
			if (round($sum,2)>round($montantCherche,2)) {
				$success=0;
				$second_start++;
				$sous_idx=$second_start;
				$sum=$start_rglt->[1];
				@tmpRglt=($start_rglt);
				next;
			}
			$sous_idx++;
			#print STDERR "." if ($debug);
		} # End of while -> starting with the next index for start_idx

		if ($success) {
			unshift @tmpRglt,$r_mvt;
			foreach (@tmpRglt) { $_->[4]=1; }
			$i++;
			$rapp{$i}=\@tmpRglt;
			next PR;
		}
		# On passe à l'élément suivant de la liste : next start_idx
    }
	if (!$success) { 
		#print STDERR "\n\n\t\t FAILED \n\n" if ($debug);
	}
}



#=================================================================================#
#=================================================================================#
## Calcul des rapprochements des achats ##
#=============================#

# Methode no 1 : 
# pour chaque achat, on teste l'existence du cheque...
# 
PR:for my $r_mvt (@lmvtn) {
	next if $r_mvt->[4]==1;
	for my $r_ach (@lachat) {
		next if $r_ach->[4]==1;
		if ($r_ach->[5] && $r_mvt->[5] =~/$r_ach->[5]/ && abs($r_mvt->[0]-$r_ach->[0])<60*60*24*15) {
			# Meme no de chèque...
			$r_mvt->[4]=1;
			$r_ach->[4]=1;
			my @tmpArr;
			push @tmpArr,$r_mvt;
			push @tmpArr,$r_ach;
			$rapp{++$i}=\@tmpArr;
			next PR;
		}
	}
}

# Methode no 2 : 
# pour chaque achat, on teste le montant
# 
PR:for my $r_mvt (@lmvtn) {
	next if $r_mvt->[4]==1;
	for my $r_ach (@lachat) {
		next if $r_ach->[4]==1;
		if (round($r_mvt->[1],2)==-round($r_ach->[1],2) && abs($r_mvt->[0]-$r_ach->[0])<60*60*24*15) {
			$r_mvt->[4]=1;
			$r_ach->[4]=1;
			my @tmpArr;
			push @tmpArr,$r_mvt;
			push @tmpArr,$r_ach;
			$rapp{++$i}=\@tmpArr;
			next PR;
		}
	}
}
# Suspicions :
PR:for my $r_mvt (@lmvtn) {
	next if $r_mvt->[4]!=0;
	for my $r_ach (@lachat) {
		next if $r_ach->[4]!=0;
		if (round($r_mvt->[1],2)==-round($r_ach->[1],2)) {
			$r_mvt->[4]=2;
			$r_ach->[4]=2;
			my @tmpArr;
			push @tmpArr,$r_mvt;
			push @tmpArr,$r_ach;
			$suspect{++$i}=\@tmpArr;
			next PR;
		}
	}
}


#=================================================================================#
#=================================================================================#
## Calcul des rapprochements des salaires ##
#=============================#

# Methode no 1 : 
# pour chaque salaire, on teste l'existence du cheque...
# 
PR:for my $r_mvt (@lmvtn) {
	next if $r_mvt->[4]==1;
	for my $r_ach (@lsalaire) {
		next if $r_ach->[4]==1;
		next if (!$r_ach->[5]);
		my $nochq;
		($nochq)=($r_ach->[5]=~/chq ([0-9]*)/);
		next if (!$nochq);
		if ($r_ach->[5] && $r_mvt->[5] =~/$nochq/) {
			# Meme no de chèque...
			$r_mvt->[4]=1;
			$r_ach->[4]=1;
			my @tmpArr;
			push @tmpArr,$r_mvt;
			push @tmpArr,$r_ach;
			$rapp{++$i}=\@tmpArr;
			next PR;
		}
	}
}
# Suspicions :
PR:for my $r_mvt (@lmvtn) {
	next if $r_mvt->[4]!=0;
	for my $r_ach (@lsalaire) {
		next if $r_ach->[4]!=0;
		if (round($r_mvt->[1],2)==-round($r_ach->[1],2) && abs($r_mvt->[0]-$r_ach->[0])<60*60*24*45) {
			$r_mvt->[4]=2;
			$r_ach->[4]=2;
			my @tmpArr;
			push @tmpArr,$r_mvt;
			push @tmpArr,$r_ach;
			$suspect{++$i}=\@tmpArr;
			next PR;
		}
	}
}


#=================================================================================#
#=================================================================================#
## Calcul des rapprochements des charges ##
#=============================#

# Methode no 1 : 
# pour chaque charge, on teste l'existence du cheque...
# 
PR:for my $r_mvt (@lmvtn) {
	next if $r_mvt->[4]==1;
	for my $r_ach (@lcharge) {
		next if $r_ach->[4]==1;
		if ($r_ach->[5] && $r_mvt->[5] =~/$r_ach->[5]/ && abs($r_mvt->[0]-$r_ach->[0])<60*60*24*15) {
			# Meme no de chèque...
			$r_mvt->[4]=1;
			$r_ach->[4]=1;
			my @tmpArr;
			push @tmpArr,$r_mvt;
			push @tmpArr,$r_ach;
			$rapp{++$i}=\@tmpArr;
			next PR;
		}
	}
}

# Methode no 2 : 
# pour chaque achat, on teste le montant
# 
PR:for my $r_mvt (@lmvtn) {
	next if $r_mvt->[4]==1;
	for my $r_ach (@lcharge) {
		next if $r_ach->[4]==1;
		if (round($r_mvt->[1],2)==-round($r_ach->[1],2) && abs($r_mvt->[0]-$r_ach->[0])<60*60*24*15) {
			$r_mvt->[4]=1;
			$r_ach->[4]=1;
			my @tmpArr;
			push @tmpArr,$r_mvt;
			push @tmpArr,$r_ach;
			$rapp{++$i}=\@tmpArr;
			next PR;
		}
	}
}
# Suspicions :
PR:for my $r_mvt (@lmvtn) {
	next if $r_mvt->[4]==1;
	for my $r_ach (@lcharge) {
		next if $r_ach->[4]==1;
		if (round($r_mvt->[1],2)==-round($r_ach->[1],2) && abs($r_mvt->[0]-$r_ach->[0])<60*60*24*45) {
			$r_mvt->[4]=2;
			$r_ach->[4]=2;
			my @tmpArr;
			push @tmpArr,$r_mvt;
			push @tmpArr,$r_ach;
			$suspect{++$i}=\@tmpArr;
			next PR;
		}
	}
}



#=================================================================================#
#=================================================================================#
## Calcul des rapprochements des charges sociales ##
#=============================#

# Methode no 1 : 
# pour chaque charge, on teste l'existence du cheque...
# 
PR:for my $r_mvt (@lmvtn) {
	next if $r_mvt->[4]==1;
	for my $r_ach (@lchargesoc) {
		next if $r_ach->[4]==1;
		if ($r_ach->[5] && $r_mvt->[5] =~/$r_ach->[5]/ && abs($r_mvt->[0]-$r_ach->[0])<60*60*24*15) {
			# Meme no de chèque...
			$r_mvt->[4]=1;
			$r_ach->[4]=1;
			my @tmpArr;
			push @tmpArr,$r_mvt;
			push @tmpArr,$r_ach;
			$rapp{++$i}=\@tmpArr;
			next PR;
		}
	}
}

# Methode no 2 : 
# pour chaque achat, on teste le montant
# 
PR:for my $r_mvt (@lmvtn) {
	next if $r_mvt->[4]==1;
	for my $r_ach (@lchargesoc) {
		next if $r_ach->[4]==1;
		if (round($r_mvt->[1],2)==-round($r_ach->[1],2) && abs($r_mvt->[0]-$r_ach->[0])<60*60*24*15) {
			$r_mvt->[4]=1;
			$r_ach->[4]=1;
			my @tmpArr;
			push @tmpArr,$r_mvt;
			push @tmpArr,$r_ach;
			$rapp{++$i}=\@tmpArr;
			next PR;
		}
	}
}
# Suspicions :
PR:for my $r_mvt (@lmvtn) {
	next if $r_mvt->[4]==1;
	for my $r_ach (@lchargesoc) {
		next if $r_ach->[4]==1;
		if (round($r_mvt->[1],2)==-round($r_ach->[1],2) && abs($r_mvt->[0]-$r_ach->[0])<60*60*24*45) {
			$r_mvt->[4]=2;
			$r_ach->[4]=2;
			my @tmpArr;
			push @tmpArr,$r_mvt;
			push @tmpArr,$r_ach;
			$suspect{++$i}=\@tmpArr;
			next PR;
		}
	}
}








#=================================================================================#
#=================================================================================#
# Affichage #
#======================
#print STDERR "" . "="x50 ."\n";
# succes :
for $i (keys(%rapp)) {
	my @lref=@{$rapp{$i}};
	my $date=strftime("%d/%m/%Y",localtime($lref[0]->[0]-1000000000));
	#print STDERR <<EOF;
	____________________________________
	Mouvement du $date de $lref[0]->[1] ¤ constitué de :
EOF
	foreach my $idxRglt (1 .. $#lref) {
		my $date=strftime("%d/%m/%Y",localtime($lref[$idxRglt]->[0]-1000000000));
		#print STDERR "\t\t ".$lref[$idxRglt]->[3]." ".$lclient{$lref[$idxRglt]->[2]}." du $date de ".round($lref[$idxRglt]->[1],2)." ¤\n";
	}
}

# suspicions :
#print STDERR "\n___________________\n Suspicions :\n";
for $i (keys(%suspect)) {
	my @lref=@{$suspect{$i}};
	my $date=strftime("%d/%m/%Y",localtime($lref[0]->[0]-1000000000));
	#print STDERR <<EOF;
	____________________________________
	Mouvement du $date de $lref[0]->[1] ¤ [ $lref[0]->[5] ] constitué de :
EOF
	foreach my $idxRglt (1 .. $#lref) {
		my $date=strftime("%d/%m/%Y",localtime($lref[$idxRglt]->[0]-1000000000));
		#print STDERR "\t\t ".$lref[$idxRglt]->[3]." ".$lclient{$lref[$idxRglt]->[2]}." du $date de ".round($lref[$idxRglt]->[1],2)." ¤\n";
		# les rglts sont groupés par date-client : 
	}
}

# echecs :
#print STDERR "\n\n====Echecs===================\n";
for my $r_mvt (@lmvt) {
	next if $r_mvt->[4]!=0;
	#print STDERR "Echec pour mvt du ".strftime("%d %m %Y",localtime($r_mvt->[0]-1000000000))." de ".round($r_mvt->[1],2)." ¤ (soit ".round($r_mvt->[1]*6.55957,2)." FRF)\n";
}
for my $r_mvt (@lmvtn) {
	next if $r_mvt->[4]!=0;
	#print STDERR "Echec pour mvt du ".strftime("%d %m %Y",localtime($r_mvt->[0]-1000000000))." de ".round($r_mvt->[1],2)." ¤ (soit ".round($r_mvt->[1]*6.55957,2)." FRF) [".$r_mvt->[5]."]\n";
}


#print STDERR "\n\n=============================\n";
for my $r_rglt (@lrglt) {
	next if $r_rglt->[4]!=0;
	my ($jour,$mois,$annee)=split(' ',strftime("%d %m %Y",localtime($r_rglt->[0]-1000000000)));
	my $timeStop=timelocal(0,0,0,1,2,2001)+1000000000;
	next if ($r_rglt->[0]<$timeStop);
	#print STDERR "Echec pour ".$r_rglt->[3]." du $jour/$mois/$annee de ".substr(" "x15 . $lclient{$r_rglt->[2]}." ",-18)." de ".substr(" "x15 .round($r_rglt->[1],2)." ",-12)." ¤ (soit ".substr(" "x15 .round($r_rglt->[1]*6.55957,2)." ",-12)." FRF)\n";
}
for my $r_rglt (@lachat) {
	next if $r_rglt->[4]!=0;
	my ($jour,$mois,$annee)=split(' ',strftime("%d %m %Y",localtime($r_rglt->[0]-1000000000)));
	my $timeStop=timelocal(0,0,0,1,2,2001)+1000000000;
	next if ($r_rglt->[0]<$timeStop);
	#print STDERR "Echec pour ".$r_rglt->[3]." du $jour/$mois/$annee de ".substr(" "x15 . $lclient{$r_rglt->[2]}." ",-18)." de ".substr(" "x15 .round($r_rglt->[1],2)." ",-12)." ¤ (soit ".substr(" "x15 .round($r_rglt->[1]*6.55957,2)." ",-12)." FRF)\n";
}
#======================

#======================#=============================================#======================#
#======================#               Génération SQL                #======================#
#======================#=============================================#======================#

my @req;
for $i (keys(%rapp)) {
	my @lref=@{$rapp{$i}};
	my $date=strftime("%d/%m/%Y",localtime($lref[0]->[0]-1000000000));
	foreach my $idxRglt (1 .. $#lref) {
		if ($lref[$idxRglt]->[3] =~ /achat|reglement/) {
			# les rglts/achats sont groupés par date-client/fournisseur : 
			my $payeur="client";
			$payeur="fournisseur" if ($lref[$idxRglt]->[3] eq "achat");
			push @req,"INSERT INTO rapprochement (".$lref[$idxRglt]->[3].",mouvement_banque) select ".$lref[$idxRglt]->[3].".uid,".$lref[0]->[2]." from ".$lref[$idxRglt]->[3]." where timestamp(datepaye)=".($lref[$idxRglt]->[0]-1000000000)." and $payeur=".$lref[$idxRglt]->[2].";\n";
		}
		else {
			push @req,"INSERT INTO rapprochement (".$lref[$idxRglt]->[3].",mouvement_banque) values (".$lref[$idxRglt]->[6].",".$lref[0]->[2].");\n";
		}
	}
}

if ($complete) {
	for $i (keys(%suspect)) {
		my @lref=@{$suspect{$i}};
		my $date=strftime("%d/%m/%Y",localtime($lref[0]->[0]-1000000000));
		foreach my $idxRglt (1 .. $#lref) {
			if ($lref[$idxRglt]->[3] =~ /achat|reglement/) {
				# les rglts/achats sont groupés par date-client/fournisseur : 
				my $payeur="client";
				$payeur="fournisseur" if ($lref[$idxRglt]->[3] eq "achat");
				push @req,"INSERT INTO rapprochement (".$lref[$idxRglt]->[3].",mouvement_banque) select ".$lref[$idxRglt]->[3].".uid,".$lref[0]->[2]." from ".$lref[$idxRglt]->[3]." where timestamp(datepaye)=".($lref[$idxRglt]->[0]-1000000000)." and $payeur=".$lref[$idxRglt]->[2].";\n";
			}
			else {
				push @req,"INSERT INTO rapprochement (".$lref[$idxRglt]->[3].",mouvement_banque) values (".$lref[$idxRglt]->[6].",".$lref[0]->[2].");\n";
			}
		}
	}
}


#=================================================================================#
#=================================================================================#
#                          Génération HTML

print <<EOF;
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html>
  <head>
    <title>PimenGest / Rapprochements </title>
    <style>
A {
 font-family: Arial, Helvetica, sans-serif; 
 color:white;
 font-size: x-small;
 font-weight: bold;
 text-decoration:none;
 }
TABLE.FOND {
 background-color:#aa5858;
}
TH {
  font-family: Arial, Helvetica, sans-serif; 
 color:white;
 background-color:#7a7a7a;
 font-size: x-small;
 }
TD {
  font-family: Arial, Helvetica, sans-serif; 
 color:black;
 background-color:#bac0c0;
 font-size: x-small;
 }
TD.PAIR {
  font-family: Arial, Helvetica, sans-serif; 
 color:black;
 background-color:#aaaaaa;
 font-size: x-small;
 font-weight: bold;
 }
TD.IMPAIR {
  font-family: Arial, Helvetica, sans-serif; 
 color:black;
 background-color:#bbbbbb;
 font-size: x-small;
 font-weight: bold;
 }
INPUT {
  font-family: Arial, Helvetica, sans-serif; 
 font-size: x-small;
 }
SELECT {
  font-family: Arial, Helvetica, sans-serif; 
 font-size: x-small;
 }
TEXTAREA {
  font-family: Arial, Helvetica, sans-serif; 
 font-size: x-small;
 }
BODY {
  font-family: Arial, Helvetica, sans-serif; 
 margin-width:0;
 margin-height:0;
 color:white;
 background-color:#9fb6cd;
 font-size: x-small;
 }
.PRIX {
 background-color:#787878;
}
.ACHAT {
 background-color:#cc2222;
}
.SALAIRE {
 background-color:#5555cc;
}
.CHARGES {
 background-color:orange;
}
.CH_SOCIALES {
 background-color:orange;
}
.REGLEMENT {
 background-color:green;
}

   </style>
  </head>
<body bgcolor="white" marginwidth=0>
EOF


# suspicions :
print "<br>___________________<br> Suspicions :<br>";
print '<table cellspacing="0" cellpadding="3">';
for $i (keys(%suspect)) {
	my @lref=@{$suspect{$i}};
	my $date=strftime("%d/%m/%Y",localtime($lref[0]->[0]-1000000000));
	my $montant=round($lref[0]->[1],2);
	print <<EOF;
	<tr><td colspan="2" bgcolor="white">&nbsp;</td></tr>
	<tr><th colspan="2" align="left" nowrap>Mouvement du $date de $montant Eur [&nbsp;$lref[0]->[5]&nbsp;]&nbsp;:</th></tr>
EOF
	foreach my $idxRglt (1 .. $#lref) {
		my $date=strftime("%d/%m/%Y",localtime($lref[$idxRglt]->[0]-1000000000));
		print "<tr><td width=\"100\" align=\"right\">-</td><td>".$lref[$idxRglt]->[3]." ".$lclient{$lref[$idxRglt]->[2]}." du $date de ".round($lref[$idxRglt]->[1],2)." Eur</td></tr>";
		# les rglts sont groupés par date-client : 
	}
}
print '</table>';




