home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC World 2000 February
/
PCWorld_2000-02_cd.bin
/
live
/
usr
/
X11R6
/
lib
/
X11
/
cbb
/
contrib
/
recur.pl
< prev
next >
Wrap
Perl Script
|
1998-10-07
|
10KB
|
355 lines
#!/usr/bin/perl
# recur.pl - Manage and update recurring transactions in a .cbb file.
#
# Written by Curtis Olson. Started January 16, 1996.
#
# Copyright (C) 1996 Curtis L. Olson - curt@sledge.mn.org
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# 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., 675 Mass Ave, Cambridge, MA 02139, USA.
#
# $Id: recur.pl,v 2.9 1998/08/14 14:28:44 curt Exp $
# (Log is kept at end of this file)
use strict; # don't take no guff
require "timelocal.pl";
package CBB;
my($key, $date, $check, $desc, $debit, $credit, $cat, $com, $cleared, $total);
my($recur, $result, $update);
my($future_days, $secs_per_day, $cur_date, $account);
# specify the installed location of the necessary pieces.
$CBB::cbb_incl_dir = "/usr/X11R6/lib/X11/cbb";
unshift(@INC, $CBB::cbb_incl_dir);
require "memorized.pl";
require "categories.pl";
require "common.pl";
require "engine.pl";
require "memorized.pl";
($#ARGV >= 0) || die "Usage: $0 account";
# how many days to plan ahead
#$future_days = 366; # approximately 1 year;
$future_days = 92; # approximately 3 months;
$secs_per_day = 86400; # seconds per day;
$cur_date = &raw_date;
$account = shift(@ARGV);
if ( $account !~ /\.cbb$/ ) {
die "Account name must end in '.cbb'\n";
}
(&load_trans($account) eq "ok") || die "Cannot open account: $account";
#-----------------------------------------------------------------------
# Traverse all transactions and perform the following steps on entries with
# $cleared = "?":
#
# 1. If date has passed, change $cleared to "!"
# 2. If date is present or future, delete entry. These entries will be
# reinserted later.
#-----------------------------------------------------------------------
print "Updating/deleting current recurring transactions: ";
$result = &first_trans();
while ( $result ne "none" ) {
($key, $date, $check, $desc, $debit, $credit, $cat, $com, $cleared,
$total) = split(/\t/, $result);
if ( $cleared eq "?" ) {
if ( $date < $cur_date ) {
# set $cleared to "!"
# print "updating - $result\n";
print ".";
$update = "$key\t$date\t$check\t$desc\t$debit\t$credit\t".
"$cat\t$com\t!\t$total";
&update_trans($update);
} else {
# delete
# print "deleting - $result\n";
print ".";
&delete_trans($key);
}
}
$result = &next_trans();
}
print "\n";
#-----------------------------------------------------------------------
# Now add in all future recurring transactions
#-----------------------------------------------------------------------
print "Adding in future recurring transactions: ";
# print "$account - " . &file_root($account) . "\n";
$recur = &file_root($account) . ".rcr"; #
# print "$recur\n"; #
open(RECUR, "<$recur") || die "Cannot open: $recur";
while ( <RECUR> ) {
# print length($_) . " - $_";
if ( m/^#/ || ! m/\t/ ) {
# ignore this line
} else {
# Ok, we found one!
&add_all_recurs($_);
}
}
close(RECUR);
# Finally, save the result
(&save_trans("$account") eq "ok") || die "Cannot save account: $account";
#-----------------------------------------------------------------------
# Supporting Routines
#-----------------------------------------------------------------------
# Add all recuring transactions specified
sub add_all_recurs {
my($line) = @_;
my($days, $months, $years, $desc, $debit, $credit, $com, $cat, $begindate,
$cutoff);
my($date, $dates, $key, $trans, @DATES);
chop($line);
($days, $months, $years, $desc, $debit, $credit, $com, $cat,
$begindate, $cutoff) = split(/\t/, $line);
if ( ($begindate eq "") || ($begindate < $cur_date) ) {
$begindate = $cur_date;
}
if ( $cutoff eq "" ) {
$cutoff = &calc_cutoff();
}
# print "cutoff = $cutoff\n";
if ( ($days < 32) || ($days =~ m/,/) || ($days eq "*") ) {
# type 1 recurring transaction
$dates = &gen_dates_1($days, $months, $years, $begindate, $cutoff);
# print "$dates\n";
} else {
# type 2 recurring transaction
$dates = &gen_dates_2($days, $months, $years, $begindate, $cutoff);
# print "$dates\n";
}
@DATES = split(/,/, $dates);
foreach $date (@DATES) {
print ".";
$trans = "$date\t\t$desc\t$debit\t$credit\t$cat\t$com\t?\t";
if ($cat =~ m/^\[/) {
$key = &create_xfer($trans);
} else {
$key = &create_trans($trans);
}
}
}
print "\n";
# Calculate cutoff date
sub calc_cutoff {
my($csec,$cmin,$chour,$cmday,$cmon,$cyear,$cwday,$cyday,$cisdst) =
localtime(time);
my($cutoff_secs, $today_secs);
# print "calling timelocal with cmon = $cmon\n";
$today_secs = &main'timelocal(0, 0, 0, $cmday, $cmon, $cyear);
$cutoff_secs = $today_secs + ($future_days * $secs_per_day);
($csec,$cmin,$chour,$cmday,$cmon,$cyear,$cwday,$cyday,$cisdst) =
localtime($cutoff_secs);
return ¢ury() . $cyear . &pad($cmon + 1) . &pad($cmday);
}
# Generate a list of type 1 dates
sub gen_dates_1 {
my($days, $months, $years, $begindate, $cutoff) = @_;
my($csec,$cmin,$chour,$cmday,$cmon,$cyear,$cwday,$cyday,$cisdst) =
localtime(time);
my($ldates) = "";
my($day, $month, $year, $tdays, $tmonth, $tyear);
my($this_date, $month_end, $next_month);
my(@DAYS, @MONTHS, @YEARS);
# print "$days - $months - $years\n";
if ( $months eq "*" ) {
$months = "1,2,3,4,5,6,7,8,9,10,11,12";
}
@MONTHS = split(/,/, $months);
if ( $years eq "*" ) {
$years = "$cyear," . ($cyear+1);
}
@YEARS = split(/,/, $years);
foreach $year (@YEARS) {
foreach $month (@MONTHS) {
# print ¢ury() . $year . &pad($month) . "\n";
if ( $month == 12 ) {
$tyear = $year + 1; $tmonth = 1;
} else {
$tyear = $year; $tmonth = $month + 1;
}
# note in perl the months start at 0 ... :(
# print "calling timelocal with tmonth = $tmonth \n";
$next_month = &main'timelocal(0, 0, 0, 1, ($tmonth - 1), $tyear);
# subtract the number of seconds in a day to get the last
# day of the previous month
$month_end = $next_month - $secs_per_day;
($csec,$cmin,$chour,$cmday,$cmon,$cyear,$cwday,$cyday,$cisdst) =
localtime($month_end);
if ( $days eq "*" ) {
$tdays = "1";
$day = 2;
while ( $day <= $cmday ) {
$tdays .= "," . $day;
$day++;
}
} else {
$tdays = $days;
$tdays =~ s/last/$cmday/;
}
# print "$tdays\n";
@DAYS = split(/,/, $tdays);
foreach $day (@DAYS) {
$this_date = ¢ury() . $year . &pad($month) . &pad($day);
if ( ($this_date >= $begindate) && ($this_date <= $cutoff) ) {
# print "$this_date\n";
if ( $ldates eq "" ) {
$ldates = $this_date;
} else {
$ldates .= "," . $this_date;
}
}
}
}
}
return $ldates;
}
# Generate a list of type 2 dates
sub gen_dates_2 {
my($start, $incr, $junk, $begindate, $cutoff) = @_;
my($ldates) = "";
my($csec,$cmin,$chour,$cmday,$cmon,$cyear,$cwday,$cyday,$cisdst);
my($scentury, $syear, $smonth, $sday) =
$start =~ /(\d\d)(\d\d)(\d\d)(\d\d)/;
my($secs, $sincr, $start_secs, $this_date);
# print "$syear - $smonth - $sday\n";
# print "calling timelocal with smonth = $smonth\n";
$start_secs = &main'timelocal(0, 0, 0, $sday, ($smonth - 1), $syear);
$sincr = $incr * $secs_per_day;
$secs = $start_secs;
($csec,$cmin,$chour,$cmday,$cmon,$cyear,$cwday,$cyday,$cisdst) =
localtime($secs);
$this_date = ¢ury() . $cyear . &pad($cmon + 1) . &pad($cmday);
while ( $this_date <= $cutoff ) {
if ( $this_date >= $begindate ) {
if ( $ldates eq "" ) {
$ldates = $this_date;
} else {
$ldates .= "," . $this_date;
}
# print "$this_date\n";
}
$secs += $sincr;
($csec,$cmin,$chour,$cmday,$cmon,$cyear,$cwday,$cyday,$cisdst) =
localtime($secs);
$this_date = ¢ury() . $cyear . &pad($cmon + 1) . &pad($cmday);
}
return $ldates;
}
#----------------------------------------------------------------------------
# $Log: recur.pl,v $
# Revision 2.9 1998/08/14 14:28:44 curt
# Added desc-pie graph.
# Added option to eliminate splash screen.
# Other misc. tweaks and bug fixes.
#
# Revision 2.8 1997/02/28 21:21:58 curt
# Fixed some problems introduced by using "use strict"
#
# Revision 2.7 1997/02/19 18:09:09 curt
# Fixed some residual oversites from switching to "use strict".
#
# Revision 2.6 1997/01/18 17:26:39 curt
# Added "use strict" pragma to enforce good scoping habits.
#
# Revision 2.5 1996/10/03 04:49:08 curt
# Fixed an inconsistency in &raw_date() in common.pl (with how it was
# called.)
#
# Version now is 0.67-beta-x
#
# Revision 2.4 1996/10/03 03:53:42 curt
# CBB now determines the current century automatically ... no need for it
# to be hard coded. Removed all hardcoded instances of the century (especially
# in reports.pl and recur.pl)
#
# Added an optional --debug flag to the invocation of CBB.
#
# Revision 2.3 1996/09/17 19:41:10 curt
# Add support for recurring transfer transactions.
#
# Revision 2.2 1996/07/13 02:58:24 curt
# Misc. changes.
#
# Revision 2.1 1996/02/27 05:36:04 curt
# Just stumbling around a bit with cvs ... :-(
#
# Revision 2.0 1996/02/27 04:43:14 curt
# Initial 2.0 revision. (See "Log" files for old history.)