#!/usr/bin/perl -w

# Source: @RPM_PACKAGE_VERSION@-@RPM_PACKAGE_RELEASE@

use utf8;
use strict;
use warnings;

BEGIN {
        
        unshift(@INC,($ENV{'POPHOME'}||'@POPHOME@').'/lib')
			unless $ENV{'KUNDE_NO_PERLPATH'};
      }

select(STDERR); $|=1; select(STDOUT);

print "*** Rechnungen anzeigen\n\n" if -t STDIN;

use Umlaut qw(textmodus);
use Cf qw($WDESCR $MAILDOM $MWSTKO);
use Dbase::Help qw(DoFn unixdate DoSelect isodate Do DoTime);
use Dbase::Globals qw(find_descr sendmail name_kunde bignum);
use Loader qw(
	acct_text
	edit_arechnung export_fibunet
	list_arechnung_text lister
	set_arechnung_text
  );
use IO::File;
use IO::Pipe;
use Fehler qw(fehler report_fehler probleme warnungen hat_problem ffehler
	problem ffehler);

my $vers = '@RPM_PACKAGE_VERSION@-@RPM_PACKAGE_RELEASE@';
my $lp;

sub Usage() {
	textmodus(\*STDERR);
    die <<END;
Usage: $0 -- verarbeitet Rechnungen
1  Verarbeitungsschritte:
       -b     gibt Buchungssätze aus (Fibunet)
       -B     gibt Buchungssätze aus (Lexware)
        -o XX  ... in diese Datei (statt stdout)
       -D     gibt dtaus-Datei aus
       -Q     gibt FibuNet-Änderungsdaten für Abbuchungen aus
       -A X/Y gibt Abbuchungs-Datei aus (Lexware; Buchungsdatum X, Beleg Y)
        -O XX  ... in diese Datei (statt stdout)

       -m     mailt Rechnungen
       -p     druckt Rechnungen
2  Ansehen/Editieren:
       -e/-E  ruft die Rechnung (-E: nur) zum Editieren auf
       -v     schickt die Rechnung durch "less"
       -w XX  schreibt die Rechnung in Datei XX   %r => RNR  %k => Kunde
3  Auswahl:
       -d XX  Rechnungen ab Datum XX
       -r XX  ab dieser Rechnung (inkl.)
       -R XX  bis zu dieser Rechnung (inkl.)
       -a     alle passenden Rechnungen
       Rechnungsnummer...
              diese Rechnungen
   Sonst:
       -F     Maile/Drucke die angegebenen Rechnungen, egal was im Kunden steht
       -f     verarbeite alle ausgewählten Rechnungen, egal ob notwendig
       -n     vermerke die ausgeführten Aktionen nicht in der Datenbank
       -L     jede Rechnung einzeln drucken (ansonsten: ein dicker Druckjob)
       -P XX  Drucke auf Ausgabe# XX (siehe 'kunde >?')
       -i xx  Verzögerung (_I_ntervall) zwischen Ausdrucken (Sekunden)

Opt(1+2) Aktion
 -?-     Nichts passiert.
 3--     Die ausgewählten Rechnungen werden angezeigt.
 ?-1     Die Dateien werden erstellt / die Rechnungen werden gedruckt
          für diejenigen Rechnungen, bei denen das noch nicht passiert ist.
 ?21     Alle Rechnungen, für die eine der angegebenen Schritte ansteht,
          werden angezeigt.

Falls eine Auswahl(3) getroffen wurde, werden nur die dort angegebenen
Rechnungen verarbeitet. Nur dann kann '-f' verwendet werden.

Version: $vers
END
  exit 1;
}

use Getopt::Std;
our($opt_h,$opt_a,$opt_b,$opt_P,$opt_B,$opt_e,$opt_E,$opt_m,$opt_p,$opt_f,$opt_F,$opt_A,$opt_o,$opt_w,$opt_R,$opt_r,$opt_O,$opt_d,$opt_v,$opt_n,$og1,$og2,$og3,$opt_Q,$opt_i,$opt_L);
getopts("aA:bBcd:eEfFhi:Lmno:O:pP:Qr:R:vw:") or Usage;
Usage if $opt_h;
Usage if @ARGV == 0 and not defined $opt_a and not defined $opt_r and not defined $opt_d and not defined $opt_A and not defined $opt_Q;
Usage if $opt_d and not ($opt_d = unixdate $opt_d);
my $opt_beleg;
if($opt_A) {
	Usage unless $opt_A =~ s/\/(.+)$//;
	$opt_beleg = $1;
	Usage unless $opt_A = unixdate $opt_A;
}
$og1 = $opt_b || $opt_B || $opt_Q || $opt_A || $opt_m || $opt_p;
$og2 = ($opt_w or $opt_v or $opt_e or $opt_E);
$og3 = ($opt_d or $opt_r or @ARGV);
exit 0 if not $og1 and not $og3;
if($og3 and not $og2 and not $og1) {
	$opt_v=1;
	$og2=1;
}
if(defined $opt_P) {
	my $pr = find_descr("ausgabe",$opt_P);
	die "Ausgabe '$opt_P' nicht bekannt.\n" unless $pr;
	$opt_P = $pr;
}

Usage if $opt_f and not $og3;
Usage if $opt_F and $opt_p and $opt_m;

my $lastpr=0;

my $abit = find_descr("rstatus","abbuchen");
$abit = bignum(1)<<$abit if $abit;
my $nabit = 0xffff & ~$abit;

my $abbit = find_descr("rstatus","abgebucht");
$abbit = bignum(1)<<$abbit if $abbit;
my $nabbit = 0xffff & ~$abbit;

my $bbit = find_descr("rstatus","buchen");
$bbit = bignum(1)<<$bbit if $bbit;
my $nbbit = 0xffff & ~$bbit;

my $dbit = find_descr("rstatus","gedruckt");
$dbit = bignum(1)<<$dbit if $dbit;
my $ndbit = 0xffff & ~$dbit;

my $mbit = find_descr("rstatus","gemailt");
$mbit = bignum(1)<<$mbit if $mbit;
my $nmbit = 0xffff & ~$mbit;

my $kmbit = find_descr("kunde","mail");
$kmbit = bignum(1)<<$kmbit if $kmbit;
my $nkmbit = 0xffff & ~$kmbit;

## CODE ##
my @rech;
my $sel;
if($opt_b or $opt_B) {
	unless($opt_f) {
		$sel .= " and (rechnungen.flags & ".($bbit|$bbit).")";
	}
}
if($opt_A or $opt_Q) {
	unless($opt_f) {
		$sel .= " and ((rechnungen.flags & $abbit) = $abbit)";
	}
}
if($opt_m or $opt_p) {
	unless($opt_f) {
		$sel .= " and not (rechnungen.flags & ".($mbit|$dbit).")";
	}
}
if($opt_d) {
	$sel .= " and rechnungen.datum >= $opt_d";
}
if($opt_r) {
	$sel .= " and rnr >= $opt_r";
}
if($opt_R) {
	$sel .= " and rnr <= $opt_R";
}
if(@ARGV) {
	$sel .= " and ( rnr = ".join(" or rnr = ", @ARGV)." ) ";
}

DoSelect {
	push(@rech,$_[0]);
} "select rechnungen.rnr from rechnungen,kunde where kunde.id = rechnungen.kunde $sel order by rechnungen.rnr";

die "Keine Rechnungen gefunden!\n" unless @rech;

## dtaus1
my $xbetragsum = 0;
my $xkontosum = 0;
my $xblzsum = 0;
my $xanz = 0;
my $zref;
my $ttmmjj;
sub gross($) {
    my($r) = @_;
    $r =~ tr/a-zäöü/A-ZÄÖÜ/; ## notwendig???
    $r =~ tr/äöüÄÖÜß/\204\224\201\x8e\x99\x9a\xe1/; ## PC-Zeichensatz
	$r;
}

if($opt_b or $opt_B) {
	open(ABB,">".($opt_o || "&STDOUT")) or die "Konnte keine Ausgabedatei generieren: $!\n";
}
if($opt_A) {
	my($y,$m,$d) = isodate $opt_A;
	$m = "0$m" if $m <= 9;
	$d = "0$d" if $d <= 9;
	$opt_A = "$d.$m.$y";
	open(DTEIN,">".($opt_O || "&STDOUT")) or die "Konnte keine Abbuchungsdatei generieren: $!\n";
}

my $Qdata = qq#( ):0001;1;0\n#;

my @gedruckt=();
rech: foreach my $rech(@rech) {
  ffehler {
	my ($fl,$kf) = DoFn("select rechnungen.flags,kunde.flags from rechnungen,kunde where rnr = $rech and kunde.id = rechnungen.kunde");

	my $do;
	$do++ if ($opt_b or $opt_B) and ($opt_f or $fl&$bbit);
	$do++ if ($opt_A or $opt_Q) and ($opt_f or $fl&$abbit);
	$do++ if ($opt_m          ) and ($opt_f or not $fl&$mbit) and ($opt_F or $kf&$kmbit);
	$do++ if ($opt_p          ) and ($opt_f or not $fl&$dbit) and ($opt_F or not $kf&$kmbit);

# -?-     Nichts passiert.
# --1     Die Dateien werden erstellt / die Rechnungen werden gedruckt
#          für diejenigen Rechnungen, bei denen das noch nicht passiert ist.
# -21     Alle Rechnungen, für die eine der angegebenen Schritte ansteht,
#          werden angezeigt.
#	## LESS
	if($opt_v or $opt_e) {
		list_arechnung_text($rech);
	}
	if($opt_w) {
		my $fn = $opt_w;
		$fn =~ s/%k/DoFn("select kunde from rechnungen where rnr=$rech")/eg;
		$fn =~ s/%r/$rech/g;
		my $data = DoFn("select rtext from rechnungen where rnr = $rech");
		open(R,">> $fn") or fehler "Open Datei '$fn': $!";
		print R $data or fehler "Schreibe Datei '$fn': $!";
		close(R) or fehler "Schreibe Datei '$fn': $!";
	}
	if($opt_E) {
		set_arechnung_text($rech);
	}
	if(not hat_problem and ($opt_e or $opt_E)) {
		my $res = edit_arechnung($rech,0,"###Rech###",8);
		last rech if not defined $res or $res eq "Q";
		next rech if $res eq "q";
	}

	## Output
	if(not hat_problem and $opt_B and ($opt_f or $fl&$bbit)) { # Lexware
		#31.01.2000;A;20000014;2000-01, 8482, 35326;512.34;11162;
		#;;;MWSt 2000-01, 8482, 35326;70.67;;1777
		#;;;weissman: Bundle-128KB-1GB, 2000-01, xxx;441.67;;8482
		my($betrag,$steuer,$inh,$rd,$knd) = DoFn("select betrag,steuer,infotext,datum,kunde from rechnungen where rnr = $rech");
		if($rd) {
			$knd += 10000;
			my($y,$m,$d)=isodate $rd;
			$d = "0$d" if $d < 10;
			$m = "0$m" if $m < 10;
			$rd = "$d.$m.$y";

			$betrag /= 100;
			$steuer /= 100;
			my $sbetr = $betrag+$steuer;
			$sbetr = sprintf("%.2f",$sbetr);
			$betrag = sprintf("%.2f",$betrag);
			$steuer = sprintf("%.2f",$steuer);

			print ABB <<END;
$rd;A;$rech;$inh;$sbetr;$knd;
;;;MWSt $inh;$steuer;;$MWSTKO
END
			DoSelect {
				my($kd,$ko,$in,$be) = @_;
				$kd += 10000;
				$in = name_kunde($kd-10000).": $in" if $kd != $knd;
				$be /= 100;
				$be = sprintf("%.2f",$be);
				print ABB <<END;
;;;$in;$be;;$ko
END
			} "select kunde,konto,buchtext,betrag from buchung where rnr = $rech";
		} else {
			print STDERR "Rechnung '$rech' nicht lesbar.\n";
		}
	}
	if(not hat_problem and $opt_b and ($opt_f or $fl&$bbit)) { # FibuNet
		die "FibuNet-Buchungssätze kann ich noch nicht generieren.\n";
	}
	if(not hat_problem and $opt_A and ($opt_f or not ($abit|$abbit)&~$fl)) { # dtaus-Datei
		my($betrag,$rd,$knr) = DoFn("select betrag+steuer,datum,kunde from rechnungen where rnr = $rech");

		if($rd) {
#05.03.1998;B;420207;ZE-Abb. Olbrich / ReA980006;39.00;1210;10491
			my $kname = name_kunde($knr);
			$knr += 10000;
			$betrag = sprintf("%.2f",$betrag/100);

			print DTEIN "$opt_A;B;$opt_beleg;ZE-Abb $kname / ReA$rech;$betrag;1210;$knr\n";
			Do("update rechnungen set flags = flags & $nabit where rnr = $rech") unless $opt_n;
		} else {
			print STDERR "Rechnung '$rech' nicht eingebucht.\n";
		}
	}
	if(not hat_problem and $opt_Q and ($opt_f or ($abbit&$fl))) { # dtaus-Datei
		my($knr) = DoFn("select kunde from rechnungen where rnr = $rech");
		$knr += 10000;
		$Qdata .= qq#( ):1112;$knr;"A$rech";;;;;;;;;;;;;;;;;"d";\n#;
		$Qdata .= qq#( ):0005;"rech Q $vers"\n#;
	}

	## Versenden
	if(not hat_problem) {
		my $done;
		if($opt_m) {
			## zone-c/prio  nic/prio  zone-c/0  nic/0  :/1
			my $kunde = DoFn("select kunde from rechungen where rnr= $rech");
			my $pers = DoFn("select billc from kunde where id=$kunde");
			$pers = DoFn("select hauptperson from kunde where id=$kunde") unless $pers;
			
			if(defined $pers) {
				my $dat = DoFn("select rtext from rechnungen where rnr = $rech");
				sendmail(<<END.$dat, "faktura\@$MAILDOM",$pers);
From: Faktura $WDESCR <faktura\@$MAILDOM
To: $pers
Subject: Rechnung $WDESCR-$rech

END
				$done++;
			} else {
				print "$rech: keine Mailadresse: Drucken!\n";
				$kf &= $nkmbit;
			}
			
		}
		if($opt_p and ($opt_f or not $fl&$dbit) and ($opt_F or not $kf&$kmbit)) {
			my $dat = DoFn("select rtext from rechnungen where rnr = $rech");
			my($nbs) = DoFn("select count(*) from buchung where rnr = $rech");

			$dat = acct_text($rech) if $fl & (bignum(1)<<find_descr("rstatus","manuell")) and $nbs;

			unless(defined $dat) {
				problem "Rechnung $rech ist leer.","Evtl. DB-Sync-Problem, probiers in fünf Minuten nochmal.";
				next;
			}
			if($opt_i) {
				my $now = DoTime;
				sleep($opt_i-($now-$lastpr)) if($now-$lastpr) < $opt_i;
				$lastpr = $now;
			}
			if($lp) {
				print $lp "\f";
			} else {
				$lp = lister( defined $opt_P ? $opt_P : 2 );
			}
			print $lp $dat or fehler "Kein Druck: $rech: $!\n";
			if($opt_L) {
				my $lpx = $lp; $lp = undef;
				$lpx->close or fehler "Kein Druck: $rech: $!\n";

			}

			if($opt_L) {
				Do("update rechnungen set flags = flags | $dbit where rnr = $rech") if defined $opt_P and not $opt_n;
			} else {
				push(@gedruckt,$rech);
			}
			$done++;
		}
	}
	probleme { print STDERR "Problem: @_\n"; warnungen { 1; }; 1; };
	warnungen { print STDERR "Warnung: @_\n"; 1; };
  } sub {
	report_fehler;
  };
}

if($lp) {
	$lp->close or fehler "Kein Druck: $!\n";
	if(@gedruckt and defined $opt_P and not $opt_n) {
		foreach my $rech(@gedruckt) {
			Do("update rechnungen set flags = flags | $dbit where rnr = $rech");
		}
	}
}

if($opt_Q) {
	ffehler {
		export_fibunet( sub { $Qdata }, 'Markieren DTAUS' );
	} sub {
		problem @_;
	}
}

exit(0);
