diff options
Diffstat (limited to 'contrib')
-rwxr-xr-x | contrib/non-profit-audit-reports/bank-reconcilation.plx | 122 |
1 files changed, 122 insertions, 0 deletions
diff --git a/contrib/non-profit-audit-reports/bank-reconcilation.plx b/contrib/non-profit-audit-reports/bank-reconcilation.plx new file mode 100755 index 00000000..7201ef1f --- /dev/null +++ b/contrib/non-profit-audit-reports/bank-reconcilation.plx @@ -0,0 +1,122 @@ +#!/usr/bin/perl + +use strict; +use warnings; + +use Math::BigFloat; +use Date::Manip; + +Math::BigFloat->precision(-2); +my $ZERO = Math::BigFloat->new("0.00"); + +my $VERBOSE = 0; +my $DEBUG = 0; + +my $LEDGER_BIN = "/usr/local/bin/ledger"; + +###################################################################### +sub SubSetSumSolver ($$$) { + my($numberList, $totalSought, $extractNumber) = @_; + + my($P, $N) = (0, 0); + foreach my $ii (@{$numberList}) { + if ($ii < $ZERO) { + $N += $ii; + } else { + $P += $ii; + } + } + my $size = scalar(@{$numberList}); + my %Q; + my(@L) = + map { { val => &$extractNumber($_), obj => $_ } } @{$numberList}; + + for (my $ii = 0 ; $ii <= $size ; $ii++ ) { + $Q{$ii}{0}{value} = 1; + $Q{$ii}{0}{list} = []; + } + for (my $jj = $N; $jj <= $P ; $jj++) { + $Q{0}{$jj}{value} = ($L[0]{val} == $jj); + $Q{0}{$jj}{list} = $Q{0}{$jj}{value} ? [ $L[0]{obj} ] : []; + } + for (my $ii = 1; $ii <= $size ; $ii++ ) { + for (my $jj = $N; $jj <= $P ; $jj++) { + if ($Q{$ii-1}{$jj}{value}) { + $Q{$ii}{$jj}{value} = 1; + + $Q{$ii}{$jj}{list} = [] unless defined $Q{$ii}{$jj}{list}; + push(@{$Q{$ii}{$jj}{list}}, @{$Q{$ii-1}{$jj}{list}}); + + } elsif ($L[$ii]{val} == $jj) { + $Q{$ii}{$jj}{value} = 1; + + $Q{$ii}{$jj}{list} = [] unless defined $Q{$ii}{$jj}{list}; + push(@{$Q{$ii}{$jj}{list}}, $jj); + } elsif ($Q{$ii-1}{$jj - $L[$ii]{val}}{value}) { + $Q{$ii}{$jj}{value} = 1; + $Q{$ii}{$jj}{list} = [] unless defined $Q{$ii}{$jj}{list}; + push(@{$Q{$ii}{$jj}{list}}, $L[$ii]{obj}, @{$Q{$ii-1}{$jj - $L[$ii]{val}}{list}}); + } else { + $Q{$ii}{$jj}{value} = 0; + $Q{$ii}{$jj}{list} = []; + } + } + } + foreach (my $ii = 0; $ii <= $size; $ii++) { + foreach (my $jj = $N; $jj <= $P; $jj++) { + print "Q($ii, $jj) == $Q{$ii}{$jj}{value} with List of ", join(", ", @{$Q{$ii}{$jj}{list}}), "\n"; + } + } + return [ $Q{$size}{$totalSought}{value}, \@{$Q{$size}{$totalSought}{list}}]; +} +###################################################################### +sub Commify ($) { + my $text = reverse $_[0]; + $text =~ s/(\d\d\d)(?=\d)(?!\d*\.)/$1,/g; + return scalar reverse $text; +} +###################################################################### +sub ParseNumber($) { + $_[0] =~ s/,//g; + return Math::BigFloat->new($_[0]); +} +if (@ARGV < 4) { + print STDERR "usage: $0 <ACCOUNT_REGEX> <END_DATE> <BANK_STATEMENT_BALANCE> <LEDGER_OPTIONS>\n"; + exit 1; +} +###################################################################### +my($account, $endDate, $balanceSought, @mainLedgerOptions) = @ARGV; + +$balanceSought = ParseNumber($balanceSought); + +my $err; +my $startDate = UnixDate(DateCalc(ParseDate($endDate), ParseDateDelta("- 1 month"), \$err), "%Y/%m/%d"); +die "Date calculation error on $endDate" if ($err); + +my(@fullCommand) = ($LEDGER_BIN, @mainLedgerOptions, '-V', '-X', '$', + '-b', $startDate, '-e', $endDate, + '-F', '"%(date)","%C","%P","%t"\n', + 'reg', "/$account/"); + + open(FILE, "-|", @fullCommand) + or die "unable to run command ledger command: @fullCommand: $!"; + +my @entries; + +foreach my $line (<FILE>) { + die "Unable to parse output line from: $line" + unless $line =~ /^\s*"([^"]*)","([^"]*)","([^"]*)","([^"]*)"\s*$/; + my($date, $checkNum, $payee, $amount) = ($1, $2, $3, $4); + die "$amount is not a valid amount" + unless $amount =~ s/\s*\$\s*([\-\d\.\,]+)\s*$/$1/; + $amount = ParseNumber($amount); + + print "$date, $checkNum, $payee, $amount\n"; + push(@entries, { date => $date, checkNum => $checkNum, amount => $amount }); +} + +############################################################################### +# +# Local variables: +# compile-command: "perl -c bank-reconcilation.plx" +# End: |