package Zephir::Dues; use strict; use Zephir; ## vars for testing## my $setup = 161.29; ############### my $rate = [ ['01/01/1990', '09/01/2003', 105], ['08/01/2003', '10/01/2003', 190], ['10/01/2003', '01/01/2007', 140], ]; sub notify { if(not Zephir::authorize('Administrator')){ return Zephir::boxit("Not Authorized","Error"); } my @users = split(',', $Z::r{usernames}); for(@users){ my %hash = Zephir::userdata($_); $hash{username} = $_; $_ = \%hash; } my $out = Zephir::tmpl( template => 'Dues_notify', users => \@users, ); return Zephir::boxit($out,"Results"); } sub notify_email { if(not Zephir::authorize('Administrator')){ return Zephir::boxit("Not Authorized","Error"); } my @users = split(',',$Z::r{emails}); my $email = Zephir::tmpl(template => 'Dues_email'); my ($subject,$body) = $email =~ /^(.*?)[\n\r\f](.*)$/s; for(@users){ Zephir::email( to=>$_, from=>'myemail@alsdkfj.com', body=>$body, subject=>$subject, ); } print "Location: http://$Z::var{HOSTNAME}$Z::var{Z_URL}?lib=Dues&action=admin\n\n"; return; } sub admin { if(not Zephir::authorize('Administrator')){ return Zephir::boxit("Not Authorized","Error"); } add_membership() if(defined $Z::r{usernames}); add_payment() if(defined $Z::r{payment}); my $info = $Z::var{DB}->selectcol_arrayref('SELECT name FROM dues'); my %temp; @temp{@$info} = (); delete $temp{''}; @$info = keys %temp; my ($total_payments, $total_debt, $balance, @users); $Z::r{show} ||= 'all'; $Z::r{show_other} = 'all'; $Z::r{show_other} = 'current' if($Z::r{show} eq 'all'); for(@$info){ my $temp = get_data($_); next unless defined $temp; $total_payments += $temp->{total_payments}; $total_debt += $temp->{total_debt}; $balance += $temp->{balance}; next if($Z::r{show} eq 'current' and not defined $temp->{current}); push @users, ($temp); } @users = sort { $a->{balance} <=> $b->{balance} } @users; my $hash_ref = load_edit_jid() if(defined $Z::r{jid}); $hash_ref = load_edit_pid() if(defined $Z::r{pid}); $hash_ref->{tjoin} = dates($hash_ref->{tjoin}, 'tjoin'); $hash_ref->{tquit} = dates($hash_ref->{tquit}, 'tquit'); my $select_names = Zephir::select_box( name => 'name', 'values' => [keys %temp], selected => $hash_ref->{name} || '', ); my $out = Zephir::tmpl( template => 'Dues_admin', rows => \@users, total_payments => cash($total_payments), total_debt => cash($total_debt), balance => cash($balance), select_names => $select_names, %Z::r, %$hash_ref, ); return $out; return Zephir::template( title => 'WHA dues administration', body_loop => $out, ); } sub dates { my ($date, $name) = @_; my ($mm,$dd,$yy) = split('/', $date || ''); my @m_labels = ('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'); my $month = Zephir::select_box( name => "month_$name", 'values' => [(1..12)], labels => \@m_labels, selected => $mm||'', ); my $day = Zephir::select_box( name => "day_$name", 'values' => [(1..31)], selected => $dd||'', ); my $year = Zephir::select_box( name => "year_$name", 'values' => [(1995..2010)], selected => $yy||'', ); return "$month$day$year"; } sub load_edit_jid { return $Z::var{DB}->selectrow_hashref( 'SELECT * FROM dues WHERE id=?', undef, $Z::r{jid}); } sub load_edit_pid { return $Z::var{DB}->selectrow_hashref( 'SELECT * FROM dues WHERE id=?', undef, $Z::r{pid}); } sub add_membership { if(not Zephir::authorize('Administrator')){ return Zephir::boxit("Not Authorized","Error"); } $Z::r{tjoin} = "$Z::r{month_tjoin}/$Z::r{day_tjoin}/$Z::r{year_tjoin}"; $Z::r{tquit} = "$Z::r{month_tquit}/$Z::r{day_tquit}/$Z::r{year_tquit}"; if(defined $Z::r{delete}){ $Z::var{DB}->do('DELETE FROM dues WHERE id=?', undef, $Z::r{id}); } elsif($Z::r{id} ne ''){ $Z::var{DB}->do('UPDATE dues SET usernames=?,tjoin=?,tquit=?,shares=? WHERE id=? and name=?' ,undef, $Z::r{usernames}, $Z::r{tjoin}, $Z::r{tquit}, $Z::r{shares}, $Z::r{id}, $Z::r{name} ) if($Z::r{usernames} ne '' and $Z::r{name} ne '' and $Z::r{shares} ne ''); } else{ $Z::var{DB}->do('INSERT INTO dues (usernames,name,tjoin,tquit,shares) VALUES(?,?,?,?,?)' ,undef, $Z::r{usernames}, $Z::r{name}, $Z::r{tjoin}, $Z::r{tquit}, $Z::r{shares}, ) if($Z::r{usernames} ne '' and $Z::r{name} ne '' and $Z::r{shares} ne ''); } } sub add_payment { if(not Zephir::authorize('Administrator')){ return Zephir::boxit("Not Authorized","Error"); } $Z::r{tjoin} = "$Z::r{month_tjoin}/$Z::r{day_tjoin}/$Z::r{year_tjoin}"; if(defined $Z::r{delete}){ $Z::var{DB}->do('DELETE FROM dues WHERE id=?', undef, $Z::r{id}); } elsif($Z::r{id} ne ''){ $Z::var{DB}->do('UPDATE dues SET tjoin=?,payment=? WHERE id=? and name=?' ,undef, $Z::r{tjoin}, $Z::r{payment}, $Z::r{id}, $Z::r{name} ) if($Z::r{tjoin} ne '' and $Z::r{payment} ne ''); } else{ $Z::var{DB}->do('INSERT INTO dues (name,tjoin,payment) VALUES(?,?,?)' ,undef, $Z::r{name}, $Z::r{tjoin}, $Z::r{payment}, ) if($Z::r{name} ne '' and $Z::r{tjoin} ne '' and $Z::r{payment} ne ''); } } sub get_data { my ($name,$tmpl) = @_; # usernames is a list like ',username,' or ',user1,user2,user3,' my $info = $Z::var{DB}->selectall_arrayref( 'SELECT usernames,tjoin,tquit,shares,id FROM dues WHERE name=? AND length(usernames)' ,undef, $name); my $usernames = $info->[0]->[0]; #join is time in this context my $payments = $Z::var{DB}->selectall_arrayref( 'SELECT tjoin,payment,id FROM dues WHERE name=? AND payment>0' ,undef, $name); my $total_debt = 0; my (@values, $total_members, $current); for(@$info){ my (undef, $join, $quit, $shares, $id) = @$_; my ($m1,$d1,$y1) = split('/', $join); my ($m2,$d2,$y2) = split('/', $quit); my $t1 = Date_to_Time($m1,$d1,$y1); my $t2 = Date_to_Time($m2,$d2,$y2); my $ttime = $t2-$t1; if($ttime < 0){ $t2 = time(); $ttime = $t2 - $t1; $quit = $current = "current"; } for(@$rate){ my ($d1, $d2, $rate) = @$_; my $rt1 = Date_to_Time(split('/', $d1)); my $rt2 = Date_to_Time(split('/', $d2)); (my $other_share_hours, $total_members) = total_share_hours($t1, $t2); my $hours = intersect($rt1, $rt2, $t1, $t2) / 3600; my $debt = ($hours**2) / $other_share_hours * $shares * $rate * 12 / 365.24 / 24; $total_debt += $debt; } $_ = "$shares shares: $join-$quit"; push @values, $id; } $total_debt += $setup / ($total_members || 0.001); $info = Zephir::select_box( name=>'jid','values' => \@values, labels => $info ); my $total_payments = 0; undef @values; for(@$payments){ my ($time, $payment, $id) = @$_; $total_payments += $payment; $payment = cash($payment); $_ = "\$$payment ($time)"; push @values, $id; } $payments = Zephir::select_box( name => 'pid', 'values' => \@values, labels => $payments ); my $balance = $total_payments - $total_debt; $name =~ s/ / /gs; my %out = ( usernames => $usernames, name => $name, info => $info, payments => $payments, total_payments => cash($total_payments), total_debt => cash($total_debt), balance => cash($balance), current => $current, ); return \%out; } sub cash { my $cash = shift; $cash = int($cash*100)/100; $cash = sprintf("%1.2f",$cash); return $cash; } sub gtime { my $time = shift; $time = Zephir::ztime($time); $time =~ s/^(.*?) .*$/$1/; return $time } sub main { my ($name); my $un = $Z::a{username} || ')&^#$)*#$^'; # usernames is a list like 'username' or 'user1,user2,user3' my $info = $Z::var{DB}->selectall_arrayref( 'SELECT usernames,name FROM dues WHERE LENGTH(usernames)' ); for(@$info){ if($_->[0] =~ /[,\W]*\Q$un\E[,\W]*/){ $name = $_->[1]; } } if(not defined $name){ return Zephir::boxit("You don't appear to be registered as a WHA member under this username.","Error"); } $info = get_data($name,"Dues_user"); ($info->{rate}) = total_share_hours(time - 3600*24*30,time); $info->{rate} = $rate->[-1]->[2] * 24 * 30 / $info->{rate}; $info->{rate} = cash($info->{rate}); # use total_share_hours to find rate for last month my $out = Zephir::tmpl(%$info); return Zephir::template( title => 'WHA dues', body_loop => $out, ); } sub intersect { my ($a,$b,$c,$d) = @_; my ($n1,$n2) = ([$a,$b],[$c,$d]); if($a > $c){ my $t = $n1; $n1 = $n2; $n2 = $t; } return (($n1->[1]-$n2->[0])*($n1->[1]>$n2->[0])) - (($n1->[1]-$n2->[1])*($n1->[1]>$n2->[1])); } my $tsh; sub total_share_hours { my ($join, $quit) = @_; if(not defined $tsh){ $tsh = $Z::var{DB}->selectall_arrayref( 'SELECT tjoin,tquit,shares,name FROM dues'); for(@$tsh){ my ($j,$q,$s,$n) = @$_; next unless $s; my ($m1,$d1,$y1) = split('/', $j); my ($m2,$d2,$y2) = split('/', $q); $j = Date_to_Time($m1,$d1,$y1); $q = Date_to_Time($m2,$d2,$y2); $q = time if($q < $j); $_ = [$j,$q,$s,$n]; } } my $total = 0; my (%members,$tm); for(@$tsh){ my ($j,$q,$s,$n) = @$_; next unless $s; $tm++ if(not defined $members{$n}); $members{$n} = 1; my $hours = intersect($join,$quit,$j,$q); $total += $s * $hours / 3600; } return ($total, $tm); } sub Date_to_Time { my ($MM, $DD, $YYYY) = @_; my $maxtime = time + 3600*24*365; --$MM; my ($mm,$dd,$yy); my $guess = ($YYYY - 1969 - 1)*3600*24*365*($YYYY > 1969); while($guess < $maxtime){ $guess += 3600*24; ($mm,$dd,$yy) = (localtime($guess))[4,3,5]; $guess += ($MM - $mm - 1)*30*24*3600*($MM > $mm); next unless $mm == $MM; next unless $dd == $DD; $yy += 1900; next unless $yy == $YYYY; last; } return $guess; } 1;