=================================================================== RCS file: /cvs/pta/pta.pl,v retrieving revision 1.7 retrieving revision 1.8 diff -u -p -r1.7 -r1.8 --- pta/pta.pl 2020/11/18 12:55:44 1.7 +++ pta/pta.pl 2020/11/18 16:35:40 1.8 @@ -20,16 +20,18 @@ use strict; use Getopt::Std qw(getopts); use Time::Local qw(timegm); -our ($opt_a, $opt_b, $opt_c, $opt_L, $opt_n, $opt_p, $opt_s); +our ($opt_a, $opt_b, $opt_c, $opt_D, $opt_L, $opt_n, $opt_p, $opt_s); my %accounts; # {ano}{type, text}; from pta-accounts(5) my %alist; # {ano}{subname, ''}[]; contains lists of entries -my %cclist; # {cc}{ano}[]; contains lists of entries -my %entry; # {year, month, day, date, id, contra, +my %cclist; # {cc}{ano}[]; contains lists of entries +my %entry; # {year, month, day, date, daynum, id, contra, # amount, rel, old, days, skip, cc, text, sum} -my %prices; # {cc}{year, month, day, date, days, price} -my %profit; # {cc}[]; contains lists of profit entries -my %ptot; # {cc}{profit, percent, capital, pcpa, days} +my %prices; # {cc}{year, month, day, date, daynum, price} +my %profit; # {cc}[]; contains lists of profit entries +my %ptot; # {cc}{profit, percent, capital, pcpa, days} +my $startday; # Initialized by the first journal line. +my $endday = (timegm 0, 0, 0, 31, 11, 99999) / 86400; my %atypes = ( A => 'Assets', @@ -88,6 +90,7 @@ sub translate_type ($) { # but does not handle unrealized profits and losses. sub make_entry (\%$) { my ($entry, $ano) = @_; + return if $entry->{daynum} > $endday; my $sub = $accounts{$ano}{type} =~ /[RX]/ && $entry->{text} =~ s/\((.*?)\) *// ? $1 : ''; my $old = $alist{$ano}{$sub} ? $alist{$ano}{$sub}[-1]{sum} : 0; @@ -144,9 +147,15 @@ sub usage () { # === MAIN PROGRAM ===================================================== -getopts 'abcL:nps' or usage; +getopts 'abcD:L:nps' or usage; $opt_a = $opt_b = $opt_c = $opt_p = $opt_s = 1 unless $opt_a || $opt_b || $opt_c || $opt_n || $opt_p || $opt_s; +if ($opt_D) { + $opt_D =~ /^(?:(\d{4})(\d{2})(\d{2}):)?(?:(\d{4})(\d{2})(\d{2}))?$/ + or die "-D parse error: $opt_D"; + $startday = (timegm 0, 0, 0, $3, $2 - 1, $1) / 86400 if $1; + $endday = (timegm 0, 0, 0, $6, $5 - 1, $4) / 86400 if $4; +} unless ($translations = $translations->{$opt_L || 'en'}) { printf STDERR "unsupported language: -L %s\n", $opt_L; usage; @@ -192,33 +201,36 @@ while (<$in>) { "$entry{contra} split $line"; $amount *= $entry{amount} < 0 ? -1 : +1; - # Combine the text on the split side. - my $newentry = { - %entry, - amount => $amount, - text => "$entry{text} $text", - }; - if ($cc) { - $newentry->{cc} = $cc; - $newentry->{text} = "[$cc] $newentry->{text}"; - } - make_entry %$newentry, $ano; + if ($entry{daynum} <= $endday) { + # Combine the text on the split side. + my $newentry = { + %entry, + amount => $amount, + text => "$entry{text} $text", + }; + if ($cc) { + $newentry->{cc} = $cc; + $newentry->{text} = "[$cc] $newentry->{text}"; + } + make_entry %$newentry, $ano; - # Append split account numbers on the combined side. - my $contra = $entry{contra}; - $alist{$contra}{''}[-1]{text} .= " $ano" - unless $alist{$contra}{''}[-1]{text} =~ / $ano/; + # Append split account numbers on the combined side. + my $contra = $entry{contra}; + $alist{$contra}{''}[-1]{text} .= " $ano" + unless $alist{$contra}{''}[-1]{text} =~ / $ano/; - # If the split side specifies a cost center, - # manually create the cost center entry on the combined - # side because make_entry was only called once there. - if ($cc) { - my $old = $cclist{$cc}{$contra} ? - $cclist{$cc}{$contra}[-1]{sum} : 0; - $newentry->{contra} = $ano; - $newentry->{amount} *= -1; - $newentry->{sum} = $old - $amount; - push @{$cclist{$cc}{$contra}}, $newentry; + # If the split side specifies a cost center, + # manually create the cost center entry + # on the combined side because make_entry() + # was only called once there. + if ($cc) { + my $old = $cclist{$cc}{$contra} ? + $cclist{$cc}{$contra}[-1]{sum} : 0; + $newentry->{contra} = $ano; + $newentry->{amount} *= -1; + $newentry->{sum} = $old - $amount; + push @{$cclist{$cc}{$contra}}, $newentry; + } } # Keep track of the remaining amount. @@ -231,6 +243,8 @@ while (<$in>) { s/^(\d{4})(\d{2})(\d{2}) +// or die "$fn date parse error: $line"; my ($year, $month, $day) = ($1, $2, $3); + my $daynum = (timegm 0, 0, 0, $day, $month-1, $year) / 86400; + $startday //= $daynum; s/^(\S+) +// or die "$fn ID parse error: $line"; my $id = $1; s/^(\d+) +// or die "$fn debit account number parse error: $line"; @@ -258,9 +272,10 @@ while (<$in>) { month => $month, day => $day, date => "$year-$month-$day", - days => (timegm 0,0,0, $day, $month-1, $year) / 86400, + daynum => $daynum, price => $newpc * $amount, }; + next if $new->{daynum} > $endday; $prices{$cc} = $new unless $prices{$cc} && $oldpc == $newpc; next unless $oldpc; @@ -284,7 +299,7 @@ while (<$in>) { if ($old) { # Record a gain or loss in this period. $newprofit->{olddate} = $old->{date}; - $newprofit->{days} = $new->{days} - $old->{days}; + $newprofit->{days} = $new->{daynum} - $old->{daynum}; $newprofit->{text} .= sprintf " %s %s (%dd)", (translate 'since'), $old->{date}, $newprofit->{days}; @@ -314,7 +329,8 @@ while (<$in>) { year => $year, month => $month, day => $day, - date => "$year-$month-$day", + date => "$year-$month-$day", + daynum => (timegm 0, 0, 0, $day, $month - 1, $year) / 86400, id => $id, text => $text, cc => $cc, @@ -540,6 +556,7 @@ for my $cc (sort keys %cclist) { $days += $entry->{days}; $capital += $entry->{old} * $entry->{days}; } + next unless $days; my $entry = { profit => $pr, percent => 100.0 * $pr / $capital * $days, @@ -569,7 +586,7 @@ if ($opt_p && %ptot) { $ptot{$cc}{capital}, $ptot{$cc}{pcpa}, $ptot{$cc}{days}, $cc; $pr += $ptot{$cc}{profit}; - $capital += $ptot{$cc}{capital} * $ptot{$cc}{days} / 360.0; + $capital += $ptot{$cc}{capital} * $ptot{$cc}{days} / 365.245; $maxd = $ptot{$cc}{days} if $maxd < $ptot{$cc}{days}; } printf "%9.2f %5.1f%% of %9.2f %5.1f%% p.a. %3dd %s\n",